diff options
author | Jeff Garzik <jgarzik@pretzel.yyz.us> | 2005-06-27 22:03:52 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-27 22:03:52 -0400 |
commit | 716b43303df605510399d6da0d0dd4e2ea376e7c (patch) | |
tree | 57412aaf516b7a10b4b81064aeda318514fec168 | |
parent | 5696c1944a33b4434a9a1ebb6383b906afd43a10 (diff) | |
parent | c7b645f934e52a54af58142d91fb51f881f8ce26 (diff) |
Merge upstream ieee80211.h with us (us == branch 'ieee80211' of netdev-2.6)
318 files changed, 18247 insertions, 13845 deletions
diff --git a/Documentation/block/ioprio.txt b/Documentation/block/ioprio.txt new file mode 100644 index 000000000000..96ccf681075e --- /dev/null +++ b/Documentation/block/ioprio.txt | |||
@@ -0,0 +1,176 @@ | |||
1 | Block io priorities | ||
2 | =================== | ||
3 | |||
4 | |||
5 | Intro | ||
6 | ----- | ||
7 | |||
8 | With the introduction of cfq v3 (aka cfq-ts or time sliced cfq), basic io | ||
9 | priorities is supported for reads on files. This enables users to io nice | ||
10 | processes or process groups, similar to what has been possible to cpu | ||
11 | scheduling for ages. This document mainly details the current possibilites | ||
12 | with cfq, other io schedulers do not support io priorities so far. | ||
13 | |||
14 | Scheduling classes | ||
15 | ------------------ | ||
16 | |||
17 | CFQ implements three generic scheduling classes that determine how io is | ||
18 | served for a process. | ||
19 | |||
20 | IOPRIO_CLASS_RT: This is the realtime io class. This scheduling class is given | ||
21 | higher priority than any other in the system, processes from this class are | ||
22 | given first access to the disk every time. Thus it needs to be used with some | ||
23 | care, one io RT process can starve the entire system. Within the RT class, | ||
24 | there are 8 levels of class data that determine exactly how much time this | ||
25 | process needs the disk for on each service. In the future this might change | ||
26 | to be more directly mappable to performance, by passing in a wanted data | ||
27 | rate instead. | ||
28 | |||
29 | IOPRIO_CLASS_BE: This is the best-effort scheduling class, which is the default | ||
30 | for any process that hasn't set a specific io priority. The class data | ||
31 | determines how much io bandwidth the process will get, it's directly mappable | ||
32 | to the cpu nice levels just more coarsely implemented. 0 is the highest | ||
33 | BE prio level, 7 is the lowest. The mapping between cpu nice level and io | ||
34 | nice level is determined as: io_nice = (cpu_nice + 20) / 5. | ||
35 | |||
36 | IOPRIO_CLASS_IDLE: This is the idle scheduling class, processes running at this | ||
37 | level only get io time when no one else needs the disk. The idle class has no | ||
38 | class data, since it doesn't really apply here. | ||
39 | |||
40 | Tools | ||
41 | ----- | ||
42 | |||
43 | See below for a sample ionice tool. Usage: | ||
44 | |||
45 | # ionice -c<class> -n<level> -p<pid> | ||
46 | |||
47 | If pid isn't given, the current process is assumed. IO priority settings | ||
48 | are inherited on fork, so you can use ionice to start the process at a given | ||
49 | level: | ||
50 | |||
51 | # ionice -c2 -n0 /bin/ls | ||
52 | |||
53 | will run ls at the best-effort scheduling class at the highest priority. | ||
54 | For a running process, you can give the pid instead: | ||
55 | |||
56 | # ionice -c1 -n2 -p100 | ||
57 | |||
58 | will change pid 100 to run at the realtime scheduling class, at priority 2. | ||
59 | |||
60 | ---> snip ionice.c tool <--- | ||
61 | |||
62 | #include <stdio.h> | ||
63 | #include <stdlib.h> | ||
64 | #include <errno.h> | ||
65 | #include <getopt.h> | ||
66 | #include <unistd.h> | ||
67 | #include <sys/ptrace.h> | ||
68 | #include <asm/unistd.h> | ||
69 | |||
70 | extern int sys_ioprio_set(int, int, int); | ||
71 | extern int sys_ioprio_get(int, int); | ||
72 | |||
73 | #if defined(__i386__) | ||
74 | #define __NR_ioprio_set 289 | ||
75 | #define __NR_ioprio_get 290 | ||
76 | #elif defined(__ppc__) | ||
77 | #define __NR_ioprio_set 273 | ||
78 | #define __NR_ioprio_get 274 | ||
79 | #elif defined(__x86_64__) | ||
80 | #define __NR_ioprio_set 251 | ||
81 | #define __NR_ioprio_get 252 | ||
82 | #elif defined(__ia64__) | ||
83 | #define __NR_ioprio_set 1274 | ||
84 | #define __NR_ioprio_get 1275 | ||
85 | #else | ||
86 | #error "Unsupported arch" | ||
87 | #endif | ||
88 | |||
89 | _syscall3(int, ioprio_set, int, which, int, who, int, ioprio); | ||
90 | _syscall2(int, ioprio_get, int, which, int, who); | ||
91 | |||
92 | enum { | ||
93 | IOPRIO_CLASS_NONE, | ||
94 | IOPRIO_CLASS_RT, | ||
95 | IOPRIO_CLASS_BE, | ||
96 | IOPRIO_CLASS_IDLE, | ||
97 | }; | ||
98 | |||
99 | enum { | ||
100 | IOPRIO_WHO_PROCESS = 1, | ||
101 | IOPRIO_WHO_PGRP, | ||
102 | IOPRIO_WHO_USER, | ||
103 | }; | ||
104 | |||
105 | #define IOPRIO_CLASS_SHIFT 13 | ||
106 | |||
107 | const char *to_prio[] = { "none", "realtime", "best-effort", "idle", }; | ||
108 | |||
109 | int main(int argc, char *argv[]) | ||
110 | { | ||
111 | int ioprio = 4, set = 0, ioprio_class = IOPRIO_CLASS_BE; | ||
112 | int c, pid = 0; | ||
113 | |||
114 | while ((c = getopt(argc, argv, "+n:c:p:")) != EOF) { | ||
115 | switch (c) { | ||
116 | case 'n': | ||
117 | ioprio = strtol(optarg, NULL, 10); | ||
118 | set = 1; | ||
119 | break; | ||
120 | case 'c': | ||
121 | ioprio_class = strtol(optarg, NULL, 10); | ||
122 | set = 1; | ||
123 | break; | ||
124 | case 'p': | ||
125 | pid = strtol(optarg, NULL, 10); | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | switch (ioprio_class) { | ||
131 | case IOPRIO_CLASS_NONE: | ||
132 | ioprio_class = IOPRIO_CLASS_BE; | ||
133 | break; | ||
134 | case IOPRIO_CLASS_RT: | ||
135 | case IOPRIO_CLASS_BE: | ||
136 | break; | ||
137 | case IOPRIO_CLASS_IDLE: | ||
138 | ioprio = 7; | ||
139 | break; | ||
140 | default: | ||
141 | printf("bad prio class %d\n", ioprio_class); | ||
142 | return 1; | ||
143 | } | ||
144 | |||
145 | if (!set) { | ||
146 | if (!pid && argv[optind]) | ||
147 | pid = strtol(argv[optind], NULL, 10); | ||
148 | |||
149 | ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid); | ||
150 | |||
151 | printf("pid=%d, %d\n", pid, ioprio); | ||
152 | |||
153 | if (ioprio == -1) | ||
154 | perror("ioprio_get"); | ||
155 | else { | ||
156 | ioprio_class = ioprio >> IOPRIO_CLASS_SHIFT; | ||
157 | ioprio = ioprio & 0xff; | ||
158 | printf("%s: prio %d\n", to_prio[ioprio_class], ioprio); | ||
159 | } | ||
160 | } else { | ||
161 | if (ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio | ioprio_class << IOPRIO_CLASS_SHIFT) == -1) { | ||
162 | perror("ioprio_set"); | ||
163 | return 1; | ||
164 | } | ||
165 | |||
166 | if (argv[optind]) | ||
167 | execvp(argv[optind], &argv[optind]); | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | ---> snip ionice.c tool <--- | ||
174 | |||
175 | |||
176 | March 11 2005, Jens Axboe <axboe@suse.de> | ||
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt index d599beb9df8a..c8f9a73111da 100644 --- a/Documentation/cciss.txt +++ b/Documentation/cciss.txt | |||
@@ -17,6 +17,7 @@ This driver is known to work with the following cards: | |||
17 | * SA P600 | 17 | * SA P600 |
18 | * SA P800 | 18 | * SA P800 |
19 | * SA E400 | 19 | * SA E400 |
20 | * SA E300 | ||
20 | 21 | ||
21 | If nodes are not already created in the /dev/cciss directory, run as root: | 22 | If nodes are not already created in the /dev/cciss directory, run as root: |
22 | 23 | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index f44bb5567c5b..89cd417651e0 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1115,7 +1115,7 @@ running once the system is up. | |||
1115 | See Documentation/ramdisk.txt. | 1115 | See Documentation/ramdisk.txt. |
1116 | 1116 | ||
1117 | psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to | 1117 | psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to |
1118 | probe for (bare|imps|exps). | 1118 | probe for (bare|imps|exps|lifebook|any). |
1119 | psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports | 1119 | psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports |
1120 | per second. | 1120 | per second. |
1121 | psmouse.resetafter= | 1121 | psmouse.resetafter= |
diff --git a/MAINTAINERS b/MAINTAINERS index a0b0d595d17c..4db63de9652a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1149,7 +1149,7 @@ S: Maintained | |||
1149 | 1149 | ||
1150 | INFINIBAND SUBSYSTEM | 1150 | INFINIBAND SUBSYSTEM |
1151 | P: Roland Dreier | 1151 | P: Roland Dreier |
1152 | M: roland@topspin.com | 1152 | M: rolandd@cisco.com |
1153 | P: Sean Hefty | 1153 | P: Sean Hefty |
1154 | M: mshefty@ichips.intel.com | 1154 | M: mshefty@ichips.intel.com |
1155 | P: Hal Rosenstock | 1155 | P: Hal Rosenstock |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 8f146a4b4752..bbea636ff687 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/leds.h> | 32 | #include <asm/leds.h> |
33 | #include <asm/processor.h> | 33 | #include <asm/processor.h> |
34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
35 | #include <asm/mach/time.h> | ||
35 | 36 | ||
36 | extern const char *processor_modes[]; | 37 | extern const char *processor_modes[]; |
37 | extern void setup_mm_for_reboot(char mode); | 38 | extern void setup_mm_for_reboot(char mode); |
@@ -85,8 +86,10 @@ EXPORT_SYMBOL(pm_power_off); | |||
85 | void default_idle(void) | 86 | void default_idle(void) |
86 | { | 87 | { |
87 | local_irq_disable(); | 88 | local_irq_disable(); |
88 | if (!need_resched() && !hlt_counter) | 89 | if (!need_resched() && !hlt_counter) { |
90 | timer_dyn_reprogram(); | ||
89 | arch_idle(); | 91 | arch_idle(); |
92 | } | ||
90 | local_irq_enable(); | 93 | local_irq_enable(); |
91 | } | 94 | } |
92 | 95 | ||
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 06054c9ba074..1b7fcd50c3e2 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c | |||
@@ -424,15 +424,19 @@ static int timer_dyn_tick_disable(void) | |||
424 | return ret; | 424 | return ret; |
425 | } | 425 | } |
426 | 426 | ||
427 | /* | ||
428 | * Reprogram the system timer for at least the calculated time interval. | ||
429 | * This function should be called from the idle thread with IRQs disabled, | ||
430 | * immediately before sleeping. | ||
431 | */ | ||
427 | void timer_dyn_reprogram(void) | 432 | void timer_dyn_reprogram(void) |
428 | { | 433 | { |
429 | struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; | 434 | struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; |
430 | unsigned long flags; | ||
431 | 435 | ||
432 | write_seqlock_irqsave(&xtime_lock, flags); | 436 | write_seqlock(&xtime_lock); |
433 | if (dyn_tick->state & DYN_TICK_ENABLED) | 437 | if (dyn_tick->state & DYN_TICK_ENABLED) |
434 | dyn_tick->reprogram(next_timer_interrupt() - jiffies); | 438 | dyn_tick->reprogram(next_timer_interrupt() - jiffies); |
435 | write_sequnlock_irqrestore(&xtime_lock, flags); | 439 | write_sequnlock(&xtime_lock); |
436 | } | 440 | } |
437 | 441 | ||
438 | static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) | 442 | static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) |
diff --git a/arch/arm/mach-aaec2000/Makefile.boot b/arch/arm/mach-aaec2000/Makefile.boot new file mode 100644 index 000000000000..8f5a8b7c53c7 --- /dev/null +++ b/arch/arm/mach-aaec2000/Makefile.boot | |||
@@ -0,0 +1 @@ | |||
zreladdr-y := 0xf0008000 | |||
diff --git a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c index 6e805d451d0e..7f37857b1a28 100644 --- a/arch/arm/mach-omap/usb.c +++ b/arch/arm/mach-omap/usb.c | |||
@@ -288,8 +288,8 @@ static void usb_release(struct device *dev) | |||
288 | static struct resource udc_resources[] = { | 288 | static struct resource udc_resources[] = { |
289 | /* order is significant! */ | 289 | /* order is significant! */ |
290 | { /* registers */ | 290 | { /* registers */ |
291 | .start = IO_ADDRESS(UDC_BASE), | 291 | .start = UDC_BASE, |
292 | .end = IO_ADDRESS(UDC_BASE + 0xff), | 292 | .end = UDC_BASE + 0xff, |
293 | .flags = IORESOURCE_MEM, | 293 | .flags = IORESOURCE_MEM, |
294 | }, { /* general IRQ */ | 294 | }, { /* general IRQ */ |
295 | .start = IH2_BASE + 20, | 295 | .start = IH2_BASE + 20, |
@@ -355,8 +355,8 @@ static struct platform_device ohci_device = { | |||
355 | static struct resource otg_resources[] = { | 355 | static struct resource otg_resources[] = { |
356 | /* order is significant! */ | 356 | /* order is significant! */ |
357 | { | 357 | { |
358 | .start = IO_ADDRESS(OTG_BASE), | 358 | .start = OTG_BASE, |
359 | .end = IO_ADDRESS(OTG_BASE + 0xff), | 359 | .end = OTG_BASE + 0xff, |
360 | .flags = IORESOURCE_MEM, | 360 | .flags = IORESOURCE_MEM, |
361 | }, { | 361 | }, { |
362 | .start = IH2_BASE + 8, | 362 | .start = IH2_BASE + 8, |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index c08710b1ff02..6dcb23d64bf5 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -522,6 +522,69 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s) | |||
522 | printk(KERN_INFO "Freeing %s memory: %dK\n", s, size); | 522 | printk(KERN_INFO "Freeing %s memory: %dK\n", s, size); |
523 | } | 523 | } |
524 | 524 | ||
525 | static inline void | ||
526 | free_memmap(int node, unsigned long start_pfn, unsigned long end_pfn) | ||
527 | { | ||
528 | struct page *start_pg, *end_pg; | ||
529 | unsigned long pg, pgend; | ||
530 | |||
531 | /* | ||
532 | * Convert start_pfn/end_pfn to a struct page pointer. | ||
533 | */ | ||
534 | start_pg = pfn_to_page(start_pfn); | ||
535 | end_pg = pfn_to_page(end_pfn); | ||
536 | |||
537 | /* | ||
538 | * Convert to physical addresses, and | ||
539 | * round start upwards and end downwards. | ||
540 | */ | ||
541 | pg = PAGE_ALIGN(__pa(start_pg)); | ||
542 | pgend = __pa(end_pg) & PAGE_MASK; | ||
543 | |||
544 | /* | ||
545 | * If there are free pages between these, | ||
546 | * free the section of the memmap array. | ||
547 | */ | ||
548 | if (pg < pgend) | ||
549 | free_bootmem_node(NODE_DATA(node), pg, pgend - pg); | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | * The mem_map array can get very big. Free the unused area of the memory map. | ||
554 | */ | ||
555 | static void __init free_unused_memmap_node(int node, struct meminfo *mi) | ||
556 | { | ||
557 | unsigned long bank_start, prev_bank_end = 0; | ||
558 | unsigned int i; | ||
559 | |||
560 | /* | ||
561 | * [FIXME] This relies on each bank being in address order. This | ||
562 | * may not be the case, especially if the user has provided the | ||
563 | * information on the command line. | ||
564 | */ | ||
565 | for (i = 0; i < mi->nr_banks; i++) { | ||
566 | if (mi->bank[i].size == 0 || mi->bank[i].node != node) | ||
567 | continue; | ||
568 | |||
569 | bank_start = mi->bank[i].start >> PAGE_SHIFT; | ||
570 | if (bank_start < prev_bank_end) { | ||
571 | printk(KERN_ERR "MEM: unordered memory banks. " | ||
572 | "Not freeing memmap.\n"); | ||
573 | break; | ||
574 | } | ||
575 | |||
576 | /* | ||
577 | * If we had a previous bank, and there is a space | ||
578 | * between the current bank and the previous, free it. | ||
579 | */ | ||
580 | if (prev_bank_end && prev_bank_end != bank_start) | ||
581 | free_memmap(node, prev_bank_end, bank_start); | ||
582 | |||
583 | prev_bank_end = (mi->bank[i].start + | ||
584 | mi->bank[i].size) >> PAGE_SHIFT; | ||
585 | } | ||
586 | } | ||
587 | |||
525 | /* | 588 | /* |
526 | * mem_init() marks the free areas in the mem_map and tells us how much | 589 | * mem_init() marks the free areas in the mem_map and tells us how much |
527 | * memory is free. This is done after various parts of the system have | 590 | * memory is free. This is done after various parts of the system have |
@@ -540,16 +603,12 @@ void __init mem_init(void) | |||
540 | max_mapnr = virt_to_page(high_memory) - mem_map; | 603 | max_mapnr = virt_to_page(high_memory) - mem_map; |
541 | #endif | 604 | #endif |
542 | 605 | ||
543 | /* | ||
544 | * We may have non-contiguous memory. | ||
545 | */ | ||
546 | if (meminfo.nr_banks != 1) | ||
547 | create_memmap_holes(&meminfo); | ||
548 | |||
549 | /* this will put all unused low memory onto the freelists */ | 606 | /* this will put all unused low memory onto the freelists */ |
550 | for_each_online_node(node) { | 607 | for_each_online_node(node) { |
551 | pg_data_t *pgdat = NODE_DATA(node); | 608 | pg_data_t *pgdat = NODE_DATA(node); |
552 | 609 | ||
610 | free_unused_memmap_node(node, &meminfo); | ||
611 | |||
553 | if (pgdat->node_spanned_pages != 0) | 612 | if (pgdat->node_spanned_pages != 0) |
554 | totalram_pages += free_all_bootmem_node(pgdat); | 613 | totalram_pages += free_all_bootmem_node(pgdat); |
555 | } | 614 | } |
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 2c2b93d77d43..052ab443ec4e 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c | |||
@@ -169,7 +169,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm) | |||
169 | 169 | ||
170 | memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); | 170 | memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); |
171 | 171 | ||
172 | /* | ||
173 | * Copy over the kernel and IO PGD entries | ||
174 | */ | ||
172 | init_pgd = pgd_offset_k(0); | 175 | init_pgd = pgd_offset_k(0); |
176 | memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, | ||
177 | (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); | ||
178 | |||
179 | clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); | ||
173 | 180 | ||
174 | if (!vectors_high()) { | 181 | if (!vectors_high()) { |
175 | /* | 182 | /* |
@@ -198,14 +205,6 @@ pgd_t *get_pgd_slow(struct mm_struct *mm) | |||
198 | spin_unlock(&mm->page_table_lock); | 205 | spin_unlock(&mm->page_table_lock); |
199 | } | 206 | } |
200 | 207 | ||
201 | /* | ||
202 | * Copy over the kernel and IO PGD entries | ||
203 | */ | ||
204 | memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, | ||
205 | (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); | ||
206 | |||
207 | clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); | ||
208 | |||
209 | return new_pgd; | 208 | return new_pgd; |
210 | 209 | ||
211 | no_pte: | 210 | no_pte: |
@@ -698,75 +697,3 @@ void __init iotable_init(struct map_desc *io_desc, int nr) | |||
698 | for (i = 0; i < nr; i++) | 697 | for (i = 0; i < nr; i++) |
699 | create_mapping(io_desc + i); | 698 | create_mapping(io_desc + i); |
700 | } | 699 | } |
701 | |||
702 | static inline void | ||
703 | free_memmap(int node, unsigned long start_pfn, unsigned long end_pfn) | ||
704 | { | ||
705 | struct page *start_pg, *end_pg; | ||
706 | unsigned long pg, pgend; | ||
707 | |||
708 | /* | ||
709 | * Convert start_pfn/end_pfn to a struct page pointer. | ||
710 | */ | ||
711 | start_pg = pfn_to_page(start_pfn); | ||
712 | end_pg = pfn_to_page(end_pfn); | ||
713 | |||
714 | /* | ||
715 | * Convert to physical addresses, and | ||
716 | * round start upwards and end downwards. | ||
717 | */ | ||
718 | pg = PAGE_ALIGN(__pa(start_pg)); | ||
719 | pgend = __pa(end_pg) & PAGE_MASK; | ||
720 | |||
721 | /* | ||
722 | * If there are free pages between these, | ||
723 | * free the section of the memmap array. | ||
724 | */ | ||
725 | if (pg < pgend) | ||
726 | free_bootmem_node(NODE_DATA(node), pg, pgend - pg); | ||
727 | } | ||
728 | |||
729 | static inline void free_unused_memmap_node(int node, struct meminfo *mi) | ||
730 | { | ||
731 | unsigned long bank_start, prev_bank_end = 0; | ||
732 | unsigned int i; | ||
733 | |||
734 | /* | ||
735 | * [FIXME] This relies on each bank being in address order. This | ||
736 | * may not be the case, especially if the user has provided the | ||
737 | * information on the command line. | ||
738 | */ | ||
739 | for (i = 0; i < mi->nr_banks; i++) { | ||
740 | if (mi->bank[i].size == 0 || mi->bank[i].node != node) | ||
741 | continue; | ||
742 | |||
743 | bank_start = mi->bank[i].start >> PAGE_SHIFT; | ||
744 | if (bank_start < prev_bank_end) { | ||
745 | printk(KERN_ERR "MEM: unordered memory banks. " | ||
746 | "Not freeing memmap.\n"); | ||
747 | break; | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | * If we had a previous bank, and there is a space | ||
752 | * between the current bank and the previous, free it. | ||
753 | */ | ||
754 | if (prev_bank_end && prev_bank_end != bank_start) | ||
755 | free_memmap(node, prev_bank_end, bank_start); | ||
756 | |||
757 | prev_bank_end = PAGE_ALIGN(mi->bank[i].start + | ||
758 | mi->bank[i].size) >> PAGE_SHIFT; | ||
759 | } | ||
760 | } | ||
761 | |||
762 | /* | ||
763 | * The mem_map array can get very big. Free | ||
764 | * the unused area of the memory map. | ||
765 | */ | ||
766 | void __init create_memmap_holes(struct meminfo *mi) | ||
767 | { | ||
768 | int node; | ||
769 | |||
770 | for_each_online_node(node) | ||
771 | free_unused_memmap_node(node, mi); | ||
772 | } | ||
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 30c1dfbb052f..6d3a79e5fef8 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types | |||
@@ -6,7 +6,7 @@ | |||
6 | # To add an entry into this database, please see Documentation/arm/README, | 6 | # To add an entry into this database, please see Documentation/arm/README, |
7 | # or contact rmk@arm.linux.org.uk | 7 | # or contact rmk@arm.linux.org.uk |
8 | # | 8 | # |
9 | # Last update: Thu Mar 24 14:34:50 2005 | 9 | # Last update: Thu Jun 23 20:19:33 2005 |
10 | # | 10 | # |
11 | # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number | 11 | # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number |
12 | # | 12 | # |
@@ -243,7 +243,7 @@ yoho ARCH_YOHO YOHO 231 | |||
243 | jasper ARCH_JASPER JASPER 232 | 243 | jasper ARCH_JASPER JASPER 232 |
244 | dsc25 ARCH_DSC25 DSC25 233 | 244 | dsc25 ARCH_DSC25 DSC25 233 |
245 | omap_innovator MACH_OMAP_INNOVATOR OMAP_INNOVATOR 234 | 245 | omap_innovator MACH_OMAP_INNOVATOR OMAP_INNOVATOR 234 |
246 | ramses ARCH_RAMSES RAMSES 235 | 246 | mnci ARCH_RAMSES RAMSES 235 |
247 | s28x ARCH_S28X S28X 236 | 247 | s28x ARCH_S28X S28X 236 |
248 | mport3 ARCH_MPORT3 MPORT3 237 | 248 | mport3 ARCH_MPORT3 MPORT3 237 |
249 | pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238 | 249 | pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238 |
@@ -323,7 +323,7 @@ nimbra29x ARCH_NIMBRA29X NIMBRA29X 311 | |||
323 | nimbra210 ARCH_NIMBRA210 NIMBRA210 312 | 323 | nimbra210 ARCH_NIMBRA210 NIMBRA210 312 |
324 | hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313 | 324 | hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313 |
325 | labarm ARCH_LABARM LABARM 314 | 325 | labarm ARCH_LABARM LABARM 314 |
326 | m825xx ARCH_M825XX M825XX 315 | 326 | comcerto ARCH_M825XX M825XX 315 |
327 | m7100 SA1100_M7100 M7100 316 | 327 | m7100 SA1100_M7100 M7100 316 |
328 | nipc2 ARCH_NIPC2 NIPC2 317 | 328 | nipc2 ARCH_NIPC2 NIPC2 317 |
329 | fu7202 ARCH_FU7202 FU7202 318 | 329 | fu7202 ARCH_FU7202 FU7202 318 |
@@ -724,3 +724,66 @@ lpc22xx MACH_LPC22XX LPC22XX 715 | |||
724 | omap_comet3 MACH_COMET3 COMET3 716 | 724 | omap_comet3 MACH_COMET3 COMET3 716 |
725 | omap_comet4 MACH_COMET4 COMET4 717 | 725 | omap_comet4 MACH_COMET4 COMET4 717 |
726 | csb625 MACH_CSB625 CSB625 718 | 726 | csb625 MACH_CSB625 CSB625 718 |
727 | fortunet2 MACH_FORTUNET2 FORTUNET2 719 | ||
728 | s5h2200 MACH_S5H2200 S5H2200 720 | ||
729 | optorm920 MACH_OPTORM920 OPTORM920 721 | ||
730 | adsbitsyxb MACH_ADSBITSYXB ADSBITSYXB 722 | ||
731 | adssphere MACH_ADSSPHERE ADSSPHERE 723 | ||
732 | adsportal MACH_ADSPORTAL ADSPORTAL 724 | ||
733 | ln2410sbc MACH_LN2410SBC LN2410SBC 725 | ||
734 | cb3rufc MACH_CB3RUFC CB3RUFC 726 | ||
735 | mp2usb MACH_MP2USB MP2USB 727 | ||
736 | ntnp425c MACH_NTNP425C NTNP425C 728 | ||
737 | colibri MACH_COLIBRI COLIBRI 729 | ||
738 | pcm7220 MACH_PCM7220 PCM7220 730 | ||
739 | gateway7001 MACH_GATEWAY7001 GATEWAY7001 731 | ||
740 | pcm027 MACH_PCM027 PCM027 732 | ||
741 | cmpxa MACH_CMPXA CMPXA 733 | ||
742 | anubis MACH_ANUBIS ANUBIS 734 | ||
743 | ite8152 MACH_ITE8152 ITE8152 735 | ||
744 | lpc3xxx MACH_LPC3XXX LPC3XXX 736 | ||
745 | puppeteer MACH_PUPPETEER PUPPETEER 737 | ||
746 | vt001 MACH_MACH_VADATECH MACH_VADATECH 738 | ||
747 | e570 MACH_E570 E570 739 | ||
748 | x50 MACH_X50 X50 740 | ||
749 | recon MACH_RECON RECON 741 | ||
750 | xboardgp8 MACH_XBOARDGP8 XBOARDGP8 742 | ||
751 | fpic2 MACH_FPIC2 FPIC2 743 | ||
752 | akita MACH_AKITA AKITA 744 | ||
753 | a81 MACH_A81 A81 745 | ||
754 | svm_sc25x MACH_SVM_SC25X SVM_SC25X 746 | ||
755 | vt020 MACH_VADATECH020 VADATECH020 747 | ||
756 | tli MACH_TLI TLI 748 | ||
757 | edb9315lc MACH_EDB9315LC EDB9315LC 749 | ||
758 | passec MACH_PASSEC PASSEC 750 | ||
759 | ds_tiger MACH_DS_TIGER DS_TIGER 751 | ||
760 | e310 MACH_E310 E310 752 | ||
761 | e330 MACH_E330 E330 753 | ||
762 | rt3000 MACH_RT3000 RT3000 754 | ||
763 | nokia770 MACH_NOKIA770 NOKIA770 755 | ||
764 | pnx0106 MACH_PNX0106 PNX0106 756 | ||
765 | hx21xx MACH_HX21XX HX21XX 757 | ||
766 | faraday MACH_FARADAY FARADAY 758 | ||
767 | sbc9312 MACH_SBC9312 SBC9312 759 | ||
768 | batman MACH_BATMAN BATMAN 760 | ||
769 | jpd201 MACH_JPD201 JPD201 761 | ||
770 | mipsa MACH_MIPSA MIPSA 762 | ||
771 | kacom MACH_KACOM KACOM 763 | ||
772 | swarcocpu MACH_SWARCOCPU SWARCOCPU 764 | ||
773 | swarcodsl MACH_SWARCODSL SWARCODSL 765 | ||
774 | blueangel MACH_BLUEANGEL BLUEANGEL 766 | ||
775 | hairygrama MACH_HAIRYGRAMA HAIRYGRAMA 767 | ||
776 | banff MACH_BANFF BANFF 768 | ||
777 | carmeva MACH_CARMEVA CARMEVA 769 | ||
778 | sam255 MACH_SAM255 SAM255 770 | ||
779 | ppm10 MACH_PPM10 PPM10 771 | ||
780 | edb9315a MACH_EDB9315A EDB9315A 772 | ||
781 | sunset MACH_SUNSET SUNSET 773 | ||
782 | stargate2 MACH_STARGATE2 STARGATE2 774 | ||
783 | intelmote2 MACH_INTELMOTE2 INTELMOTE2 775 | ||
784 | trizeps4 MACH_TRIZEPS4 TRIZEPS4 776 | ||
785 | mainstone2 MACH_MAINSTONE2 MAINSTONE2 777 | ||
786 | ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778 | ||
787 | tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779 | ||
788 | universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780 | ||
789 | hicoarm9 MACH_HICOARM9 HICOARM9 781 | ||
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 3762f6b35ab2..fc8b17521761 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c | |||
@@ -127,48 +127,23 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | |||
127 | regs->eip = (unsigned long)&p->ainsn.insn; | 127 | regs->eip = (unsigned long)&p->ainsn.insn; |
128 | } | 128 | } |
129 | 129 | ||
130 | struct task_struct *arch_get_kprobe_task(void *ptr) | ||
131 | { | ||
132 | return ((struct thread_info *) (((unsigned long) ptr) & | ||
133 | (~(THREAD_SIZE -1))))->task; | ||
134 | } | ||
135 | |||
136 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | 130 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) |
137 | { | 131 | { |
138 | unsigned long *sara = (unsigned long *)®s->esp; | 132 | unsigned long *sara = (unsigned long *)®s->esp; |
139 | struct kretprobe_instance *ri; | 133 | struct kretprobe_instance *ri; |
140 | static void *orig_ret_addr; | 134 | |
135 | if ((ri = get_free_rp_inst(rp)) != NULL) { | ||
136 | ri->rp = rp; | ||
137 | ri->task = current; | ||
138 | ri->ret_addr = (kprobe_opcode_t *) *sara; | ||
141 | 139 | ||
142 | /* | ||
143 | * Save the return address when the return probe hits | ||
144 | * the first time, and use it to populate the (krprobe | ||
145 | * instance)->ret_addr for subsequent return probes at | ||
146 | * the same addrress since stack address would have | ||
147 | * the kretprobe_trampoline by then. | ||
148 | */ | ||
149 | if (((void*) *sara) != kretprobe_trampoline) | ||
150 | orig_ret_addr = (void*) *sara; | ||
151 | |||
152 | if ((ri = get_free_rp_inst(rp)) != NULL) { | ||
153 | ri->rp = rp; | ||
154 | ri->stack_addr = sara; | ||
155 | ri->ret_addr = orig_ret_addr; | ||
156 | add_rp_inst(ri); | ||
157 | /* Replace the return addr with trampoline addr */ | 140 | /* Replace the return addr with trampoline addr */ |
158 | *sara = (unsigned long) &kretprobe_trampoline; | 141 | *sara = (unsigned long) &kretprobe_trampoline; |
159 | } else { | ||
160 | rp->nmissed++; | ||
161 | } | ||
162 | } | ||
163 | 142 | ||
164 | void arch_kprobe_flush_task(struct task_struct *tk) | 143 | add_rp_inst(ri); |
165 | { | 144 | } else { |
166 | struct kretprobe_instance *ri; | 145 | rp->nmissed++; |
167 | while ((ri = get_rp_inst_tsk(tk)) != NULL) { | 146 | } |
168 | *((unsigned long *)(ri->stack_addr)) = | ||
169 | (unsigned long) ri->ret_addr; | ||
170 | recycle_rp_inst(ri); | ||
171 | } | ||
172 | } | 147 | } |
173 | 148 | ||
174 | /* | 149 | /* |
@@ -286,36 +261,59 @@ no_kprobe: | |||
286 | */ | 261 | */ |
287 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 262 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
288 | { | 263 | { |
289 | struct task_struct *tsk; | 264 | struct kretprobe_instance *ri = NULL; |
290 | struct kretprobe_instance *ri; | 265 | struct hlist_head *head; |
291 | struct hlist_head *head; | 266 | struct hlist_node *node, *tmp; |
292 | struct hlist_node *node; | 267 | unsigned long orig_ret_address = 0; |
293 | unsigned long *sara = ((unsigned long *) ®s->esp) - 1; | 268 | unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; |
294 | |||
295 | tsk = arch_get_kprobe_task(sara); | ||
296 | head = kretprobe_inst_table_head(tsk); | ||
297 | |||
298 | hlist_for_each_entry(ri, node, head, hlist) { | ||
299 | if (ri->stack_addr == sara && ri->rp) { | ||
300 | if (ri->rp->handler) | ||
301 | ri->rp->handler(ri, regs); | ||
302 | } | ||
303 | } | ||
304 | return 0; | ||
305 | } | ||
306 | 269 | ||
307 | void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs, | 270 | head = kretprobe_inst_table_head(current); |
308 | unsigned long flags) | ||
309 | { | ||
310 | struct kretprobe_instance *ri; | ||
311 | /* RA already popped */ | ||
312 | unsigned long *sara = ((unsigned long *)®s->esp) - 1; | ||
313 | 271 | ||
314 | while ((ri = get_rp_inst(sara))) { | 272 | /* |
315 | regs->eip = (unsigned long)ri->ret_addr; | 273 | * It is possible to have multiple instances associated with a given |
274 | * task either because an multiple functions in the call path | ||
275 | * have a return probe installed on them, and/or more then one return | ||
276 | * return probe was registered for a target function. | ||
277 | * | ||
278 | * We can handle this because: | ||
279 | * - instances are always inserted at the head of the list | ||
280 | * - when multiple return probes are registered for the same | ||
281 | * function, the first instance's ret_addr will point to the | ||
282 | * real return address, and all the rest will point to | ||
283 | * kretprobe_trampoline | ||
284 | */ | ||
285 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | ||
286 | if (ri->task != current) | ||
287 | /* another task is sharing our hash bucket */ | ||
288 | continue; | ||
289 | |||
290 | if (ri->rp && ri->rp->handler) | ||
291 | ri->rp->handler(ri, regs); | ||
292 | |||
293 | orig_ret_address = (unsigned long)ri->ret_addr; | ||
316 | recycle_rp_inst(ri); | 294 | recycle_rp_inst(ri); |
295 | |||
296 | if (orig_ret_address != trampoline_address) | ||
297 | /* | ||
298 | * This is the real return address. Any other | ||
299 | * instances associated with this task are for | ||
300 | * other calls deeper on the call stack | ||
301 | */ | ||
302 | break; | ||
317 | } | 303 | } |
318 | regs->eflags &= ~TF_MASK; | 304 | |
305 | BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); | ||
306 | regs->eip = orig_ret_address; | ||
307 | |||
308 | unlock_kprobes(); | ||
309 | preempt_enable_no_resched(); | ||
310 | |||
311 | /* | ||
312 | * By returning a non-zero value, we are telling | ||
313 | * kprobe_handler() that we have handled unlocking | ||
314 | * and re-enabling preemption. | ||
315 | */ | ||
316 | return 1; | ||
319 | } | 317 | } |
320 | 318 | ||
321 | /* | 319 | /* |
@@ -403,8 +401,7 @@ static inline int post_kprobe_handler(struct pt_regs *regs) | |||
403 | current_kprobe->post_handler(current_kprobe, regs, 0); | 401 | current_kprobe->post_handler(current_kprobe, regs, 0); |
404 | } | 402 | } |
405 | 403 | ||
406 | if (current_kprobe->post_handler != trampoline_post_handler) | 404 | resume_execution(current_kprobe, regs); |
407 | resume_execution(current_kprobe, regs); | ||
408 | regs->eflags |= kprobe_saved_eflags; | 405 | regs->eflags |= kprobe_saved_eflags; |
409 | 406 | ||
410 | /*Restore back the original saved kprobes variables and continue. */ | 407 | /*Restore back the original saved kprobes variables and continue. */ |
@@ -534,3 +531,13 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
534 | } | 531 | } |
535 | return 0; | 532 | return 0; |
536 | } | 533 | } |
534 | |||
535 | static struct kprobe trampoline_p = { | ||
536 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, | ||
537 | .pre_handler = trampoline_probe_handler | ||
538 | }; | ||
539 | |||
540 | int __init arch_init(void) | ||
541 | { | ||
542 | return register_kprobe(&trampoline_p); | ||
543 | } | ||
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 5f8cfa6b7940..ba243a4cc119 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -617,6 +617,33 @@ handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss) | |||
617 | } | 617 | } |
618 | 618 | ||
619 | /* | 619 | /* |
620 | * This function selects if the context switch from prev to next | ||
621 | * has to tweak the TSC disable bit in the cr4. | ||
622 | */ | ||
623 | static inline void disable_tsc(struct task_struct *prev_p, | ||
624 | struct task_struct *next_p) | ||
625 | { | ||
626 | struct thread_info *prev, *next; | ||
627 | |||
628 | /* | ||
629 | * gcc should eliminate the ->thread_info dereference if | ||
630 | * has_secure_computing returns 0 at compile time (SECCOMP=n). | ||
631 | */ | ||
632 | prev = prev_p->thread_info; | ||
633 | next = next_p->thread_info; | ||
634 | |||
635 | if (has_secure_computing(prev) || has_secure_computing(next)) { | ||
636 | /* slow path here */ | ||
637 | if (has_secure_computing(prev) && | ||
638 | !has_secure_computing(next)) { | ||
639 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
640 | } else if (!has_secure_computing(prev) && | ||
641 | has_secure_computing(next)) | ||
642 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
643 | } | ||
644 | } | ||
645 | |||
646 | /* | ||
620 | * switch_to(x,yn) should switch tasks from x to y. | 647 | * switch_to(x,yn) should switch tasks from x to y. |
621 | * | 648 | * |
622 | * We fsave/fwait so that an exception goes off at the right time | 649 | * We fsave/fwait so that an exception goes off at the right time |
@@ -695,6 +722,8 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas | |||
695 | if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) | 722 | if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) |
696 | handle_io_bitmap(next, tss); | 723 | handle_io_bitmap(next, tss); |
697 | 724 | ||
725 | disable_tsc(prev_p, next_p); | ||
726 | |||
698 | return prev_p; | 727 | return prev_p; |
699 | } | 728 | } |
700 | 729 | ||
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 442a6e937b19..3db9a04aec6e 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S | |||
@@ -289,3 +289,5 @@ ENTRY(sys_call_table) | |||
289 | .long sys_add_key | 289 | .long sys_add_key |
290 | .long sys_request_key | 290 | .long sys_request_key |
291 | .long sys_keyctl | 291 | .long sys_keyctl |
292 | .long sys_ioprio_set | ||
293 | .long sys_ioprio_get /* 290 */ | ||
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index b1d5d3d5276c..785a51b0ad8e 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -1577,8 +1577,8 @@ sys_call_table: | |||
1577 | data8 sys_add_key | 1577 | data8 sys_add_key |
1578 | data8 sys_request_key | 1578 | data8 sys_request_key |
1579 | data8 sys_keyctl | 1579 | data8 sys_keyctl |
1580 | data8 sys_ni_syscall | 1580 | data8 sys_ioprio_set |
1581 | data8 sys_ni_syscall // 1275 | 1581 | data8 sys_ioprio_get // 1275 |
1582 | data8 sys_set_zone_reclaim | 1582 | data8 sys_set_zone_reclaim |
1583 | data8 sys_ni_syscall | 1583 | data8 sys_ni_syscall |
1584 | data8 sys_ni_syscall | 1584 | data8 sys_ni_syscall |
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 5978823d5c63..3aa3167edbec 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
36 | #include <asm/kdebug.h> | 36 | #include <asm/kdebug.h> |
37 | #include <asm/sections.h> | ||
37 | 38 | ||
38 | extern void jprobe_inst_return(void); | 39 | extern void jprobe_inst_return(void); |
39 | 40 | ||
@@ -263,13 +264,33 @@ static inline void get_kprobe_inst(bundle_t *bundle, uint slot, | |||
263 | } | 264 | } |
264 | } | 265 | } |
265 | 266 | ||
267 | /* Returns non-zero if the addr is in the Interrupt Vector Table */ | ||
268 | static inline int in_ivt_functions(unsigned long addr) | ||
269 | { | ||
270 | return (addr >= (unsigned long)__start_ivt_text | ||
271 | && addr < (unsigned long)__end_ivt_text); | ||
272 | } | ||
273 | |||
266 | static int valid_kprobe_addr(int template, int slot, unsigned long addr) | 274 | static int valid_kprobe_addr(int template, int slot, unsigned long addr) |
267 | { | 275 | { |
268 | if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) { | 276 | if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) { |
269 | printk(KERN_WARNING "Attempting to insert unaligned kprobe at 0x%lx\n", | 277 | printk(KERN_WARNING "Attempting to insert unaligned kprobe " |
270 | addr); | 278 | "at 0x%lx\n", addr); |
271 | return -EINVAL; | 279 | return -EINVAL; |
272 | } | 280 | } |
281 | |||
282 | if (in_ivt_functions(addr)) { | ||
283 | printk(KERN_WARNING "Kprobes can't be inserted inside " | ||
284 | "IVT functions at 0x%lx\n", addr); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | if (slot == 1 && bundle_encoding[template][1] != L) { | ||
289 | printk(KERN_WARNING "Inserting kprobes on slot #1 " | ||
290 | "is not supported\n"); | ||
291 | return -EINVAL; | ||
292 | } | ||
293 | |||
273 | return 0; | 294 | return 0; |
274 | } | 295 | } |
275 | 296 | ||
@@ -290,6 +311,94 @@ static inline void set_current_kprobe(struct kprobe *p) | |||
290 | current_kprobe = p; | 311 | current_kprobe = p; |
291 | } | 312 | } |
292 | 313 | ||
314 | static void kretprobe_trampoline(void) | ||
315 | { | ||
316 | } | ||
317 | |||
318 | /* | ||
319 | * At this point the target function has been tricked into | ||
320 | * returning into our trampoline. Lookup the associated instance | ||
321 | * and then: | ||
322 | * - call the handler function | ||
323 | * - cleanup by marking the instance as unused | ||
324 | * - long jump back to the original return address | ||
325 | */ | ||
326 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | ||
327 | { | ||
328 | struct kretprobe_instance *ri = NULL; | ||
329 | struct hlist_head *head; | ||
330 | struct hlist_node *node, *tmp; | ||
331 | unsigned long orig_ret_address = 0; | ||
332 | unsigned long trampoline_address = | ||
333 | ((struct fnptr *)kretprobe_trampoline)->ip; | ||
334 | |||
335 | head = kretprobe_inst_table_head(current); | ||
336 | |||
337 | /* | ||
338 | * It is possible to have multiple instances associated with a given | ||
339 | * task either because an multiple functions in the call path | ||
340 | * have a return probe installed on them, and/or more then one return | ||
341 | * return probe was registered for a target function. | ||
342 | * | ||
343 | * We can handle this because: | ||
344 | * - instances are always inserted at the head of the list | ||
345 | * - when multiple return probes are registered for the same | ||
346 | * function, the first instance's ret_addr will point to the | ||
347 | * real return address, and all the rest will point to | ||
348 | * kretprobe_trampoline | ||
349 | */ | ||
350 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | ||
351 | if (ri->task != current) | ||
352 | /* another task is sharing our hash bucket */ | ||
353 | continue; | ||
354 | |||
355 | if (ri->rp && ri->rp->handler) | ||
356 | ri->rp->handler(ri, regs); | ||
357 | |||
358 | orig_ret_address = (unsigned long)ri->ret_addr; | ||
359 | recycle_rp_inst(ri); | ||
360 | |||
361 | if (orig_ret_address != trampoline_address) | ||
362 | /* | ||
363 | * This is the real return address. Any other | ||
364 | * instances associated with this task are for | ||
365 | * other calls deeper on the call stack | ||
366 | */ | ||
367 | break; | ||
368 | } | ||
369 | |||
370 | BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); | ||
371 | regs->cr_iip = orig_ret_address; | ||
372 | |||
373 | unlock_kprobes(); | ||
374 | preempt_enable_no_resched(); | ||
375 | |||
376 | /* | ||
377 | * By returning a non-zero value, we are telling | ||
378 | * kprobe_handler() that we have handled unlocking | ||
379 | * and re-enabling preemption. | ||
380 | */ | ||
381 | return 1; | ||
382 | } | ||
383 | |||
384 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | ||
385 | { | ||
386 | struct kretprobe_instance *ri; | ||
387 | |||
388 | if ((ri = get_free_rp_inst(rp)) != NULL) { | ||
389 | ri->rp = rp; | ||
390 | ri->task = current; | ||
391 | ri->ret_addr = (kprobe_opcode_t *)regs->b0; | ||
392 | |||
393 | /* Replace the return addr with trampoline addr */ | ||
394 | regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip; | ||
395 | |||
396 | add_rp_inst(ri); | ||
397 | } else { | ||
398 | rp->nmissed++; | ||
399 | } | ||
400 | } | ||
401 | |||
293 | int arch_prepare_kprobe(struct kprobe *p) | 402 | int arch_prepare_kprobe(struct kprobe *p) |
294 | { | 403 | { |
295 | unsigned long addr = (unsigned long) p->addr; | 404 | unsigned long addr = (unsigned long) p->addr; |
@@ -492,8 +601,8 @@ static int pre_kprobes_handler(struct die_args *args) | |||
492 | if (p->pre_handler && p->pre_handler(p, regs)) | 601 | if (p->pre_handler && p->pre_handler(p, regs)) |
493 | /* | 602 | /* |
494 | * Our pre-handler is specifically requesting that we just | 603 | * Our pre-handler is specifically requesting that we just |
495 | * do a return. This is handling the case where the | 604 | * do a return. This is used for both the jprobe pre-handler |
496 | * pre-handler is really our special jprobe pre-handler. | 605 | * and the kretprobe trampoline |
497 | */ | 606 | */ |
498 | return 1; | 607 | return 1; |
499 | 608 | ||
@@ -599,3 +708,14 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
599 | *regs = jprobe_saved_regs; | 708 | *regs = jprobe_saved_regs; |
600 | return 1; | 709 | return 1; |
601 | } | 710 | } |
711 | |||
712 | static struct kprobe trampoline_p = { | ||
713 | .pre_handler = trampoline_probe_handler | ||
714 | }; | ||
715 | |||
716 | int __init arch_init(void) | ||
717 | { | ||
718 | trampoline_p.addr = | ||
719 | (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip; | ||
720 | return register_kprobe(&trampoline_p); | ||
721 | } | ||
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index ebb71f3d6d19..6e35bff05d59 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/efi.h> | 27 | #include <linux/efi.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/kprobes.h> | ||
30 | 31 | ||
31 | #include <asm/cpu.h> | 32 | #include <asm/cpu.h> |
32 | #include <asm/delay.h> | 33 | #include <asm/delay.h> |
@@ -707,6 +708,13 @@ kernel_thread_helper (int (*fn)(void *), void *arg) | |||
707 | void | 708 | void |
708 | flush_thread (void) | 709 | flush_thread (void) |
709 | { | 710 | { |
711 | /* | ||
712 | * Remove function-return probe instances associated with this task | ||
713 | * and put them back on the free list. Do not insert an exit probe for | ||
714 | * this function, it will be disabled by kprobe_flush_task if you do. | ||
715 | */ | ||
716 | kprobe_flush_task(current); | ||
717 | |||
710 | /* drop floating-point and debug-register state if it exists: */ | 718 | /* drop floating-point and debug-register state if it exists: */ |
711 | current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); | 719 | current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); |
712 | ia64_drop_fpu(current); | 720 | ia64_drop_fpu(current); |
@@ -721,6 +729,14 @@ flush_thread (void) | |||
721 | void | 729 | void |
722 | exit_thread (void) | 730 | exit_thread (void) |
723 | { | 731 | { |
732 | |||
733 | /* | ||
734 | * Remove function-return probe instances associated with this task | ||
735 | * and put them back on the free list. Do not insert an exit probe for | ||
736 | * this function, it will be disabled by kprobe_flush_task if you do. | ||
737 | */ | ||
738 | kprobe_flush_task(current); | ||
739 | |||
724 | ia64_drop_fpu(current); | 740 | ia64_drop_fpu(current); |
725 | #ifdef CONFIG_PERFMON | 741 | #ifdef CONFIG_PERFMON |
726 | /* if needed, stop monitoring and flush state to perfmon context */ | 742 | /* if needed, stop monitoring and flush state to perfmon context */ |
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index b9f0db4c1b04..a676e79e0681 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
@@ -8,6 +8,11 @@ | |||
8 | #define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE) | 8 | #define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE) |
9 | #include <asm-generic/vmlinux.lds.h> | 9 | #include <asm-generic/vmlinux.lds.h> |
10 | 10 | ||
11 | #define IVT_TEXT \ | ||
12 | VMLINUX_SYMBOL(__start_ivt_text) = .; \ | ||
13 | *(.text.ivt) \ | ||
14 | VMLINUX_SYMBOL(__end_ivt_text) = .; | ||
15 | |||
11 | OUTPUT_FORMAT("elf64-ia64-little") | 16 | OUTPUT_FORMAT("elf64-ia64-little") |
12 | OUTPUT_ARCH(ia64) | 17 | OUTPUT_ARCH(ia64) |
13 | ENTRY(phys_start) | 18 | ENTRY(phys_start) |
@@ -39,7 +44,7 @@ SECTIONS | |||
39 | 44 | ||
40 | .text : AT(ADDR(.text) - LOAD_OFFSET) | 45 | .text : AT(ADDR(.text) - LOAD_OFFSET) |
41 | { | 46 | { |
42 | *(.text.ivt) | 47 | IVT_TEXT |
43 | *(.text) | 48 | *(.text) |
44 | SCHED_TEXT | 49 | SCHED_TEXT |
45 | LOCK_TEXT | 50 | LOCK_TEXT |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 508026ae5842..65ee15396ffd 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -457,7 +457,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
457 | if (!user_mode(regs)) | 457 | if (!user_mode(regs)) |
458 | return 1; | 458 | return 1; |
459 | 459 | ||
460 | if (try_to_freeze(0)) | 460 | if (try_to_freeze()) |
461 | goto no_signal; | 461 | goto no_signal; |
462 | 462 | ||
463 | if (!oldset) | 463 | if (!oldset) |
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index b6a63a49a232..191a8def3bdb 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S | |||
@@ -1449,3 +1449,5 @@ _GLOBAL(sys_call_table) | |||
1449 | .long sys_request_key /* 270 */ | 1449 | .long sys_request_key /* 270 */ |
1450 | .long sys_keyctl | 1450 | .long sys_keyctl |
1451 | .long sys_waitid | 1451 | .long sys_waitid |
1452 | .long sys_ioprio_set | ||
1453 | .long sys_ioprio_get | ||
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 334ef4150d92..6164a2b34733 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c | |||
@@ -606,9 +606,19 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, | |||
606 | struct page *page = pfn_to_page(pfn); | 606 | struct page *page = pfn_to_page(pfn); |
607 | if (!PageReserved(page) | 607 | if (!PageReserved(page) |
608 | && !test_bit(PG_arch_1, &page->flags)) { | 608 | && !test_bit(PG_arch_1, &page->flags)) { |
609 | if (vma->vm_mm == current->active_mm) | 609 | if (vma->vm_mm == current->active_mm) { |
610 | #ifdef CONFIG_8xx | ||
611 | /* On 8xx, cache control instructions (particularly | ||
612 | * "dcbst" from flush_dcache_icache) fault as write | ||
613 | * operation if there is an unpopulated TLB entry | ||
614 | * for the address in question. To workaround that, | ||
615 | * we invalidate the TLB here, thus avoiding dcbst | ||
616 | * misbehaviour. | ||
617 | */ | ||
618 | _tlbie(address); | ||
619 | #endif | ||
610 | __flush_dcache_icache((void *) address); | 620 | __flush_dcache_icache((void *) address); |
611 | else | 621 | } else |
612 | flush_dcache_icache_page(page); | 622 | flush_dcache_icache_page(page); |
613 | set_bit(PG_arch_1, &page->flags); | 623 | set_bit(PG_arch_1, &page->flags); |
614 | } | 624 | } |
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S index f459ade1bd63..016a74649155 100644 --- a/arch/ppc/platforms/pmac_sleep.S +++ b/arch/ppc/platforms/pmac_sleep.S | |||
@@ -46,7 +46,7 @@ | |||
46 | .section .text | 46 | .section .text |
47 | .align 5 | 47 | .align 5 |
48 | 48 | ||
49 | #if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ_PMAC) | 49 | #if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) |
50 | 50 | ||
51 | /* This gets called by via-pmu.c late during the sleep process. | 51 | /* This gets called by via-pmu.c late during the sleep process. |
52 | * The PMU was already send the sleep command and will shut us down | 52 | * The PMU was already send the sleep command and will shut us down |
@@ -382,7 +382,7 @@ turn_on_mmu: | |||
382 | isync | 382 | isync |
383 | rfi | 383 | rfi |
384 | 384 | ||
385 | #endif /* defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ) */ | 385 | #endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */ |
386 | 386 | ||
387 | .section .data | 387 | .section .data |
388 | .balign L1_CACHE_LINE_SIZE | 388 | .balign L1_CACHE_LINE_SIZE |
diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c index de60ccc7db9f..778ce4fec368 100644 --- a/arch/ppc/platforms/pmac_time.c +++ b/arch/ppc/platforms/pmac_time.c | |||
@@ -206,7 +206,7 @@ via_calibrate_decr(void) | |||
206 | return 1; | 206 | return 1; |
207 | } | 207 | } |
208 | 208 | ||
209 | #ifdef CONFIG_PMAC_PBOOK | 209 | #ifdef CONFIG_PM |
210 | /* | 210 | /* |
211 | * Reset the time after a sleep. | 211 | * Reset the time after a sleep. |
212 | */ | 212 | */ |
@@ -238,7 +238,7 @@ time_sleep_notify(struct pmu_sleep_notifier *self, int when) | |||
238 | static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = { | 238 | static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = { |
239 | time_sleep_notify, SLEEP_LEVEL_MISC, | 239 | time_sleep_notify, SLEEP_LEVEL_MISC, |
240 | }; | 240 | }; |
241 | #endif /* CONFIG_PMAC_PBOOK */ | 241 | #endif /* CONFIG_PM */ |
242 | 242 | ||
243 | /* | 243 | /* |
244 | * Query the OF and get the decr frequency. | 244 | * Query the OF and get the decr frequency. |
@@ -251,9 +251,9 @@ pmac_calibrate_decr(void) | |||
251 | struct device_node *cpu; | 251 | struct device_node *cpu; |
252 | unsigned int freq, *fp; | 252 | unsigned int freq, *fp; |
253 | 253 | ||
254 | #ifdef CONFIG_PMAC_PBOOK | 254 | #ifdef CONFIG_PM |
255 | pmu_register_sleep_notifier(&time_sleep_notifier); | 255 | pmu_register_sleep_notifier(&time_sleep_notifier); |
256 | #endif /* CONFIG_PMAC_PBOOK */ | 256 | #endif /* CONFIG_PM */ |
257 | 257 | ||
258 | /* We assume MacRISC2 machines have correct device-tree | 258 | /* We assume MacRISC2 machines have correct device-tree |
259 | * calibration. That's better since the VIA itself seems | 259 | * calibration. That's better since the VIA itself seems |
diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c index 70e58f43f2b8..8b149c2fc54f 100644 --- a/arch/ppc/platforms/sandpoint.c +++ b/arch/ppc/platforms/sandpoint.c | |||
@@ -324,6 +324,7 @@ sandpoint_setup_arch(void) | |||
324 | pdata[1].irq = 0; | 324 | pdata[1].irq = 0; |
325 | pdata[1].mapbase = 0; | 325 | pdata[1].mapbase = 0; |
326 | } | 326 | } |
327 | } | ||
327 | 328 | ||
328 | printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n"); | 329 | printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n"); |
329 | printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); | 330 | printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); |
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c index b45d8268bf93..ad39b86ca92c 100644 --- a/arch/ppc/syslib/open_pic.c +++ b/arch/ppc/syslib/open_pic.c | |||
@@ -370,8 +370,9 @@ void __init openpic_init(int offset) | |||
370 | /* Initialize IPI interrupts */ | 370 | /* Initialize IPI interrupts */ |
371 | if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb); | 371 | if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb); |
372 | for (i = 0; i < OPENPIC_NUM_IPI; i++) { | 372 | for (i = 0; i < OPENPIC_NUM_IPI; i++) { |
373 | /* Disabled, Priority 10..13 */ | 373 | /* Disabled, increased priorities 10..13 */ |
374 | openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset); | 374 | openpic_initipi(i, OPENPIC_PRIORITY_IPI_BASE+i, |
375 | OPENPIC_VEC_IPI+i+offset); | ||
375 | /* IPIs are per-CPU */ | 376 | /* IPIs are per-CPU */ |
376 | irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU; | 377 | irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU; |
377 | irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi; | 378 | irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi; |
@@ -399,8 +400,9 @@ void __init openpic_init(int offset) | |||
399 | if (sense & IRQ_SENSE_MASK) | 400 | if (sense & IRQ_SENSE_MASK) |
400 | irq_desc[i+offset].status = IRQ_LEVEL; | 401 | irq_desc[i+offset].status = IRQ_LEVEL; |
401 | 402 | ||
402 | /* Enabled, Priority 8 */ | 403 | /* Enabled, Default priority */ |
403 | openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK), | 404 | openpic_initirq(i, OPENPIC_PRIORITY_DEFAULT, i+offset, |
405 | (sense & IRQ_POLARITY_MASK), | ||
404 | (sense & IRQ_SENSE_MASK)); | 406 | (sense & IRQ_SENSE_MASK)); |
405 | /* Processor 0 */ | 407 | /* Processor 0 */ |
406 | openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE); | 408 | openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE); |
@@ -656,6 +658,18 @@ static void __init openpic_maptimer(u_int timer, cpumask_t cpumask) | |||
656 | } | 658 | } |
657 | 659 | ||
658 | /* | 660 | /* |
661 | * Change the priority of an interrupt | ||
662 | */ | ||
663 | void __init | ||
664 | openpic_set_irq_priority(u_int irq, u_int pri) | ||
665 | { | ||
666 | check_arg_irq(irq); | ||
667 | openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority, | ||
668 | OPENPIC_PRIORITY_MASK, | ||
669 | pri << OPENPIC_PRIORITY_SHIFT); | ||
670 | } | ||
671 | |||
672 | /* | ||
659 | * Initalize the interrupt source which will generate an NMI. | 673 | * Initalize the interrupt source which will generate an NMI. |
660 | * This raises the interrupt's priority from 8 to 9. | 674 | * This raises the interrupt's priority from 8 to 9. |
661 | * | 675 | * |
@@ -665,9 +679,7 @@ void __init | |||
665 | openpic_init_nmi_irq(u_int irq) | 679 | openpic_init_nmi_irq(u_int irq) |
666 | { | 680 | { |
667 | check_arg_irq(irq); | 681 | check_arg_irq(irq); |
668 | openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority, | 682 | openpic_set_irq_priority(irq, OPENPIC_PRIORITY_NMI); |
669 | OPENPIC_PRIORITY_MASK, | ||
670 | 9 << OPENPIC_PRIORITY_SHIFT); | ||
671 | } | 683 | } |
672 | 684 | ||
673 | /* | 685 | /* |
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index 782ce3efa2c1..1d2ff6d6b0b3 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c | |||
@@ -36,6 +36,8 @@ | |||
36 | #include <asm/kdebug.h> | 36 | #include <asm/kdebug.h> |
37 | #include <asm/sstep.h> | 37 | #include <asm/sstep.h> |
38 | 38 | ||
39 | static DECLARE_MUTEX(kprobe_mutex); | ||
40 | |||
39 | static struct kprobe *current_kprobe; | 41 | static struct kprobe *current_kprobe; |
40 | static unsigned long kprobe_status, kprobe_saved_msr; | 42 | static unsigned long kprobe_status, kprobe_saved_msr; |
41 | static struct kprobe *kprobe_prev; | 43 | static struct kprobe *kprobe_prev; |
@@ -54,6 +56,15 @@ int arch_prepare_kprobe(struct kprobe *p) | |||
54 | printk("Cannot register a kprobe on rfid or mtmsrd\n"); | 56 | printk("Cannot register a kprobe on rfid or mtmsrd\n"); |
55 | ret = -EINVAL; | 57 | ret = -EINVAL; |
56 | } | 58 | } |
59 | |||
60 | /* insn must be on a special executable page on ppc64 */ | ||
61 | if (!ret) { | ||
62 | up(&kprobe_mutex); | ||
63 | p->ainsn.insn = get_insn_slot(); | ||
64 | down(&kprobe_mutex); | ||
65 | if (!p->ainsn.insn) | ||
66 | ret = -ENOMEM; | ||
67 | } | ||
57 | return ret; | 68 | return ret; |
58 | } | 69 | } |
59 | 70 | ||
@@ -79,16 +90,22 @@ void arch_disarm_kprobe(struct kprobe *p) | |||
79 | 90 | ||
80 | void arch_remove_kprobe(struct kprobe *p) | 91 | void arch_remove_kprobe(struct kprobe *p) |
81 | { | 92 | { |
93 | up(&kprobe_mutex); | ||
94 | free_insn_slot(p->ainsn.insn); | ||
95 | down(&kprobe_mutex); | ||
82 | } | 96 | } |
83 | 97 | ||
84 | static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | 98 | static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) |
85 | { | 99 | { |
100 | kprobe_opcode_t insn = *p->ainsn.insn; | ||
101 | |||
86 | regs->msr |= MSR_SE; | 102 | regs->msr |= MSR_SE; |
87 | /*single step inline if it a breakpoint instruction*/ | 103 | |
88 | if (p->opcode == BREAKPOINT_INSTRUCTION) | 104 | /* single step inline if it is a trap variant */ |
105 | if (IS_TW(insn) || IS_TD(insn) || IS_TWI(insn) || IS_TDI(insn)) | ||
89 | regs->nip = (unsigned long)p->addr; | 106 | regs->nip = (unsigned long)p->addr; |
90 | else | 107 | else |
91 | regs->nip = (unsigned long)&p->ainsn.insn; | 108 | regs->nip = (unsigned long)p->ainsn.insn; |
92 | } | 109 | } |
93 | 110 | ||
94 | static inline void save_previous_kprobe(void) | 111 | static inline void save_previous_kprobe(void) |
@@ -105,6 +122,23 @@ static inline void restore_previous_kprobe(void) | |||
105 | kprobe_saved_msr = kprobe_saved_msr_prev; | 122 | kprobe_saved_msr = kprobe_saved_msr_prev; |
106 | } | 123 | } |
107 | 124 | ||
125 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | ||
126 | { | ||
127 | struct kretprobe_instance *ri; | ||
128 | |||
129 | if ((ri = get_free_rp_inst(rp)) != NULL) { | ||
130 | ri->rp = rp; | ||
131 | ri->task = current; | ||
132 | ri->ret_addr = (kprobe_opcode_t *)regs->link; | ||
133 | |||
134 | /* Replace the return addr with trampoline addr */ | ||
135 | regs->link = (unsigned long)kretprobe_trampoline; | ||
136 | add_rp_inst(ri); | ||
137 | } else { | ||
138 | rp->nmissed++; | ||
139 | } | ||
140 | } | ||
141 | |||
108 | static inline int kprobe_handler(struct pt_regs *regs) | 142 | static inline int kprobe_handler(struct pt_regs *regs) |
109 | { | 143 | { |
110 | struct kprobe *p; | 144 | struct kprobe *p; |
@@ -195,6 +229,78 @@ no_kprobe: | |||
195 | } | 229 | } |
196 | 230 | ||
197 | /* | 231 | /* |
232 | * Function return probe trampoline: | ||
233 | * - init_kprobes() establishes a probepoint here | ||
234 | * - When the probed function returns, this probe | ||
235 | * causes the handlers to fire | ||
236 | */ | ||
237 | void kretprobe_trampoline_holder(void) | ||
238 | { | ||
239 | asm volatile(".global kretprobe_trampoline\n" | ||
240 | "kretprobe_trampoline:\n" | ||
241 | "nop\n"); | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Called when the probe at kretprobe trampoline is hit | ||
246 | */ | ||
247 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | ||
248 | { | ||
249 | struct kretprobe_instance *ri = NULL; | ||
250 | struct hlist_head *head; | ||
251 | struct hlist_node *node, *tmp; | ||
252 | unsigned long orig_ret_address = 0; | ||
253 | unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; | ||
254 | |||
255 | head = kretprobe_inst_table_head(current); | ||
256 | |||
257 | /* | ||
258 | * It is possible to have multiple instances associated with a given | ||
259 | * task either because an multiple functions in the call path | ||
260 | * have a return probe installed on them, and/or more then one return | ||
261 | * return probe was registered for a target function. | ||
262 | * | ||
263 | * We can handle this because: | ||
264 | * - instances are always inserted at the head of the list | ||
265 | * - when multiple return probes are registered for the same | ||
266 | * function, the first instance's ret_addr will point to the | ||
267 | * real return address, and all the rest will point to | ||
268 | * kretprobe_trampoline | ||
269 | */ | ||
270 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | ||
271 | if (ri->task != current) | ||
272 | /* another task is sharing our hash bucket */ | ||
273 | continue; | ||
274 | |||
275 | if (ri->rp && ri->rp->handler) | ||
276 | ri->rp->handler(ri, regs); | ||
277 | |||
278 | orig_ret_address = (unsigned long)ri->ret_addr; | ||
279 | recycle_rp_inst(ri); | ||
280 | |||
281 | if (orig_ret_address != trampoline_address) | ||
282 | /* | ||
283 | * This is the real return address. Any other | ||
284 | * instances associated with this task are for | ||
285 | * other calls deeper on the call stack | ||
286 | */ | ||
287 | break; | ||
288 | } | ||
289 | |||
290 | BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); | ||
291 | regs->nip = orig_ret_address; | ||
292 | |||
293 | unlock_kprobes(); | ||
294 | |||
295 | /* | ||
296 | * By returning a non-zero value, we are telling | ||
297 | * kprobe_handler() that we have handled unlocking | ||
298 | * and re-enabling preemption. | ||
299 | */ | ||
300 | return 1; | ||
301 | } | ||
302 | |||
303 | /* | ||
198 | * Called after single-stepping. p->addr is the address of the | 304 | * Called after single-stepping. p->addr is the address of the |
199 | * instruction whose first byte has been replaced by the "breakpoint" | 305 | * instruction whose first byte has been replaced by the "breakpoint" |
200 | * instruction. To avoid the SMP problems that can occur when we | 306 | * instruction. To avoid the SMP problems that can occur when we |
@@ -205,9 +311,10 @@ no_kprobe: | |||
205 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) | 311 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) |
206 | { | 312 | { |
207 | int ret; | 313 | int ret; |
314 | unsigned int insn = *p->ainsn.insn; | ||
208 | 315 | ||
209 | regs->nip = (unsigned long)p->addr; | 316 | regs->nip = (unsigned long)p->addr; |
210 | ret = emulate_step(regs, p->ainsn.insn[0]); | 317 | ret = emulate_step(regs, insn); |
211 | if (ret == 0) | 318 | if (ret == 0) |
212 | regs->nip = (unsigned long)p->addr + 4; | 319 | regs->nip = (unsigned long)p->addr + 4; |
213 | } | 320 | } |
@@ -331,3 +438,13 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
331 | memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs)); | 438 | memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs)); |
332 | return 1; | 439 | return 1; |
333 | } | 440 | } |
441 | |||
442 | static struct kprobe trampoline_p = { | ||
443 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, | ||
444 | .pre_handler = trampoline_probe_handler | ||
445 | }; | ||
446 | |||
447 | int __init arch_init(void) | ||
448 | { | ||
449 | return register_kprobe(&trampoline_p); | ||
450 | } | ||
diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c index b230a63fe4c8..705742f4eec6 100644 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ b/arch/ppc64/kernel/ppc_ksyms.c | |||
@@ -75,6 +75,7 @@ EXPORT_SYMBOL(giveup_fpu); | |||
75 | EXPORT_SYMBOL(giveup_altivec); | 75 | EXPORT_SYMBOL(giveup_altivec); |
76 | #endif | 76 | #endif |
77 | EXPORT_SYMBOL(__flush_icache_range); | 77 | EXPORT_SYMBOL(__flush_icache_range); |
78 | EXPORT_SYMBOL(flush_dcache_range); | ||
78 | 79 | ||
79 | #ifdef CONFIG_SMP | 80 | #ifdef CONFIG_SMP |
80 | #ifdef CONFIG_PPC_ISERIES | 81 | #ifdef CONFIG_PPC_ISERIES |
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c index aba89554d89d..f7cae05e40fb 100644 --- a/arch/ppc64/kernel/process.c +++ b/arch/ppc64/kernel/process.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/kallsyms.h> | 36 | #include <linux/kallsyms.h> |
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/utsname.h> | 38 | #include <linux/utsname.h> |
39 | #include <linux/kprobes.h> | ||
39 | 40 | ||
40 | #include <asm/pgtable.h> | 41 | #include <asm/pgtable.h> |
41 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
@@ -307,6 +308,8 @@ void show_regs(struct pt_regs * regs) | |||
307 | 308 | ||
308 | void exit_thread(void) | 309 | void exit_thread(void) |
309 | { | 310 | { |
311 | kprobe_flush_task(current); | ||
312 | |||
310 | #ifndef CONFIG_SMP | 313 | #ifndef CONFIG_SMP |
311 | if (last_task_used_math == current) | 314 | if (last_task_used_math == current) |
312 | last_task_used_math = NULL; | 315 | last_task_used_math = NULL; |
@@ -321,6 +324,7 @@ void flush_thread(void) | |||
321 | { | 324 | { |
322 | struct thread_info *t = current_thread_info(); | 325 | struct thread_info *t = current_thread_info(); |
323 | 326 | ||
327 | kprobe_flush_task(current); | ||
324 | if (t->flags & _TIF_ABI_PENDING) | 328 | if (t->flags & _TIF_ABI_PENDING) |
325 | t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); | 329 | t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); |
326 | 330 | ||
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 2348a75e050d..2a532db9138a 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c | |||
@@ -91,6 +91,7 @@ unsigned long tb_to_xs; | |||
91 | unsigned tb_to_us; | 91 | unsigned tb_to_us; |
92 | unsigned long processor_freq; | 92 | unsigned long processor_freq; |
93 | DEFINE_SPINLOCK(rtc_lock); | 93 | DEFINE_SPINLOCK(rtc_lock); |
94 | EXPORT_SYMBOL_GPL(rtc_lock); | ||
94 | 95 | ||
95 | unsigned long tb_to_ns_scale; | 96 | unsigned long tb_to_ns_scale; |
96 | unsigned long tb_to_ns_shift; | 97 | unsigned long tb_to_ns_shift; |
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 4e680f87a75f..acd2a778ebe6 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/string.h> | 38 | #include <linux/string.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/preempt.h> | 40 | #include <linux/preempt.h> |
41 | #include <linux/moduleloader.h> | 41 | |
42 | #include <asm/cacheflush.h> | 42 | #include <asm/cacheflush.h> |
43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
44 | #include <asm/kdebug.h> | 44 | #include <asm/kdebug.h> |
@@ -51,8 +51,6 @@ static struct kprobe *kprobe_prev; | |||
51 | static unsigned long kprobe_status_prev, kprobe_old_rflags_prev, kprobe_saved_rflags_prev; | 51 | static unsigned long kprobe_status_prev, kprobe_old_rflags_prev, kprobe_saved_rflags_prev; |
52 | static struct pt_regs jprobe_saved_regs; | 52 | static struct pt_regs jprobe_saved_regs; |
53 | static long *jprobe_saved_rsp; | 53 | static long *jprobe_saved_rsp; |
54 | static kprobe_opcode_t *get_insn_slot(void); | ||
55 | static void free_insn_slot(kprobe_opcode_t *slot); | ||
56 | void jprobe_return_end(void); | 54 | void jprobe_return_end(void); |
57 | 55 | ||
58 | /* copy of the kernel stack at the probe fire time */ | 56 | /* copy of the kernel stack at the probe fire time */ |
@@ -274,48 +272,23 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | |||
274 | regs->rip = (unsigned long)p->ainsn.insn; | 272 | regs->rip = (unsigned long)p->ainsn.insn; |
275 | } | 273 | } |
276 | 274 | ||
277 | struct task_struct *arch_get_kprobe_task(void *ptr) | ||
278 | { | ||
279 | return ((struct thread_info *) (((unsigned long) ptr) & | ||
280 | (~(THREAD_SIZE -1))))->task; | ||
281 | } | ||
282 | |||
283 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | 275 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) |
284 | { | 276 | { |
285 | unsigned long *sara = (unsigned long *)regs->rsp; | 277 | unsigned long *sara = (unsigned long *)regs->rsp; |
286 | struct kretprobe_instance *ri; | 278 | struct kretprobe_instance *ri; |
287 | static void *orig_ret_addr; | 279 | |
280 | if ((ri = get_free_rp_inst(rp)) != NULL) { | ||
281 | ri->rp = rp; | ||
282 | ri->task = current; | ||
283 | ri->ret_addr = (kprobe_opcode_t *) *sara; | ||
288 | 284 | ||
289 | /* | ||
290 | * Save the return address when the return probe hits | ||
291 | * the first time, and use it to populate the (krprobe | ||
292 | * instance)->ret_addr for subsequent return probes at | ||
293 | * the same addrress since stack address would have | ||
294 | * the kretprobe_trampoline by then. | ||
295 | */ | ||
296 | if (((void*) *sara) != kretprobe_trampoline) | ||
297 | orig_ret_addr = (void*) *sara; | ||
298 | |||
299 | if ((ri = get_free_rp_inst(rp)) != NULL) { | ||
300 | ri->rp = rp; | ||
301 | ri->stack_addr = sara; | ||
302 | ri->ret_addr = orig_ret_addr; | ||
303 | add_rp_inst(ri); | ||
304 | /* Replace the return addr with trampoline addr */ | 285 | /* Replace the return addr with trampoline addr */ |
305 | *sara = (unsigned long) &kretprobe_trampoline; | 286 | *sara = (unsigned long) &kretprobe_trampoline; |
306 | } else { | ||
307 | rp->nmissed++; | ||
308 | } | ||
309 | } | ||
310 | 287 | ||
311 | void arch_kprobe_flush_task(struct task_struct *tk) | 288 | add_rp_inst(ri); |
312 | { | 289 | } else { |
313 | struct kretprobe_instance *ri; | 290 | rp->nmissed++; |
314 | while ((ri = get_rp_inst_tsk(tk)) != NULL) { | 291 | } |
315 | *((unsigned long *)(ri->stack_addr)) = | ||
316 | (unsigned long) ri->ret_addr; | ||
317 | recycle_rp_inst(ri); | ||
318 | } | ||
319 | } | 292 | } |
320 | 293 | ||
321 | /* | 294 | /* |
@@ -428,36 +401,59 @@ no_kprobe: | |||
428 | */ | 401 | */ |
429 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 402 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
430 | { | 403 | { |
431 | struct task_struct *tsk; | 404 | struct kretprobe_instance *ri = NULL; |
432 | struct kretprobe_instance *ri; | 405 | struct hlist_head *head; |
433 | struct hlist_head *head; | 406 | struct hlist_node *node, *tmp; |
434 | struct hlist_node *node; | 407 | unsigned long orig_ret_address = 0; |
435 | unsigned long *sara = (unsigned long *)regs->rsp - 1; | 408 | unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; |
436 | |||
437 | tsk = arch_get_kprobe_task(sara); | ||
438 | head = kretprobe_inst_table_head(tsk); | ||
439 | |||
440 | hlist_for_each_entry(ri, node, head, hlist) { | ||
441 | if (ri->stack_addr == sara && ri->rp) { | ||
442 | if (ri->rp->handler) | ||
443 | ri->rp->handler(ri, regs); | ||
444 | } | ||
445 | } | ||
446 | return 0; | ||
447 | } | ||
448 | 409 | ||
449 | void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs, | 410 | head = kretprobe_inst_table_head(current); |
450 | unsigned long flags) | ||
451 | { | ||
452 | struct kretprobe_instance *ri; | ||
453 | /* RA already popped */ | ||
454 | unsigned long *sara = ((unsigned long *)regs->rsp) - 1; | ||
455 | 411 | ||
456 | while ((ri = get_rp_inst(sara))) { | 412 | /* |
457 | regs->rip = (unsigned long)ri->ret_addr; | 413 | * It is possible to have multiple instances associated with a given |
414 | * task either because an multiple functions in the call path | ||
415 | * have a return probe installed on them, and/or more then one return | ||
416 | * return probe was registered for a target function. | ||
417 | * | ||
418 | * We can handle this because: | ||
419 | * - instances are always inserted at the head of the list | ||
420 | * - when multiple return probes are registered for the same | ||
421 | * function, the first instance's ret_addr will point to the | ||
422 | * real return address, and all the rest will point to | ||
423 | * kretprobe_trampoline | ||
424 | */ | ||
425 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | ||
426 | if (ri->task != current) | ||
427 | /* another task is sharing our hash bucket */ | ||
428 | continue; | ||
429 | |||
430 | if (ri->rp && ri->rp->handler) | ||
431 | ri->rp->handler(ri, regs); | ||
432 | |||
433 | orig_ret_address = (unsigned long)ri->ret_addr; | ||
458 | recycle_rp_inst(ri); | 434 | recycle_rp_inst(ri); |
435 | |||
436 | if (orig_ret_address != trampoline_address) | ||
437 | /* | ||
438 | * This is the real return address. Any other | ||
439 | * instances associated with this task are for | ||
440 | * other calls deeper on the call stack | ||
441 | */ | ||
442 | break; | ||
459 | } | 443 | } |
460 | regs->eflags &= ~TF_MASK; | 444 | |
445 | BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); | ||
446 | regs->rip = orig_ret_address; | ||
447 | |||
448 | unlock_kprobes(); | ||
449 | preempt_enable_no_resched(); | ||
450 | |||
451 | /* | ||
452 | * By returning a non-zero value, we are telling | ||
453 | * kprobe_handler() that we have handled unlocking | ||
454 | * and re-enabling preemption. | ||
455 | */ | ||
456 | return 1; | ||
461 | } | 457 | } |
462 | 458 | ||
463 | /* | 459 | /* |
@@ -550,8 +546,7 @@ int post_kprobe_handler(struct pt_regs *regs) | |||
550 | current_kprobe->post_handler(current_kprobe, regs, 0); | 546 | current_kprobe->post_handler(current_kprobe, regs, 0); |
551 | } | 547 | } |
552 | 548 | ||
553 | if (current_kprobe->post_handler != trampoline_post_handler) | 549 | resume_execution(current_kprobe, regs); |
554 | resume_execution(current_kprobe, regs); | ||
555 | regs->eflags |= kprobe_saved_rflags; | 550 | regs->eflags |= kprobe_saved_rflags; |
556 | 551 | ||
557 | /* Restore the original saved kprobes variables and continue. */ | 552 | /* Restore the original saved kprobes variables and continue. */ |
@@ -682,111 +677,12 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
682 | return 0; | 677 | return 0; |
683 | } | 678 | } |
684 | 679 | ||
685 | /* | 680 | static struct kprobe trampoline_p = { |
686 | * kprobe->ainsn.insn points to the copy of the instruction to be single-stepped. | 681 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, |
687 | * By default on x86_64, pages we get from kmalloc or vmalloc are not | 682 | .pre_handler = trampoline_probe_handler |
688 | * executable. Single-stepping an instruction on such a page yields an | ||
689 | * oops. So instead of storing the instruction copies in their respective | ||
690 | * kprobe objects, we allocate a page, map it executable, and store all the | ||
691 | * instruction copies there. (We can allocate additional pages if somebody | ||
692 | * inserts a huge number of probes.) Each page can hold up to INSNS_PER_PAGE | ||
693 | * instruction slots, each of which is MAX_INSN_SIZE*sizeof(kprobe_opcode_t) | ||
694 | * bytes. | ||
695 | */ | ||
696 | #define INSNS_PER_PAGE (PAGE_SIZE/(MAX_INSN_SIZE*sizeof(kprobe_opcode_t))) | ||
697 | struct kprobe_insn_page { | ||
698 | struct hlist_node hlist; | ||
699 | kprobe_opcode_t *insns; /* page of instruction slots */ | ||
700 | char slot_used[INSNS_PER_PAGE]; | ||
701 | int nused; | ||
702 | }; | 683 | }; |
703 | 684 | ||
704 | static struct hlist_head kprobe_insn_pages; | 685 | int __init arch_init(void) |
705 | |||
706 | /** | ||
707 | * get_insn_slot() - Find a slot on an executable page for an instruction. | ||
708 | * We allocate an executable page if there's no room on existing ones. | ||
709 | */ | ||
710 | static kprobe_opcode_t *get_insn_slot(void) | ||
711 | { | ||
712 | struct kprobe_insn_page *kip; | ||
713 | struct hlist_node *pos; | ||
714 | |||
715 | hlist_for_each(pos, &kprobe_insn_pages) { | ||
716 | kip = hlist_entry(pos, struct kprobe_insn_page, hlist); | ||
717 | if (kip->nused < INSNS_PER_PAGE) { | ||
718 | int i; | ||
719 | for (i = 0; i < INSNS_PER_PAGE; i++) { | ||
720 | if (!kip->slot_used[i]) { | ||
721 | kip->slot_used[i] = 1; | ||
722 | kip->nused++; | ||
723 | return kip->insns + (i*MAX_INSN_SIZE); | ||
724 | } | ||
725 | } | ||
726 | /* Surprise! No unused slots. Fix kip->nused. */ | ||
727 | kip->nused = INSNS_PER_PAGE; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | /* All out of space. Need to allocate a new page. Use slot 0.*/ | ||
732 | kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL); | ||
733 | if (!kip) { | ||
734 | return NULL; | ||
735 | } | ||
736 | |||
737 | /* | ||
738 | * For the %rip-relative displacement fixups to be doable, we | ||
739 | * need our instruction copy to be within +/- 2GB of any data it | ||
740 | * might access via %rip. That is, within 2GB of where the | ||
741 | * kernel image and loaded module images reside. So we allocate | ||
742 | * a page in the module loading area. | ||
743 | */ | ||
744 | kip->insns = module_alloc(PAGE_SIZE); | ||
745 | if (!kip->insns) { | ||
746 | kfree(kip); | ||
747 | return NULL; | ||
748 | } | ||
749 | INIT_HLIST_NODE(&kip->hlist); | ||
750 | hlist_add_head(&kip->hlist, &kprobe_insn_pages); | ||
751 | memset(kip->slot_used, 0, INSNS_PER_PAGE); | ||
752 | kip->slot_used[0] = 1; | ||
753 | kip->nused = 1; | ||
754 | return kip->insns; | ||
755 | } | ||
756 | |||
757 | /** | ||
758 | * free_insn_slot() - Free instruction slot obtained from get_insn_slot(). | ||
759 | */ | ||
760 | static void free_insn_slot(kprobe_opcode_t *slot) | ||
761 | { | 686 | { |
762 | struct kprobe_insn_page *kip; | 687 | return register_kprobe(&trampoline_p); |
763 | struct hlist_node *pos; | ||
764 | |||
765 | hlist_for_each(pos, &kprobe_insn_pages) { | ||
766 | kip = hlist_entry(pos, struct kprobe_insn_page, hlist); | ||
767 | if (kip->insns <= slot | ||
768 | && slot < kip->insns+(INSNS_PER_PAGE*MAX_INSN_SIZE)) { | ||
769 | int i = (slot - kip->insns) / MAX_INSN_SIZE; | ||
770 | kip->slot_used[i] = 0; | ||
771 | kip->nused--; | ||
772 | if (kip->nused == 0) { | ||
773 | /* | ||
774 | * Page is no longer in use. Free it unless | ||
775 | * it's the last one. We keep the last one | ||
776 | * so as not to have to set it up again the | ||
777 | * next time somebody inserts a probe. | ||
778 | */ | ||
779 | hlist_del(&kip->hlist); | ||
780 | if (hlist_empty(&kprobe_insn_pages)) { | ||
781 | INIT_HLIST_NODE(&kip->hlist); | ||
782 | hlist_add_head(&kip->hlist, | ||
783 | &kprobe_insn_pages); | ||
784 | } else { | ||
785 | module_free(NULL, kip->insns); | ||
786 | kfree(kip); | ||
787 | } | ||
788 | } | ||
789 | return; | ||
790 | } | ||
791 | } | ||
792 | } | 688 | } |
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 1d91271796e5..7577f9d7a75d 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -482,6 +482,33 @@ out: | |||
482 | } | 482 | } |
483 | 483 | ||
484 | /* | 484 | /* |
485 | * This function selects if the context switch from prev to next | ||
486 | * has to tweak the TSC disable bit in the cr4. | ||
487 | */ | ||
488 | static inline void disable_tsc(struct task_struct *prev_p, | ||
489 | struct task_struct *next_p) | ||
490 | { | ||
491 | struct thread_info *prev, *next; | ||
492 | |||
493 | /* | ||
494 | * gcc should eliminate the ->thread_info dereference if | ||
495 | * has_secure_computing returns 0 at compile time (SECCOMP=n). | ||
496 | */ | ||
497 | prev = prev_p->thread_info; | ||
498 | next = next_p->thread_info; | ||
499 | |||
500 | if (has_secure_computing(prev) || has_secure_computing(next)) { | ||
501 | /* slow path here */ | ||
502 | if (has_secure_computing(prev) && | ||
503 | !has_secure_computing(next)) { | ||
504 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
505 | } else if (!has_secure_computing(prev) && | ||
506 | has_secure_computing(next)) | ||
507 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
508 | } | ||
509 | } | ||
510 | |||
511 | /* | ||
485 | * This special macro can be used to load a debugging register | 512 | * This special macro can be used to load a debugging register |
486 | */ | 513 | */ |
487 | #define loaddebug(thread,r) set_debug(thread->debugreg ## r, r) | 514 | #define loaddebug(thread,r) set_debug(thread->debugreg ## r, r) |
@@ -599,6 +626,8 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct * | |||
599 | } | 626 | } |
600 | } | 627 | } |
601 | 628 | ||
629 | disable_tsc(prev_p, next_p); | ||
630 | |||
602 | return prev_p; | 631 | return prev_p; |
603 | } | 632 | } |
604 | 633 | ||
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index 3410b4d294b9..91aeb678135d 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c | |||
@@ -1806,7 +1806,8 @@ static void as_put_request(request_queue_t *q, struct request *rq) | |||
1806 | rq->elevator_private = NULL; | 1806 | rq->elevator_private = NULL; |
1807 | } | 1807 | } |
1808 | 1808 | ||
1809 | static int as_set_request(request_queue_t *q, struct request *rq, int gfp_mask) | 1809 | static int as_set_request(request_queue_t *q, struct request *rq, |
1810 | struct bio *bio, int gfp_mask) | ||
1810 | { | 1811 | { |
1811 | struct as_data *ad = q->elevator->elevator_data; | 1812 | struct as_data *ad = q->elevator->elevator_data; |
1812 | struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask); | 1813 | struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask); |
@@ -1827,7 +1828,7 @@ static int as_set_request(request_queue_t *q, struct request *rq, int gfp_mask) | |||
1827 | return 1; | 1828 | return 1; |
1828 | } | 1829 | } |
1829 | 1830 | ||
1830 | static int as_may_queue(request_queue_t *q, int rw) | 1831 | static int as_may_queue(request_queue_t *q, int rw, struct bio *bio) |
1831 | { | 1832 | { |
1832 | int ret = ELV_MQUEUE_MAY; | 1833 | int ret = ELV_MQUEUE_MAY; |
1833 | struct as_data *ad = q->elevator->elevator_data; | 1834 | struct as_data *ad = q->elevator->elevator_data; |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index abde27027c06..653512b77570 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Disk Array driver for HP SA 5xxx and 6xxx Controllers | 2 | * Disk Array driver for HP SA 5xxx and 6xxx Controllers |
3 | * Copyright 2000, 2002 Hewlett-Packard Development Company, L.P. | 3 | * Copyright 2000, 2005 Hewlett-Packard Development Company, L.P. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -54,7 +54,7 @@ | |||
54 | MODULE_AUTHOR("Hewlett-Packard Company"); | 54 | MODULE_AUTHOR("Hewlett-Packard Company"); |
55 | MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6"); | 55 | MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6"); |
56 | MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" | 56 | MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" |
57 | " SA6i P600 P800 E400"); | 57 | " SA6i P600 P800 E400 E300"); |
58 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
59 | 59 | ||
60 | #include "cciss_cmd.h" | 60 | #include "cciss_cmd.h" |
@@ -85,8 +85,10 @@ static const struct pci_device_id cciss_pci_device_id[] = { | |||
85 | 0x103C, 0x3225, 0, 0, 0}, | 85 | 0x103C, 0x3225, 0, 0, 0}, |
86 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB, | 86 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB, |
87 | 0x103c, 0x3223, 0, 0, 0}, | 87 | 0x103c, 0x3223, 0, 0, 0}, |
88 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB, | 88 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, |
89 | 0x103c, 0x3231, 0, 0, 0}, | 89 | 0x103c, 0x3231, 0, 0, 0}, |
90 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, | ||
91 | 0x103c, 0x3233, 0, 0, 0}, | ||
90 | {0,} | 92 | {0,} |
91 | }; | 93 | }; |
92 | MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); | 94 | MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); |
@@ -110,6 +112,7 @@ static struct board_type products[] = { | |||
110 | { 0x3225103C, "Smart Array P600", &SA5_access}, | 112 | { 0x3225103C, "Smart Array P600", &SA5_access}, |
111 | { 0x3223103C, "Smart Array P800", &SA5_access}, | 113 | { 0x3223103C, "Smart Array P800", &SA5_access}, |
112 | { 0x3231103C, "Smart Array E400", &SA5_access}, | 114 | { 0x3231103C, "Smart Array E400", &SA5_access}, |
115 | { 0x3233103C, "Smart Array E300", &SA5_access}, | ||
113 | }; | 116 | }; |
114 | 117 | ||
115 | /* How long to wait (in millesconds) for board to go into simple mode */ | 118 | /* How long to wait (in millesconds) for board to go into simple mode */ |
@@ -635,6 +638,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, | |||
635 | cciss_pci_info_struct pciinfo; | 638 | cciss_pci_info_struct pciinfo; |
636 | 639 | ||
637 | if (!arg) return -EINVAL; | 640 | if (!arg) return -EINVAL; |
641 | pciinfo.domain = pci_domain_nr(host->pdev->bus); | ||
638 | pciinfo.bus = host->pdev->bus->number; | 642 | pciinfo.bus = host->pdev->bus->number; |
639 | pciinfo.dev_fn = host->pdev->devfn; | 643 | pciinfo.dev_fn = host->pdev->devfn; |
640 | pciinfo.board_id = host->board_id; | 644 | pciinfo.board_id = host->board_id; |
@@ -787,13 +791,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, | |||
787 | luninfo.LunID = drv->LunID; | 791 | luninfo.LunID = drv->LunID; |
788 | luninfo.num_opens = drv->usage_count; | 792 | luninfo.num_opens = drv->usage_count; |
789 | luninfo.num_parts = 0; | 793 | luninfo.num_parts = 0; |
790 | /* count partitions 1 to 15 with sizes > 0 */ | ||
791 | for (i = 0; i < MAX_PART - 1; i++) { | ||
792 | if (!disk->part[i]) | ||
793 | continue; | ||
794 | if (disk->part[i]->nr_sects != 0) | ||
795 | luninfo.num_parts++; | ||
796 | } | ||
797 | if (copy_to_user(argp, &luninfo, | 794 | if (copy_to_user(argp, &luninfo, |
798 | sizeof(LogvolInfo_struct))) | 795 | sizeof(LogvolInfo_struct))) |
799 | return -EFAULT; | 796 | return -EFAULT; |
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index 3ac47dde64da..ff1cc968f96d 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c | |||
@@ -21,22 +21,34 @@ | |||
21 | #include <linux/hash.h> | 21 | #include <linux/hash.h> |
22 | #include <linux/rbtree.h> | 22 | #include <linux/rbtree.h> |
23 | #include <linux/mempool.h> | 23 | #include <linux/mempool.h> |
24 | 24 | #include <linux/ioprio.h> | |
25 | static unsigned long max_elapsed_crq; | 25 | #include <linux/writeback.h> |
26 | static unsigned long max_elapsed_dispatch; | ||
27 | 26 | ||
28 | /* | 27 | /* |
29 | * tunables | 28 | * tunables |
30 | */ | 29 | */ |
31 | static int cfq_quantum = 4; /* max queue in one round of service */ | 30 | static int cfq_quantum = 4; /* max queue in one round of service */ |
32 | static int cfq_queued = 8; /* minimum rq allocate limit per-queue*/ | 31 | static int cfq_queued = 8; /* minimum rq allocate limit per-queue*/ |
33 | static int cfq_service = HZ; /* period over which service is avg */ | 32 | static int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; |
34 | static int cfq_fifo_expire_r = HZ / 2; /* fifo timeout for sync requests */ | ||
35 | static int cfq_fifo_expire_w = 5 * HZ; /* fifo timeout for async requests */ | ||
36 | static int cfq_fifo_rate = HZ / 8; /* fifo expiry rate */ | ||
37 | static int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ | 33 | static int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ |
38 | static int cfq_back_penalty = 2; /* penalty of a backwards seek */ | 34 | static int cfq_back_penalty = 2; /* penalty of a backwards seek */ |
39 | 35 | ||
36 | static int cfq_slice_sync = HZ / 10; | ||
37 | static int cfq_slice_async = HZ / 25; | ||
38 | static int cfq_slice_async_rq = 2; | ||
39 | static int cfq_slice_idle = HZ / 100; | ||
40 | |||
41 | #define CFQ_IDLE_GRACE (HZ / 10) | ||
42 | #define CFQ_SLICE_SCALE (5) | ||
43 | |||
44 | #define CFQ_KEY_ASYNC (0) | ||
45 | #define CFQ_KEY_ANY (0xffff) | ||
46 | |||
47 | /* | ||
48 | * disable queueing at the driver/hardware level | ||
49 | */ | ||
50 | static int cfq_max_depth = 1; | ||
51 | |||
40 | /* | 52 | /* |
41 | * for the hash of cfqq inside the cfqd | 53 | * for the hash of cfqq inside the cfqd |
42 | */ | 54 | */ |
@@ -55,6 +67,7 @@ static int cfq_back_penalty = 2; /* penalty of a backwards seek */ | |||
55 | #define list_entry_hash(ptr) hlist_entry((ptr), struct cfq_rq, hash) | 67 | #define list_entry_hash(ptr) hlist_entry((ptr), struct cfq_rq, hash) |
56 | 68 | ||
57 | #define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list) | 69 | #define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list) |
70 | #define list_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) | ||
58 | 71 | ||
59 | #define RQ_DATA(rq) (rq)->elevator_private | 72 | #define RQ_DATA(rq) (rq)->elevator_private |
60 | 73 | ||
@@ -75,78 +88,110 @@ static int cfq_back_penalty = 2; /* penalty of a backwards seek */ | |||
75 | #define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) | 88 | #define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) |
76 | #define rq_rb_key(rq) (rq)->sector | 89 | #define rq_rb_key(rq) (rq)->sector |
77 | 90 | ||
78 | /* | ||
79 | * threshold for switching off non-tag accounting | ||
80 | */ | ||
81 | #define CFQ_MAX_TAG (4) | ||
82 | |||
83 | /* | ||
84 | * sort key types and names | ||
85 | */ | ||
86 | enum { | ||
87 | CFQ_KEY_PGID, | ||
88 | CFQ_KEY_TGID, | ||
89 | CFQ_KEY_UID, | ||
90 | CFQ_KEY_GID, | ||
91 | CFQ_KEY_LAST, | ||
92 | }; | ||
93 | |||
94 | static char *cfq_key_types[] = { "pgid", "tgid", "uid", "gid", NULL }; | ||
95 | |||
96 | static kmem_cache_t *crq_pool; | 91 | static kmem_cache_t *crq_pool; |
97 | static kmem_cache_t *cfq_pool; | 92 | static kmem_cache_t *cfq_pool; |
98 | static kmem_cache_t *cfq_ioc_pool; | 93 | static kmem_cache_t *cfq_ioc_pool; |
99 | 94 | ||
95 | #define CFQ_PRIO_LISTS IOPRIO_BE_NR | ||
96 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) | ||
97 | #define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE) | ||
98 | #define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) | ||
99 | |||
100 | #define ASYNC (0) | ||
101 | #define SYNC (1) | ||
102 | |||
103 | #define cfq_cfqq_dispatched(cfqq) \ | ||
104 | ((cfqq)->on_dispatch[ASYNC] + (cfqq)->on_dispatch[SYNC]) | ||
105 | |||
106 | #define cfq_cfqq_class_sync(cfqq) ((cfqq)->key != CFQ_KEY_ASYNC) | ||
107 | |||
108 | #define cfq_cfqq_sync(cfqq) \ | ||
109 | (cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC]) | ||
110 | |||
111 | /* | ||
112 | * Per block device queue structure | ||
113 | */ | ||
100 | struct cfq_data { | 114 | struct cfq_data { |
101 | struct list_head rr_list; | 115 | atomic_t ref; |
116 | request_queue_t *queue; | ||
117 | |||
118 | /* | ||
119 | * rr list of queues with requests and the count of them | ||
120 | */ | ||
121 | struct list_head rr_list[CFQ_PRIO_LISTS]; | ||
122 | struct list_head busy_rr; | ||
123 | struct list_head cur_rr; | ||
124 | struct list_head idle_rr; | ||
125 | unsigned int busy_queues; | ||
126 | |||
127 | /* | ||
128 | * non-ordered list of empty cfqq's | ||
129 | */ | ||
102 | struct list_head empty_list; | 130 | struct list_head empty_list; |
103 | 131 | ||
132 | /* | ||
133 | * cfqq lookup hash | ||
134 | */ | ||
104 | struct hlist_head *cfq_hash; | 135 | struct hlist_head *cfq_hash; |
105 | struct hlist_head *crq_hash; | ||
106 | 136 | ||
107 | /* queues on rr_list (ie they have pending requests */ | 137 | /* |
108 | unsigned int busy_queues; | 138 | * global crq hash for all queues |
139 | */ | ||
140 | struct hlist_head *crq_hash; | ||
109 | 141 | ||
110 | unsigned int max_queued; | 142 | unsigned int max_queued; |
111 | 143 | ||
112 | atomic_t ref; | 144 | mempool_t *crq_pool; |
113 | 145 | ||
114 | int key_type; | 146 | int rq_in_driver; |
115 | 147 | ||
116 | mempool_t *crq_pool; | 148 | /* |
149 | * schedule slice state info | ||
150 | */ | ||
151 | /* | ||
152 | * idle window management | ||
153 | */ | ||
154 | struct timer_list idle_slice_timer; | ||
155 | struct work_struct unplug_work; | ||
117 | 156 | ||
118 | request_queue_t *queue; | 157 | struct cfq_queue *active_queue; |
158 | struct cfq_io_context *active_cic; | ||
159 | int cur_prio, cur_end_prio; | ||
160 | unsigned int dispatch_slice; | ||
161 | |||
162 | struct timer_list idle_class_timer; | ||
119 | 163 | ||
120 | sector_t last_sector; | 164 | sector_t last_sector; |
165 | unsigned long last_end_request; | ||
121 | 166 | ||
122 | int rq_in_driver; | 167 | unsigned int rq_starved; |
123 | 168 | ||
124 | /* | 169 | /* |
125 | * tunables, see top of file | 170 | * tunables, see top of file |
126 | */ | 171 | */ |
127 | unsigned int cfq_quantum; | 172 | unsigned int cfq_quantum; |
128 | unsigned int cfq_queued; | 173 | unsigned int cfq_queued; |
129 | unsigned int cfq_fifo_expire_r; | 174 | unsigned int cfq_fifo_expire[2]; |
130 | unsigned int cfq_fifo_expire_w; | ||
131 | unsigned int cfq_fifo_batch_expire; | ||
132 | unsigned int cfq_back_penalty; | 175 | unsigned int cfq_back_penalty; |
133 | unsigned int cfq_back_max; | 176 | unsigned int cfq_back_max; |
134 | unsigned int find_best_crq; | 177 | unsigned int cfq_slice[2]; |
135 | 178 | unsigned int cfq_slice_async_rq; | |
136 | unsigned int cfq_tagged; | 179 | unsigned int cfq_slice_idle; |
180 | unsigned int cfq_max_depth; | ||
137 | }; | 181 | }; |
138 | 182 | ||
183 | /* | ||
184 | * Per process-grouping structure | ||
185 | */ | ||
139 | struct cfq_queue { | 186 | struct cfq_queue { |
140 | /* reference count */ | 187 | /* reference count */ |
141 | atomic_t ref; | 188 | atomic_t ref; |
142 | /* parent cfq_data */ | 189 | /* parent cfq_data */ |
143 | struct cfq_data *cfqd; | 190 | struct cfq_data *cfqd; |
144 | /* hash of mergeable requests */ | 191 | /* cfqq lookup hash */ |
145 | struct hlist_node cfq_hash; | 192 | struct hlist_node cfq_hash; |
146 | /* hash key */ | 193 | /* hash key */ |
147 | unsigned long key; | 194 | unsigned int key; |
148 | /* whether queue is on rr (or empty) list */ | ||
149 | int on_rr; | ||
150 | /* on either rr or empty list of cfqd */ | 195 | /* on either rr or empty list of cfqd */ |
151 | struct list_head cfq_list; | 196 | struct list_head cfq_list; |
152 | /* sorted list of pending requests */ | 197 | /* sorted list of pending requests */ |
@@ -158,21 +203,22 @@ struct cfq_queue { | |||
158 | /* currently allocated requests */ | 203 | /* currently allocated requests */ |
159 | int allocated[2]; | 204 | int allocated[2]; |
160 | /* fifo list of requests in sort_list */ | 205 | /* fifo list of requests in sort_list */ |
161 | struct list_head fifo[2]; | 206 | struct list_head fifo; |
162 | /* last time fifo expired */ | ||
163 | unsigned long last_fifo_expire; | ||
164 | 207 | ||
165 | int key_type; | 208 | unsigned long slice_start; |
209 | unsigned long slice_end; | ||
210 | unsigned long slice_left; | ||
211 | unsigned long service_last; | ||
166 | 212 | ||
167 | unsigned long service_start; | 213 | /* number of requests that are on the dispatch list */ |
168 | unsigned long service_used; | 214 | int on_dispatch[2]; |
169 | 215 | ||
170 | unsigned int max_rate; | 216 | /* io prio of this group */ |
217 | unsigned short ioprio, org_ioprio; | ||
218 | unsigned short ioprio_class, org_ioprio_class; | ||
171 | 219 | ||
172 | /* number of requests that have been handed to the driver */ | 220 | /* various state flags, see below */ |
173 | int in_flight; | 221 | unsigned int flags; |
174 | /* number of currently allocated requests */ | ||
175 | int alloc_limit[2]; | ||
176 | }; | 222 | }; |
177 | 223 | ||
178 | struct cfq_rq { | 224 | struct cfq_rq { |
@@ -184,42 +230,79 @@ struct cfq_rq { | |||
184 | struct cfq_queue *cfq_queue; | 230 | struct cfq_queue *cfq_queue; |
185 | struct cfq_io_context *io_context; | 231 | struct cfq_io_context *io_context; |
186 | 232 | ||
187 | unsigned long service_start; | 233 | unsigned int crq_flags; |
188 | unsigned long queue_start; | 234 | }; |
235 | |||
236 | enum cfqq_state_flags { | ||
237 | CFQ_CFQQ_FLAG_on_rr = 0, | ||
238 | CFQ_CFQQ_FLAG_wait_request, | ||
239 | CFQ_CFQQ_FLAG_must_alloc, | ||
240 | CFQ_CFQQ_FLAG_must_alloc_slice, | ||
241 | CFQ_CFQQ_FLAG_must_dispatch, | ||
242 | CFQ_CFQQ_FLAG_fifo_expire, | ||
243 | CFQ_CFQQ_FLAG_idle_window, | ||
244 | CFQ_CFQQ_FLAG_prio_changed, | ||
245 | CFQ_CFQQ_FLAG_expired, | ||
246 | }; | ||
189 | 247 | ||
190 | unsigned int in_flight : 1; | 248 | #define CFQ_CFQQ_FNS(name) \ |
191 | unsigned int accounted : 1; | 249 | static inline void cfq_mark_cfqq_##name(struct cfq_queue *cfqq) \ |
192 | unsigned int is_sync : 1; | 250 | { \ |
193 | unsigned int is_write : 1; | 251 | cfqq->flags |= (1 << CFQ_CFQQ_FLAG_##name); \ |
252 | } \ | ||
253 | static inline void cfq_clear_cfqq_##name(struct cfq_queue *cfqq) \ | ||
254 | { \ | ||
255 | cfqq->flags &= ~(1 << CFQ_CFQQ_FLAG_##name); \ | ||
256 | } \ | ||
257 | static inline int cfq_cfqq_##name(const struct cfq_queue *cfqq) \ | ||
258 | { \ | ||
259 | return (cfqq->flags & (1 << CFQ_CFQQ_FLAG_##name)) != 0; \ | ||
260 | } | ||
261 | |||
262 | CFQ_CFQQ_FNS(on_rr); | ||
263 | CFQ_CFQQ_FNS(wait_request); | ||
264 | CFQ_CFQQ_FNS(must_alloc); | ||
265 | CFQ_CFQQ_FNS(must_alloc_slice); | ||
266 | CFQ_CFQQ_FNS(must_dispatch); | ||
267 | CFQ_CFQQ_FNS(fifo_expire); | ||
268 | CFQ_CFQQ_FNS(idle_window); | ||
269 | CFQ_CFQQ_FNS(prio_changed); | ||
270 | CFQ_CFQQ_FNS(expired); | ||
271 | #undef CFQ_CFQQ_FNS | ||
272 | |||
273 | enum cfq_rq_state_flags { | ||
274 | CFQ_CRQ_FLAG_in_flight = 0, | ||
275 | CFQ_CRQ_FLAG_in_driver, | ||
276 | CFQ_CRQ_FLAG_is_sync, | ||
277 | CFQ_CRQ_FLAG_requeued, | ||
194 | }; | 278 | }; |
195 | 279 | ||
196 | static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned long); | 280 | #define CFQ_CRQ_FNS(name) \ |
281 | static inline void cfq_mark_crq_##name(struct cfq_rq *crq) \ | ||
282 | { \ | ||
283 | crq->crq_flags |= (1 << CFQ_CRQ_FLAG_##name); \ | ||
284 | } \ | ||
285 | static inline void cfq_clear_crq_##name(struct cfq_rq *crq) \ | ||
286 | { \ | ||
287 | crq->crq_flags &= ~(1 << CFQ_CRQ_FLAG_##name); \ | ||
288 | } \ | ||
289 | static inline int cfq_crq_##name(const struct cfq_rq *crq) \ | ||
290 | { \ | ||
291 | return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0; \ | ||
292 | } | ||
293 | |||
294 | CFQ_CRQ_FNS(in_flight); | ||
295 | CFQ_CRQ_FNS(in_driver); | ||
296 | CFQ_CRQ_FNS(is_sync); | ||
297 | CFQ_CRQ_FNS(requeued); | ||
298 | #undef CFQ_CRQ_FNS | ||
299 | |||
300 | static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); | ||
197 | static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *); | 301 | static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *); |
198 | static void cfq_update_next_crq(struct cfq_rq *); | ||
199 | static void cfq_put_cfqd(struct cfq_data *cfqd); | 302 | static void cfq_put_cfqd(struct cfq_data *cfqd); |
303 | static inline int cfq_pending_requests(struct cfq_data *cfqd); | ||
200 | 304 | ||
201 | /* | 305 | #define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) |
202 | * what the fairness is based on (ie how processes are grouped and | ||
203 | * differentiated) | ||
204 | */ | ||
205 | static inline unsigned long | ||
206 | cfq_hash_key(struct cfq_data *cfqd, struct task_struct *tsk) | ||
207 | { | ||
208 | /* | ||
209 | * optimize this so that ->key_type is the offset into the struct | ||
210 | */ | ||
211 | switch (cfqd->key_type) { | ||
212 | case CFQ_KEY_PGID: | ||
213 | return process_group(tsk); | ||
214 | default: | ||
215 | case CFQ_KEY_TGID: | ||
216 | return tsk->tgid; | ||
217 | case CFQ_KEY_UID: | ||
218 | return tsk->uid; | ||
219 | case CFQ_KEY_GID: | ||
220 | return tsk->gid; | ||
221 | } | ||
222 | } | ||
223 | 306 | ||
224 | /* | 307 | /* |
225 | * lots of deadline iosched dupes, can be abstracted later... | 308 | * lots of deadline iosched dupes, can be abstracted later... |
@@ -235,16 +318,12 @@ static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq) | |||
235 | 318 | ||
236 | if (q->last_merge == crq->request) | 319 | if (q->last_merge == crq->request) |
237 | q->last_merge = NULL; | 320 | q->last_merge = NULL; |
238 | |||
239 | cfq_update_next_crq(crq); | ||
240 | } | 321 | } |
241 | 322 | ||
242 | static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq) | 323 | static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq) |
243 | { | 324 | { |
244 | const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request)); | 325 | const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request)); |
245 | 326 | ||
246 | BUG_ON(!hlist_unhashed(&crq->hash)); | ||
247 | |||
248 | hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]); | 327 | hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]); |
249 | } | 328 | } |
250 | 329 | ||
@@ -257,8 +336,6 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) | |||
257 | struct cfq_rq *crq = list_entry_hash(entry); | 336 | struct cfq_rq *crq = list_entry_hash(entry); |
258 | struct request *__rq = crq->request; | 337 | struct request *__rq = crq->request; |
259 | 338 | ||
260 | BUG_ON(hlist_unhashed(&crq->hash)); | ||
261 | |||
262 | if (!rq_mergeable(__rq)) { | 339 | if (!rq_mergeable(__rq)) { |
263 | cfq_del_crq_hash(crq); | 340 | cfq_del_crq_hash(crq); |
264 | continue; | 341 | continue; |
@@ -287,36 +364,16 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) | |||
287 | return crq2; | 364 | return crq2; |
288 | if (crq2 == NULL) | 365 | if (crq2 == NULL) |
289 | return crq1; | 366 | return crq1; |
367 | if (cfq_crq_requeued(crq1)) | ||
368 | return crq1; | ||
369 | if (cfq_crq_requeued(crq2)) | ||
370 | return crq2; | ||
290 | 371 | ||
291 | s1 = crq1->request->sector; | 372 | s1 = crq1->request->sector; |
292 | s2 = crq2->request->sector; | 373 | s2 = crq2->request->sector; |
293 | 374 | ||
294 | last = cfqd->last_sector; | 375 | last = cfqd->last_sector; |
295 | 376 | ||
296 | #if 0 | ||
297 | if (!list_empty(&cfqd->queue->queue_head)) { | ||
298 | struct list_head *entry = &cfqd->queue->queue_head; | ||
299 | unsigned long distance = ~0UL; | ||
300 | struct request *rq; | ||
301 | |||
302 | while ((entry = entry->prev) != &cfqd->queue->queue_head) { | ||
303 | rq = list_entry_rq(entry); | ||
304 | |||
305 | if (blk_barrier_rq(rq)) | ||
306 | break; | ||
307 | |||
308 | if (distance < abs(s1 - rq->sector + rq->nr_sectors)) { | ||
309 | distance = abs(s1 - rq->sector +rq->nr_sectors); | ||
310 | last = rq->sector + rq->nr_sectors; | ||
311 | } | ||
312 | if (distance < abs(s2 - rq->sector + rq->nr_sectors)) { | ||
313 | distance = abs(s2 - rq->sector +rq->nr_sectors); | ||
314 | last = rq->sector + rq->nr_sectors; | ||
315 | } | ||
316 | } | ||
317 | } | ||
318 | #endif | ||
319 | |||
320 | /* | 377 | /* |
321 | * by definition, 1KiB is 2 sectors | 378 | * by definition, 1KiB is 2 sectors |
322 | */ | 379 | */ |
@@ -377,11 +434,14 @@ cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
377 | struct cfq_rq *crq_next = NULL, *crq_prev = NULL; | 434 | struct cfq_rq *crq_next = NULL, *crq_prev = NULL; |
378 | struct rb_node *rbnext, *rbprev; | 435 | struct rb_node *rbnext, *rbprev; |
379 | 436 | ||
380 | if (!ON_RB(&last->rb_node)) | 437 | rbnext = NULL; |
381 | return NULL; | 438 | if (ON_RB(&last->rb_node)) |
382 | 439 | rbnext = rb_next(&last->rb_node); | |
383 | if ((rbnext = rb_next(&last->rb_node)) == NULL) | 440 | if (!rbnext) { |
384 | rbnext = rb_first(&cfqq->sort_list); | 441 | rbnext = rb_first(&cfqq->sort_list); |
442 | if (rbnext == &last->rb_node) | ||
443 | rbnext = NULL; | ||
444 | } | ||
385 | 445 | ||
386 | rbprev = rb_prev(&last->rb_node); | 446 | rbprev = rb_prev(&last->rb_node); |
387 | 447 | ||
@@ -401,67 +461,53 @@ static void cfq_update_next_crq(struct cfq_rq *crq) | |||
401 | cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq); | 461 | cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq); |
402 | } | 462 | } |
403 | 463 | ||
404 | static int cfq_check_sort_rr_list(struct cfq_queue *cfqq) | 464 | static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) |
405 | { | 465 | { |
406 | struct list_head *head = &cfqq->cfqd->rr_list; | 466 | struct cfq_data *cfqd = cfqq->cfqd; |
407 | struct list_head *next, *prev; | 467 | struct list_head *list, *entry; |
408 | |||
409 | /* | ||
410 | * list might still be ordered | ||
411 | */ | ||
412 | next = cfqq->cfq_list.next; | ||
413 | if (next != head) { | ||
414 | struct cfq_queue *cnext = list_entry_cfqq(next); | ||
415 | 468 | ||
416 | if (cfqq->service_used > cnext->service_used) | 469 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); |
417 | return 1; | ||
418 | } | ||
419 | 470 | ||
420 | prev = cfqq->cfq_list.prev; | 471 | list_del(&cfqq->cfq_list); |
421 | if (prev != head) { | ||
422 | struct cfq_queue *cprev = list_entry_cfqq(prev); | ||
423 | 472 | ||
424 | if (cfqq->service_used < cprev->service_used) | 473 | if (cfq_class_rt(cfqq)) |
425 | return 1; | 474 | list = &cfqd->cur_rr; |
475 | else if (cfq_class_idle(cfqq)) | ||
476 | list = &cfqd->idle_rr; | ||
477 | else { | ||
478 | /* | ||
479 | * if cfqq has requests in flight, don't allow it to be | ||
480 | * found in cfq_set_active_queue before it has finished them. | ||
481 | * this is done to increase fairness between a process that | ||
482 | * has lots of io pending vs one that only generates one | ||
483 | * sporadically or synchronously | ||
484 | */ | ||
485 | if (cfq_cfqq_dispatched(cfqq)) | ||
486 | list = &cfqd->busy_rr; | ||
487 | else | ||
488 | list = &cfqd->rr_list[cfqq->ioprio]; | ||
426 | } | 489 | } |
427 | 490 | ||
428 | return 0; | 491 | /* |
429 | } | 492 | * if queue was preempted, just add to front to be fair. busy_rr |
430 | 493 | * isn't sorted. | |
431 | static void cfq_sort_rr_list(struct cfq_queue *cfqq, int new_queue) | 494 | */ |
432 | { | 495 | if (preempted || list == &cfqd->busy_rr) { |
433 | struct list_head *entry = &cfqq->cfqd->rr_list; | 496 | list_add(&cfqq->cfq_list, list); |
434 | |||
435 | if (!cfqq->on_rr) | ||
436 | return; | ||
437 | if (!new_queue && !cfq_check_sort_rr_list(cfqq)) | ||
438 | return; | 497 | return; |
439 | 498 | } | |
440 | list_del(&cfqq->cfq_list); | ||
441 | 499 | ||
442 | /* | 500 | /* |
443 | * sort by our mean service_used, sub-sort by in-flight requests | 501 | * sort by when queue was last serviced |
444 | */ | 502 | */ |
445 | while ((entry = entry->prev) != &cfqq->cfqd->rr_list) { | 503 | entry = list; |
504 | while ((entry = entry->prev) != list) { | ||
446 | struct cfq_queue *__cfqq = list_entry_cfqq(entry); | 505 | struct cfq_queue *__cfqq = list_entry_cfqq(entry); |
447 | 506 | ||
448 | if (cfqq->service_used > __cfqq->service_used) | 507 | if (!__cfqq->service_last) |
508 | break; | ||
509 | if (time_before(__cfqq->service_last, cfqq->service_last)) | ||
449 | break; | 510 | break; |
450 | else if (cfqq->service_used == __cfqq->service_used) { | ||
451 | struct list_head *prv; | ||
452 | |||
453 | while ((prv = entry->prev) != &cfqq->cfqd->rr_list) { | ||
454 | __cfqq = list_entry_cfqq(prv); | ||
455 | |||
456 | WARN_ON(__cfqq->service_used > cfqq->service_used); | ||
457 | if (cfqq->service_used != __cfqq->service_used) | ||
458 | break; | ||
459 | if (cfqq->in_flight > __cfqq->in_flight) | ||
460 | break; | ||
461 | |||
462 | entry = prv; | ||
463 | } | ||
464 | } | ||
465 | } | 511 | } |
466 | 512 | ||
467 | list_add(&cfqq->cfq_list, entry); | 513 | list_add(&cfqq->cfq_list, entry); |
@@ -469,28 +515,24 @@ static void cfq_sort_rr_list(struct cfq_queue *cfqq, int new_queue) | |||
469 | 515 | ||
470 | /* | 516 | /* |
471 | * add to busy list of queues for service, trying to be fair in ordering | 517 | * add to busy list of queues for service, trying to be fair in ordering |
472 | * the pending list according to requests serviced | 518 | * the pending list according to last request service |
473 | */ | 519 | */ |
474 | static inline void | 520 | static inline void |
475 | cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 521 | cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq, int requeue) |
476 | { | 522 | { |
477 | /* | 523 | BUG_ON(cfq_cfqq_on_rr(cfqq)); |
478 | * it's currently on the empty list | 524 | cfq_mark_cfqq_on_rr(cfqq); |
479 | */ | ||
480 | cfqq->on_rr = 1; | ||
481 | cfqd->busy_queues++; | 525 | cfqd->busy_queues++; |
482 | 526 | ||
483 | if (time_after(jiffies, cfqq->service_start + cfq_service)) | 527 | cfq_resort_rr_list(cfqq, requeue); |
484 | cfqq->service_used >>= 3; | ||
485 | |||
486 | cfq_sort_rr_list(cfqq, 1); | ||
487 | } | 528 | } |
488 | 529 | ||
489 | static inline void | 530 | static inline void |
490 | cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 531 | cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
491 | { | 532 | { |
533 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); | ||
534 | cfq_clear_cfqq_on_rr(cfqq); | ||
492 | list_move(&cfqq->cfq_list, &cfqd->empty_list); | 535 | list_move(&cfqq->cfq_list, &cfqd->empty_list); |
493 | cfqq->on_rr = 0; | ||
494 | 536 | ||
495 | BUG_ON(!cfqd->busy_queues); | 537 | BUG_ON(!cfqd->busy_queues); |
496 | cfqd->busy_queues--; | 538 | cfqd->busy_queues--; |
@@ -505,16 +547,17 @@ static inline void cfq_del_crq_rb(struct cfq_rq *crq) | |||
505 | 547 | ||
506 | if (ON_RB(&crq->rb_node)) { | 548 | if (ON_RB(&crq->rb_node)) { |
507 | struct cfq_data *cfqd = cfqq->cfqd; | 549 | struct cfq_data *cfqd = cfqq->cfqd; |
550 | const int sync = cfq_crq_is_sync(crq); | ||
508 | 551 | ||
509 | BUG_ON(!cfqq->queued[crq->is_sync]); | 552 | BUG_ON(!cfqq->queued[sync]); |
553 | cfqq->queued[sync]--; | ||
510 | 554 | ||
511 | cfq_update_next_crq(crq); | 555 | cfq_update_next_crq(crq); |
512 | 556 | ||
513 | cfqq->queued[crq->is_sync]--; | ||
514 | rb_erase(&crq->rb_node, &cfqq->sort_list); | 557 | rb_erase(&crq->rb_node, &cfqq->sort_list); |
515 | RB_CLEAR_COLOR(&crq->rb_node); | 558 | RB_CLEAR_COLOR(&crq->rb_node); |
516 | 559 | ||
517 | if (RB_EMPTY(&cfqq->sort_list) && cfqq->on_rr) | 560 | if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list)) |
518 | cfq_del_cfqq_rr(cfqd, cfqq); | 561 | cfq_del_cfqq_rr(cfqd, cfqq); |
519 | } | 562 | } |
520 | } | 563 | } |
@@ -550,7 +593,7 @@ static void cfq_add_crq_rb(struct cfq_rq *crq) | |||
550 | struct cfq_rq *__alias; | 593 | struct cfq_rq *__alias; |
551 | 594 | ||
552 | crq->rb_key = rq_rb_key(rq); | 595 | crq->rb_key = rq_rb_key(rq); |
553 | cfqq->queued[crq->is_sync]++; | 596 | cfqq->queued[cfq_crq_is_sync(crq)]++; |
554 | 597 | ||
555 | /* | 598 | /* |
556 | * looks a little odd, but the first insert might return an alias. | 599 | * looks a little odd, but the first insert might return an alias. |
@@ -561,8 +604,8 @@ static void cfq_add_crq_rb(struct cfq_rq *crq) | |||
561 | 604 | ||
562 | rb_insert_color(&crq->rb_node, &cfqq->sort_list); | 605 | rb_insert_color(&crq->rb_node, &cfqq->sort_list); |
563 | 606 | ||
564 | if (!cfqq->on_rr) | 607 | if (!cfq_cfqq_on_rr(cfqq)) |
565 | cfq_add_cfqq_rr(cfqd, cfqq); | 608 | cfq_add_cfqq_rr(cfqd, cfqq, cfq_crq_requeued(crq)); |
566 | 609 | ||
567 | /* | 610 | /* |
568 | * check if this request is a better next-serve candidate | 611 | * check if this request is a better next-serve candidate |
@@ -575,17 +618,16 @@ cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) | |||
575 | { | 618 | { |
576 | if (ON_RB(&crq->rb_node)) { | 619 | if (ON_RB(&crq->rb_node)) { |
577 | rb_erase(&crq->rb_node, &cfqq->sort_list); | 620 | rb_erase(&crq->rb_node, &cfqq->sort_list); |
578 | cfqq->queued[crq->is_sync]--; | 621 | cfqq->queued[cfq_crq_is_sync(crq)]--; |
579 | } | 622 | } |
580 | 623 | ||
581 | cfq_add_crq_rb(crq); | 624 | cfq_add_crq_rb(crq); |
582 | } | 625 | } |
583 | 626 | ||
584 | static struct request * | 627 | static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) |
585 | cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) | 628 | |
586 | { | 629 | { |
587 | const unsigned long key = cfq_hash_key(cfqd, current); | 630 | struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY); |
588 | struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, key); | ||
589 | struct rb_node *n; | 631 | struct rb_node *n; |
590 | 632 | ||
591 | if (!cfqq) | 633 | if (!cfqq) |
@@ -609,20 +651,25 @@ out: | |||
609 | 651 | ||
610 | static void cfq_deactivate_request(request_queue_t *q, struct request *rq) | 652 | static void cfq_deactivate_request(request_queue_t *q, struct request *rq) |
611 | { | 653 | { |
654 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
612 | struct cfq_rq *crq = RQ_DATA(rq); | 655 | struct cfq_rq *crq = RQ_DATA(rq); |
613 | 656 | ||
614 | if (crq) { | 657 | if (crq) { |
615 | struct cfq_queue *cfqq = crq->cfq_queue; | 658 | struct cfq_queue *cfqq = crq->cfq_queue; |
616 | 659 | ||
617 | if (cfqq->cfqd->cfq_tagged) { | 660 | if (cfq_crq_in_driver(crq)) { |
618 | cfqq->service_used--; | 661 | cfq_clear_crq_in_driver(crq); |
619 | cfq_sort_rr_list(cfqq, 0); | 662 | WARN_ON(!cfqd->rq_in_driver); |
663 | cfqd->rq_in_driver--; | ||
620 | } | 664 | } |
665 | if (cfq_crq_in_flight(crq)) { | ||
666 | const int sync = cfq_crq_is_sync(crq); | ||
621 | 667 | ||
622 | if (crq->accounted) { | 668 | cfq_clear_crq_in_flight(crq); |
623 | crq->accounted = 0; | 669 | WARN_ON(!cfqq->on_dispatch[sync]); |
624 | cfqq->cfqd->rq_in_driver--; | 670 | cfqq->on_dispatch[sync]--; |
625 | } | 671 | } |
672 | cfq_mark_crq_requeued(crq); | ||
626 | } | 673 | } |
627 | } | 674 | } |
628 | 675 | ||
@@ -640,11 +687,10 @@ static void cfq_remove_request(request_queue_t *q, struct request *rq) | |||
640 | struct cfq_rq *crq = RQ_DATA(rq); | 687 | struct cfq_rq *crq = RQ_DATA(rq); |
641 | 688 | ||
642 | if (crq) { | 689 | if (crq) { |
643 | cfq_remove_merge_hints(q, crq); | ||
644 | list_del_init(&rq->queuelist); | 690 | list_del_init(&rq->queuelist); |
691 | cfq_del_crq_rb(crq); | ||
692 | cfq_remove_merge_hints(q, crq); | ||
645 | 693 | ||
646 | if (crq->cfq_queue) | ||
647 | cfq_del_crq_rb(crq); | ||
648 | } | 694 | } |
649 | } | 695 | } |
650 | 696 | ||
@@ -662,21 +708,15 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio) | |||
662 | } | 708 | } |
663 | 709 | ||
664 | __rq = cfq_find_rq_hash(cfqd, bio->bi_sector); | 710 | __rq = cfq_find_rq_hash(cfqd, bio->bi_sector); |
665 | if (__rq) { | 711 | if (__rq && elv_rq_merge_ok(__rq, bio)) { |
666 | BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector); | 712 | ret = ELEVATOR_BACK_MERGE; |
667 | 713 | goto out; | |
668 | if (elv_rq_merge_ok(__rq, bio)) { | ||
669 | ret = ELEVATOR_BACK_MERGE; | ||
670 | goto out; | ||
671 | } | ||
672 | } | 714 | } |
673 | 715 | ||
674 | __rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio)); | 716 | __rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio)); |
675 | if (__rq) { | 717 | if (__rq && elv_rq_merge_ok(__rq, bio)) { |
676 | if (elv_rq_merge_ok(__rq, bio)) { | 718 | ret = ELEVATOR_FRONT_MERGE; |
677 | ret = ELEVATOR_FRONT_MERGE; | 719 | goto out; |
678 | goto out; | ||
679 | } | ||
680 | } | 720 | } |
681 | 721 | ||
682 | return ELEVATOR_NO_MERGE; | 722 | return ELEVATOR_NO_MERGE; |
@@ -709,20 +749,220 @@ static void | |||
709 | cfq_merged_requests(request_queue_t *q, struct request *rq, | 749 | cfq_merged_requests(request_queue_t *q, struct request *rq, |
710 | struct request *next) | 750 | struct request *next) |
711 | { | 751 | { |
712 | struct cfq_rq *crq = RQ_DATA(rq); | ||
713 | struct cfq_rq *cnext = RQ_DATA(next); | ||
714 | |||
715 | cfq_merged_request(q, rq); | 752 | cfq_merged_request(q, rq); |
716 | 753 | ||
717 | if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist)) { | 754 | /* |
718 | if (time_before(cnext->queue_start, crq->queue_start)) { | 755 | * reposition in fifo if next is older than rq |
719 | list_move(&rq->queuelist, &next->queuelist); | 756 | */ |
720 | crq->queue_start = cnext->queue_start; | 757 | if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && |
758 | time_before(next->start_time, rq->start_time)) | ||
759 | list_move(&rq->queuelist, &next->queuelist); | ||
760 | |||
761 | cfq_remove_request(q, next); | ||
762 | } | ||
763 | |||
764 | static inline void | ||
765 | __cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
766 | { | ||
767 | if (cfqq) { | ||
768 | /* | ||
769 | * stop potential idle class queues waiting service | ||
770 | */ | ||
771 | del_timer(&cfqd->idle_class_timer); | ||
772 | |||
773 | cfqq->slice_start = jiffies; | ||
774 | cfqq->slice_end = 0; | ||
775 | cfqq->slice_left = 0; | ||
776 | cfq_clear_cfqq_must_alloc_slice(cfqq); | ||
777 | cfq_clear_cfqq_fifo_expire(cfqq); | ||
778 | cfq_clear_cfqq_expired(cfqq); | ||
779 | } | ||
780 | |||
781 | cfqd->active_queue = cfqq; | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * 0 | ||
786 | * 0,1 | ||
787 | * 0,1,2 | ||
788 | * 0,1,2,3 | ||
789 | * 0,1,2,3,4 | ||
790 | * 0,1,2,3,4,5 | ||
791 | * 0,1,2,3,4,5,6 | ||
792 | * 0,1,2,3,4,5,6,7 | ||
793 | */ | ||
794 | static int cfq_get_next_prio_level(struct cfq_data *cfqd) | ||
795 | { | ||
796 | int prio, wrap; | ||
797 | |||
798 | prio = -1; | ||
799 | wrap = 0; | ||
800 | do { | ||
801 | int p; | ||
802 | |||
803 | for (p = cfqd->cur_prio; p <= cfqd->cur_end_prio; p++) { | ||
804 | if (!list_empty(&cfqd->rr_list[p])) { | ||
805 | prio = p; | ||
806 | break; | ||
807 | } | ||
808 | } | ||
809 | |||
810 | if (prio != -1) | ||
811 | break; | ||
812 | cfqd->cur_prio = 0; | ||
813 | if (++cfqd->cur_end_prio == CFQ_PRIO_LISTS) { | ||
814 | cfqd->cur_end_prio = 0; | ||
815 | if (wrap) | ||
816 | break; | ||
817 | wrap = 1; | ||
721 | } | 818 | } |
819 | } while (1); | ||
820 | |||
821 | if (unlikely(prio == -1)) | ||
822 | return -1; | ||
823 | |||
824 | BUG_ON(prio >= CFQ_PRIO_LISTS); | ||
825 | |||
826 | list_splice_init(&cfqd->rr_list[prio], &cfqd->cur_rr); | ||
827 | |||
828 | cfqd->cur_prio = prio + 1; | ||
829 | if (cfqd->cur_prio > cfqd->cur_end_prio) { | ||
830 | cfqd->cur_end_prio = cfqd->cur_prio; | ||
831 | cfqd->cur_prio = 0; | ||
832 | } | ||
833 | if (cfqd->cur_end_prio == CFQ_PRIO_LISTS) { | ||
834 | cfqd->cur_prio = 0; | ||
835 | cfqd->cur_end_prio = 0; | ||
722 | } | 836 | } |
723 | 837 | ||
724 | cfq_update_next_crq(cnext); | 838 | return prio; |
725 | cfq_remove_request(q, next); | 839 | } |
840 | |||
841 | static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) | ||
842 | { | ||
843 | struct cfq_queue *cfqq; | ||
844 | |||
845 | /* | ||
846 | * if current queue is expired but not done with its requests yet, | ||
847 | * wait for that to happen | ||
848 | */ | ||
849 | if ((cfqq = cfqd->active_queue) != NULL) { | ||
850 | if (cfq_cfqq_expired(cfqq) && cfq_cfqq_dispatched(cfqq)) | ||
851 | return NULL; | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | * if current list is non-empty, grab first entry. if it is empty, | ||
856 | * get next prio level and grab first entry then if any are spliced | ||
857 | */ | ||
858 | if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1) | ||
859 | cfqq = list_entry_cfqq(cfqd->cur_rr.next); | ||
860 | |||
861 | /* | ||
862 | * if we have idle queues and no rt or be queues had pending | ||
863 | * requests, either allow immediate service if the grace period | ||
864 | * has passed or arm the idle grace timer | ||
865 | */ | ||
866 | if (!cfqq && !list_empty(&cfqd->idle_rr)) { | ||
867 | unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE; | ||
868 | |||
869 | if (time_after_eq(jiffies, end)) | ||
870 | cfqq = list_entry_cfqq(cfqd->idle_rr.next); | ||
871 | else | ||
872 | mod_timer(&cfqd->idle_class_timer, end); | ||
873 | } | ||
874 | |||
875 | __cfq_set_active_queue(cfqd, cfqq); | ||
876 | return cfqq; | ||
877 | } | ||
878 | |||
879 | /* | ||
880 | * current cfqq expired its slice (or was too idle), select new one | ||
881 | */ | ||
882 | static void | ||
883 | __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | ||
884 | int preempted) | ||
885 | { | ||
886 | unsigned long now = jiffies; | ||
887 | |||
888 | if (cfq_cfqq_wait_request(cfqq)) | ||
889 | del_timer(&cfqd->idle_slice_timer); | ||
890 | |||
891 | if (!preempted && !cfq_cfqq_dispatched(cfqq)) | ||
892 | cfqq->service_last = now; | ||
893 | |||
894 | cfq_clear_cfqq_must_dispatch(cfqq); | ||
895 | cfq_clear_cfqq_wait_request(cfqq); | ||
896 | |||
897 | /* | ||
898 | * store what was left of this slice, if the queue idled out | ||
899 | * or was preempted | ||
900 | */ | ||
901 | if (time_after(now, cfqq->slice_end)) | ||
902 | cfqq->slice_left = now - cfqq->slice_end; | ||
903 | else | ||
904 | cfqq->slice_left = 0; | ||
905 | |||
906 | if (cfq_cfqq_on_rr(cfqq)) | ||
907 | cfq_resort_rr_list(cfqq, preempted); | ||
908 | |||
909 | if (cfqq == cfqd->active_queue) | ||
910 | cfqd->active_queue = NULL; | ||
911 | |||
912 | if (cfqd->active_cic) { | ||
913 | put_io_context(cfqd->active_cic->ioc); | ||
914 | cfqd->active_cic = NULL; | ||
915 | } | ||
916 | |||
917 | cfqd->dispatch_slice = 0; | ||
918 | } | ||
919 | |||
920 | static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted) | ||
921 | { | ||
922 | struct cfq_queue *cfqq = cfqd->active_queue; | ||
923 | |||
924 | if (cfqq) { | ||
925 | /* | ||
926 | * use deferred expiry, if there are requests in progress as | ||
927 | * not to disturb the slice of the next queue | ||
928 | */ | ||
929 | if (cfq_cfqq_dispatched(cfqq)) | ||
930 | cfq_mark_cfqq_expired(cfqq); | ||
931 | else | ||
932 | __cfq_slice_expired(cfqd, cfqq, preempted); | ||
933 | } | ||
934 | } | ||
935 | |||
936 | static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
937 | |||
938 | { | ||
939 | WARN_ON(!RB_EMPTY(&cfqq->sort_list)); | ||
940 | WARN_ON(cfqq != cfqd->active_queue); | ||
941 | |||
942 | /* | ||
943 | * idle is disabled, either manually or by past process history | ||
944 | */ | ||
945 | if (!cfqd->cfq_slice_idle) | ||
946 | return 0; | ||
947 | if (!cfq_cfqq_idle_window(cfqq)) | ||
948 | return 0; | ||
949 | /* | ||
950 | * task has exited, don't wait | ||
951 | */ | ||
952 | if (cfqd->active_cic && !cfqd->active_cic->ioc->task) | ||
953 | return 0; | ||
954 | |||
955 | cfq_mark_cfqq_must_dispatch(cfqq); | ||
956 | cfq_mark_cfqq_wait_request(cfqq); | ||
957 | |||
958 | if (!timer_pending(&cfqd->idle_slice_timer)) { | ||
959 | unsigned long slice_left = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle); | ||
960 | |||
961 | cfqd->idle_slice_timer.expires = jiffies + slice_left; | ||
962 | add_timer(&cfqd->idle_slice_timer); | ||
963 | } | ||
964 | |||
965 | return 1; | ||
726 | } | 966 | } |
727 | 967 | ||
728 | /* | 968 | /* |
@@ -738,31 +978,40 @@ static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq) | |||
738 | struct request *__rq; | 978 | struct request *__rq; |
739 | sector_t last; | 979 | sector_t last; |
740 | 980 | ||
741 | cfq_del_crq_rb(crq); | ||
742 | cfq_remove_merge_hints(q, crq); | ||
743 | list_del(&crq->request->queuelist); | 981 | list_del(&crq->request->queuelist); |
744 | 982 | ||
745 | last = cfqd->last_sector; | 983 | last = cfqd->last_sector; |
746 | while ((entry = entry->prev) != head) { | 984 | list_for_each_entry_reverse(__rq, head, queuelist) { |
747 | __rq = list_entry_rq(entry); | 985 | struct cfq_rq *__crq = RQ_DATA(__rq); |
748 | 986 | ||
749 | if (blk_barrier_rq(crq->request)) | 987 | if (blk_barrier_rq(__rq)) |
988 | break; | ||
989 | if (!blk_fs_request(__rq)) | ||
750 | break; | 990 | break; |
751 | if (!blk_fs_request(crq->request)) | 991 | if (cfq_crq_requeued(__crq)) |
752 | break; | 992 | break; |
753 | 993 | ||
754 | if (crq->request->sector > __rq->sector) | 994 | if (__rq->sector <= crq->request->sector) |
755 | break; | 995 | break; |
756 | if (__rq->sector > last && crq->request->sector < last) { | 996 | if (__rq->sector > last && crq->request->sector < last) { |
757 | last = crq->request->sector; | 997 | last = crq->request->sector + crq->request->nr_sectors; |
758 | break; | 998 | break; |
759 | } | 999 | } |
1000 | entry = &__rq->queuelist; | ||
760 | } | 1001 | } |
761 | 1002 | ||
762 | cfqd->last_sector = last; | 1003 | cfqd->last_sector = last; |
763 | crq->in_flight = 1; | 1004 | |
764 | cfqq->in_flight++; | 1005 | cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq); |
765 | list_add(&crq->request->queuelist, entry); | 1006 | |
1007 | cfq_del_crq_rb(crq); | ||
1008 | cfq_remove_merge_hints(q, crq); | ||
1009 | |||
1010 | cfq_mark_crq_in_flight(crq); | ||
1011 | cfq_clear_crq_requeued(crq); | ||
1012 | |||
1013 | cfqq->on_dispatch[cfq_crq_is_sync(crq)]++; | ||
1014 | list_add_tail(&crq->request->queuelist, entry); | ||
766 | } | 1015 | } |
767 | 1016 | ||
768 | /* | 1017 | /* |
@@ -771,173 +1020,235 @@ static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq) | |||
771 | static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq) | 1020 | static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq) |
772 | { | 1021 | { |
773 | struct cfq_data *cfqd = cfqq->cfqd; | 1022 | struct cfq_data *cfqd = cfqq->cfqd; |
774 | const int reads = !list_empty(&cfqq->fifo[0]); | 1023 | struct request *rq; |
775 | const int writes = !list_empty(&cfqq->fifo[1]); | ||
776 | unsigned long now = jiffies; | ||
777 | struct cfq_rq *crq; | 1024 | struct cfq_rq *crq; |
778 | 1025 | ||
779 | if (time_before(now, cfqq->last_fifo_expire + cfqd->cfq_fifo_batch_expire)) | 1026 | if (cfq_cfqq_fifo_expire(cfqq)) |
780 | return NULL; | 1027 | return NULL; |
781 | 1028 | ||
782 | crq = RQ_DATA(list_entry(cfqq->fifo[0].next, struct request, queuelist)); | 1029 | if (!list_empty(&cfqq->fifo)) { |
783 | if (reads && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_r)) { | 1030 | int fifo = cfq_cfqq_class_sync(cfqq); |
784 | cfqq->last_fifo_expire = now; | ||
785 | return crq; | ||
786 | } | ||
787 | 1031 | ||
788 | crq = RQ_DATA(list_entry(cfqq->fifo[1].next, struct request, queuelist)); | 1032 | crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next)); |
789 | if (writes && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_w)) { | 1033 | rq = crq->request; |
790 | cfqq->last_fifo_expire = now; | 1034 | if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) { |
791 | return crq; | 1035 | cfq_mark_cfqq_fifo_expire(cfqq); |
1036 | return crq; | ||
1037 | } | ||
792 | } | 1038 | } |
793 | 1039 | ||
794 | return NULL; | 1040 | return NULL; |
795 | } | 1041 | } |
796 | 1042 | ||
797 | /* | 1043 | /* |
798 | * dispatch a single request from given queue | 1044 | * Scale schedule slice based on io priority. Use the sync time slice only |
1045 | * if a queue is marked sync and has sync io queued. A sync queue with async | ||
1046 | * io only, should not get full sync slice length. | ||
799 | */ | 1047 | */ |
1048 | static inline int | ||
1049 | cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
1050 | { | ||
1051 | const int base_slice = cfqd->cfq_slice[cfq_cfqq_sync(cfqq)]; | ||
1052 | |||
1053 | WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR); | ||
1054 | |||
1055 | return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - cfqq->ioprio)); | ||
1056 | } | ||
1057 | |||
800 | static inline void | 1058 | static inline void |
801 | cfq_dispatch_request(request_queue_t *q, struct cfq_data *cfqd, | 1059 | cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
802 | struct cfq_queue *cfqq) | ||
803 | { | 1060 | { |
804 | struct cfq_rq *crq; | 1061 | cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies; |
1062 | } | ||
1063 | |||
1064 | static inline int | ||
1065 | cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
1066 | { | ||
1067 | const int base_rq = cfqd->cfq_slice_async_rq; | ||
1068 | |||
1069 | WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR); | ||
1070 | |||
1071 | return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio)); | ||
1072 | } | ||
1073 | |||
1074 | /* | ||
1075 | * scheduler run of queue, if there are requests pending and no one in the | ||
1076 | * driver that will restart queueing | ||
1077 | */ | ||
1078 | static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) | ||
1079 | { | ||
1080 | if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd)) | ||
1081 | kblockd_schedule_work(&cfqd->unplug_work); | ||
1082 | } | ||
1083 | |||
1084 | /* | ||
1085 | * get next queue for service | ||
1086 | */ | ||
1087 | static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) | ||
1088 | { | ||
1089 | unsigned long now = jiffies; | ||
1090 | struct cfq_queue *cfqq; | ||
1091 | |||
1092 | cfqq = cfqd->active_queue; | ||
1093 | if (!cfqq) | ||
1094 | goto new_queue; | ||
1095 | |||
1096 | if (cfq_cfqq_expired(cfqq)) | ||
1097 | goto new_queue; | ||
805 | 1098 | ||
806 | /* | 1099 | /* |
807 | * follow expired path, else get first next available | 1100 | * slice has expired |
808 | */ | 1101 | */ |
809 | if ((crq = cfq_check_fifo(cfqq)) == NULL) { | 1102 | if (!cfq_cfqq_must_dispatch(cfqq) && time_after(now, cfqq->slice_end)) |
810 | if (cfqd->find_best_crq) | 1103 | goto expire; |
811 | crq = cfqq->next_crq; | ||
812 | else | ||
813 | crq = rb_entry_crq(rb_first(&cfqq->sort_list)); | ||
814 | } | ||
815 | |||
816 | cfqd->last_sector = crq->request->sector + crq->request->nr_sectors; | ||
817 | 1104 | ||
818 | /* | 1105 | /* |
819 | * finally, insert request into driver list | 1106 | * if queue has requests, dispatch one. if not, check if |
1107 | * enough slice is left to wait for one | ||
820 | */ | 1108 | */ |
821 | cfq_dispatch_sort(q, crq); | 1109 | if (!RB_EMPTY(&cfqq->sort_list)) |
1110 | goto keep_queue; | ||
1111 | else if (!force && cfq_cfqq_class_sync(cfqq) && | ||
1112 | time_before(now, cfqq->slice_end)) { | ||
1113 | if (cfq_arm_slice_timer(cfqd, cfqq)) | ||
1114 | return NULL; | ||
1115 | } | ||
1116 | |||
1117 | expire: | ||
1118 | cfq_slice_expired(cfqd, 0); | ||
1119 | new_queue: | ||
1120 | cfqq = cfq_set_active_queue(cfqd); | ||
1121 | keep_queue: | ||
1122 | return cfqq; | ||
822 | } | 1123 | } |
823 | 1124 | ||
824 | static int cfq_dispatch_requests(request_queue_t *q, int max_dispatch) | 1125 | static int |
1126 | __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, | ||
1127 | int max_dispatch) | ||
825 | { | 1128 | { |
826 | struct cfq_data *cfqd = q->elevator->elevator_data; | 1129 | int dispatched = 0; |
827 | struct cfq_queue *cfqq; | ||
828 | struct list_head *entry, *tmp; | ||
829 | int queued, busy_queues, first_round; | ||
830 | 1130 | ||
831 | if (list_empty(&cfqd->rr_list)) | 1131 | BUG_ON(RB_EMPTY(&cfqq->sort_list)); |
832 | return 0; | ||
833 | 1132 | ||
834 | queued = 0; | 1133 | do { |
835 | first_round = 1; | 1134 | struct cfq_rq *crq; |
836 | restart: | ||
837 | busy_queues = 0; | ||
838 | list_for_each_safe(entry, tmp, &cfqd->rr_list) { | ||
839 | cfqq = list_entry_cfqq(entry); | ||
840 | 1135 | ||
841 | BUG_ON(RB_EMPTY(&cfqq->sort_list)); | 1136 | /* |
1137 | * follow expired path, else get first next available | ||
1138 | */ | ||
1139 | if ((crq = cfq_check_fifo(cfqq)) == NULL) | ||
1140 | crq = cfqq->next_crq; | ||
842 | 1141 | ||
843 | /* | 1142 | /* |
844 | * first round of queueing, only select from queues that | 1143 | * finally, insert request into driver dispatch list |
845 | * don't already have io in-flight | ||
846 | */ | 1144 | */ |
847 | if (first_round && cfqq->in_flight) | 1145 | cfq_dispatch_sort(cfqd->queue, crq); |
848 | continue; | 1146 | |
1147 | cfqd->dispatch_slice++; | ||
1148 | dispatched++; | ||
849 | 1149 | ||
850 | cfq_dispatch_request(q, cfqd, cfqq); | 1150 | if (!cfqd->active_cic) { |
1151 | atomic_inc(&crq->io_context->ioc->refcount); | ||
1152 | cfqd->active_cic = crq->io_context; | ||
1153 | } | ||
851 | 1154 | ||
852 | if (!RB_EMPTY(&cfqq->sort_list)) | 1155 | if (RB_EMPTY(&cfqq->sort_list)) |
853 | busy_queues++; | 1156 | break; |
854 | 1157 | ||
855 | queued++; | 1158 | } while (dispatched < max_dispatch); |
856 | } | 1159 | |
1160 | /* | ||
1161 | * if slice end isn't set yet, set it. if at least one request was | ||
1162 | * sync, use the sync time slice value | ||
1163 | */ | ||
1164 | if (!cfqq->slice_end) | ||
1165 | cfq_set_prio_slice(cfqd, cfqq); | ||
1166 | |||
1167 | /* | ||
1168 | * expire an async queue immediately if it has used up its slice. idle | ||
1169 | * queue always expire after 1 dispatch round. | ||
1170 | */ | ||
1171 | if ((!cfq_cfqq_sync(cfqq) && | ||
1172 | cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) || | ||
1173 | cfq_class_idle(cfqq)) | ||
1174 | cfq_slice_expired(cfqd, 0); | ||
1175 | |||
1176 | return dispatched; | ||
1177 | } | ||
1178 | |||
1179 | static int | ||
1180 | cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force) | ||
1181 | { | ||
1182 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
1183 | struct cfq_queue *cfqq; | ||
1184 | |||
1185 | if (!cfqd->busy_queues) | ||
1186 | return 0; | ||
857 | 1187 | ||
858 | if ((queued < max_dispatch) && (busy_queues || first_round)) { | 1188 | cfqq = cfq_select_queue(cfqd, force); |
859 | first_round = 0; | 1189 | if (cfqq) { |
860 | goto restart; | 1190 | cfq_clear_cfqq_must_dispatch(cfqq); |
1191 | cfq_clear_cfqq_wait_request(cfqq); | ||
1192 | del_timer(&cfqd->idle_slice_timer); | ||
1193 | |||
1194 | if (cfq_class_idle(cfqq)) | ||
1195 | max_dispatch = 1; | ||
1196 | |||
1197 | return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); | ||
861 | } | 1198 | } |
862 | 1199 | ||
863 | return queued; | 1200 | return 0; |
864 | } | 1201 | } |
865 | 1202 | ||
866 | static inline void cfq_account_dispatch(struct cfq_rq *crq) | 1203 | static inline void cfq_account_dispatch(struct cfq_rq *crq) |
867 | { | 1204 | { |
868 | struct cfq_queue *cfqq = crq->cfq_queue; | 1205 | struct cfq_queue *cfqq = crq->cfq_queue; |
869 | struct cfq_data *cfqd = cfqq->cfqd; | 1206 | struct cfq_data *cfqd = cfqq->cfqd; |
870 | unsigned long now, elapsed; | ||
871 | 1207 | ||
872 | if (!blk_fs_request(crq->request)) | 1208 | if (unlikely(!blk_fs_request(crq->request))) |
873 | return; | 1209 | return; |
874 | 1210 | ||
875 | /* | 1211 | /* |
876 | * accounted bit is necessary since some drivers will call | 1212 | * accounted bit is necessary since some drivers will call |
877 | * elv_next_request() many times for the same request (eg ide) | 1213 | * elv_next_request() many times for the same request (eg ide) |
878 | */ | 1214 | */ |
879 | if (crq->accounted) | 1215 | if (cfq_crq_in_driver(crq)) |
880 | return; | 1216 | return; |
881 | 1217 | ||
882 | now = jiffies; | 1218 | cfq_mark_crq_in_driver(crq); |
883 | if (cfqq->service_start == ~0UL) | 1219 | cfqd->rq_in_driver++; |
884 | cfqq->service_start = now; | ||
885 | |||
886 | /* | ||
887 | * on drives with tagged command queueing, command turn-around time | ||
888 | * doesn't necessarily reflect the time spent processing this very | ||
889 | * command inside the drive. so do the accounting differently there, | ||
890 | * by just sorting on the number of requests | ||
891 | */ | ||
892 | if (cfqd->cfq_tagged) { | ||
893 | if (time_after(now, cfqq->service_start + cfq_service)) { | ||
894 | cfqq->service_start = now; | ||
895 | cfqq->service_used /= 10; | ||
896 | } | ||
897 | |||
898 | cfqq->service_used++; | ||
899 | cfq_sort_rr_list(cfqq, 0); | ||
900 | } | ||
901 | |||
902 | elapsed = now - crq->queue_start; | ||
903 | if (elapsed > max_elapsed_dispatch) | ||
904 | max_elapsed_dispatch = elapsed; | ||
905 | |||
906 | crq->accounted = 1; | ||
907 | crq->service_start = now; | ||
908 | |||
909 | if (++cfqd->rq_in_driver >= CFQ_MAX_TAG && !cfqd->cfq_tagged) { | ||
910 | cfqq->cfqd->cfq_tagged = 1; | ||
911 | printk("cfq: depth %d reached, tagging now on\n", CFQ_MAX_TAG); | ||
912 | } | ||
913 | } | 1220 | } |
914 | 1221 | ||
915 | static inline void | 1222 | static inline void |
916 | cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq) | 1223 | cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq) |
917 | { | 1224 | { |
918 | struct cfq_data *cfqd = cfqq->cfqd; | 1225 | struct cfq_data *cfqd = cfqq->cfqd; |
1226 | unsigned long now; | ||
919 | 1227 | ||
920 | if (!crq->accounted) | 1228 | if (!cfq_crq_in_driver(crq)) |
921 | return; | 1229 | return; |
922 | 1230 | ||
1231 | now = jiffies; | ||
1232 | |||
923 | WARN_ON(!cfqd->rq_in_driver); | 1233 | WARN_ON(!cfqd->rq_in_driver); |
924 | cfqd->rq_in_driver--; | 1234 | cfqd->rq_in_driver--; |
925 | 1235 | ||
926 | if (!cfqd->cfq_tagged) { | 1236 | if (!cfq_class_idle(cfqq)) |
927 | unsigned long now = jiffies; | 1237 | cfqd->last_end_request = now; |
928 | unsigned long duration = now - crq->service_start; | ||
929 | 1238 | ||
930 | if (time_after(now, cfqq->service_start + cfq_service)) { | 1239 | if (!cfq_cfqq_dispatched(cfqq)) { |
931 | cfqq->service_start = now; | 1240 | if (cfq_cfqq_on_rr(cfqq)) { |
932 | cfqq->service_used >>= 3; | 1241 | cfqq->service_last = now; |
1242 | cfq_resort_rr_list(cfqq, 0); | ||
1243 | } | ||
1244 | if (cfq_cfqq_expired(cfqq)) { | ||
1245 | __cfq_slice_expired(cfqd, cfqq, 0); | ||
1246 | cfq_schedule_dispatch(cfqd); | ||
933 | } | 1247 | } |
934 | |||
935 | cfqq->service_used += duration; | ||
936 | cfq_sort_rr_list(cfqq, 0); | ||
937 | |||
938 | if (duration > max_elapsed_crq) | ||
939 | max_elapsed_crq = duration; | ||
940 | } | 1248 | } |
1249 | |||
1250 | if (cfq_crq_is_sync(crq)) | ||
1251 | crq->io_context->last_end_request = now; | ||
941 | } | 1252 | } |
942 | 1253 | ||
943 | static struct request *cfq_next_request(request_queue_t *q) | 1254 | static struct request *cfq_next_request(request_queue_t *q) |
@@ -950,7 +1261,18 @@ static struct request *cfq_next_request(request_queue_t *q) | |||
950 | dispatch: | 1261 | dispatch: |
951 | rq = list_entry_rq(q->queue_head.next); | 1262 | rq = list_entry_rq(q->queue_head.next); |
952 | 1263 | ||
953 | if ((crq = RQ_DATA(rq)) != NULL) { | 1264 | crq = RQ_DATA(rq); |
1265 | if (crq) { | ||
1266 | struct cfq_queue *cfqq = crq->cfq_queue; | ||
1267 | |||
1268 | /* | ||
1269 | * if idle window is disabled, allow queue buildup | ||
1270 | */ | ||
1271 | if (!cfq_crq_in_driver(crq) && | ||
1272 | !cfq_cfqq_idle_window(cfqq) && | ||
1273 | cfqd->rq_in_driver >= cfqd->cfq_max_depth) | ||
1274 | return NULL; | ||
1275 | |||
954 | cfq_remove_merge_hints(q, crq); | 1276 | cfq_remove_merge_hints(q, crq); |
955 | cfq_account_dispatch(crq); | 1277 | cfq_account_dispatch(crq); |
956 | } | 1278 | } |
@@ -958,7 +1280,7 @@ dispatch: | |||
958 | return rq; | 1280 | return rq; |
959 | } | 1281 | } |
960 | 1282 | ||
961 | if (cfq_dispatch_requests(q, cfqd->cfq_quantum)) | 1283 | if (cfq_dispatch_requests(q, cfqd->cfq_quantum, 0)) |
962 | goto dispatch; | 1284 | goto dispatch; |
963 | 1285 | ||
964 | return NULL; | 1286 | return NULL; |
@@ -972,13 +1294,21 @@ dispatch: | |||
972 | */ | 1294 | */ |
973 | static void cfq_put_queue(struct cfq_queue *cfqq) | 1295 | static void cfq_put_queue(struct cfq_queue *cfqq) |
974 | { | 1296 | { |
975 | BUG_ON(!atomic_read(&cfqq->ref)); | 1297 | struct cfq_data *cfqd = cfqq->cfqd; |
1298 | |||
1299 | BUG_ON(atomic_read(&cfqq->ref) <= 0); | ||
976 | 1300 | ||
977 | if (!atomic_dec_and_test(&cfqq->ref)) | 1301 | if (!atomic_dec_and_test(&cfqq->ref)) |
978 | return; | 1302 | return; |
979 | 1303 | ||
980 | BUG_ON(rb_first(&cfqq->sort_list)); | 1304 | BUG_ON(rb_first(&cfqq->sort_list)); |
981 | BUG_ON(cfqq->on_rr); | 1305 | BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]); |
1306 | BUG_ON(cfq_cfqq_on_rr(cfqq)); | ||
1307 | |||
1308 | if (unlikely(cfqd->active_queue == cfqq)) { | ||
1309 | __cfq_slice_expired(cfqd, cfqq, 0); | ||
1310 | cfq_schedule_dispatch(cfqd); | ||
1311 | } | ||
982 | 1312 | ||
983 | cfq_put_cfqd(cfqq->cfqd); | 1313 | cfq_put_cfqd(cfqq->cfqd); |
984 | 1314 | ||
@@ -991,15 +1321,17 @@ static void cfq_put_queue(struct cfq_queue *cfqq) | |||
991 | } | 1321 | } |
992 | 1322 | ||
993 | static inline struct cfq_queue * | 1323 | static inline struct cfq_queue * |
994 | __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key, const int hashval) | 1324 | __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio, |
1325 | const int hashval) | ||
995 | { | 1326 | { |
996 | struct hlist_head *hash_list = &cfqd->cfq_hash[hashval]; | 1327 | struct hlist_head *hash_list = &cfqd->cfq_hash[hashval]; |
997 | struct hlist_node *entry, *next; | 1328 | struct hlist_node *entry, *next; |
998 | 1329 | ||
999 | hlist_for_each_safe(entry, next, hash_list) { | 1330 | hlist_for_each_safe(entry, next, hash_list) { |
1000 | struct cfq_queue *__cfqq = list_entry_qhash(entry); | 1331 | struct cfq_queue *__cfqq = list_entry_qhash(entry); |
1332 | const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio); | ||
1001 | 1333 | ||
1002 | if (__cfqq->key == key) | 1334 | if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY)) |
1003 | return __cfqq; | 1335 | return __cfqq; |
1004 | } | 1336 | } |
1005 | 1337 | ||
@@ -1007,94 +1339,220 @@ __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key, const int hashval) | |||
1007 | } | 1339 | } |
1008 | 1340 | ||
1009 | static struct cfq_queue * | 1341 | static struct cfq_queue * |
1010 | cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key) | 1342 | cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio) |
1011 | { | 1343 | { |
1012 | return __cfq_find_cfq_hash(cfqd, key, hash_long(key, CFQ_QHASH_SHIFT)); | 1344 | return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT)); |
1013 | } | 1345 | } |
1014 | 1346 | ||
1015 | static inline void | 1347 | static void cfq_free_io_context(struct cfq_io_context *cic) |
1016 | cfq_rehash_cfqq(struct cfq_data *cfqd, struct cfq_queue **cfqq, | ||
1017 | struct cfq_io_context *cic) | ||
1018 | { | 1348 | { |
1019 | unsigned long hashkey = cfq_hash_key(cfqd, current); | 1349 | struct cfq_io_context *__cic; |
1020 | unsigned long hashval = hash_long(hashkey, CFQ_QHASH_SHIFT); | 1350 | struct list_head *entry, *next; |
1021 | struct cfq_queue *__cfqq; | ||
1022 | unsigned long flags; | ||
1023 | |||
1024 | spin_lock_irqsave(cfqd->queue->queue_lock, flags); | ||
1025 | 1351 | ||
1026 | hlist_del(&(*cfqq)->cfq_hash); | 1352 | list_for_each_safe(entry, next, &cic->list) { |
1027 | 1353 | __cic = list_entry(entry, struct cfq_io_context, list); | |
1028 | __cfqq = __cfq_find_cfq_hash(cfqd, hashkey, hashval); | 1354 | kmem_cache_free(cfq_ioc_pool, __cic); |
1029 | if (!__cfqq || __cfqq == *cfqq) { | ||
1030 | __cfqq = *cfqq; | ||
1031 | hlist_add_head(&__cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); | ||
1032 | __cfqq->key_type = cfqd->key_type; | ||
1033 | } else { | ||
1034 | atomic_inc(&__cfqq->ref); | ||
1035 | cic->cfqq = __cfqq; | ||
1036 | cfq_put_queue(*cfqq); | ||
1037 | *cfqq = __cfqq; | ||
1038 | } | 1355 | } |
1039 | 1356 | ||
1040 | cic->cfqq = __cfqq; | 1357 | kmem_cache_free(cfq_ioc_pool, cic); |
1041 | spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); | ||
1042 | } | 1358 | } |
1043 | 1359 | ||
1044 | static void cfq_free_io_context(struct cfq_io_context *cic) | 1360 | /* |
1361 | * Called with interrupts disabled | ||
1362 | */ | ||
1363 | static void cfq_exit_single_io_context(struct cfq_io_context *cic) | ||
1045 | { | 1364 | { |
1046 | kmem_cache_free(cfq_ioc_pool, cic); | 1365 | struct cfq_data *cfqd = cic->cfqq->cfqd; |
1366 | request_queue_t *q = cfqd->queue; | ||
1367 | |||
1368 | WARN_ON(!irqs_disabled()); | ||
1369 | |||
1370 | spin_lock(q->queue_lock); | ||
1371 | |||
1372 | if (unlikely(cic->cfqq == cfqd->active_queue)) { | ||
1373 | __cfq_slice_expired(cfqd, cic->cfqq, 0); | ||
1374 | cfq_schedule_dispatch(cfqd); | ||
1375 | } | ||
1376 | |||
1377 | cfq_put_queue(cic->cfqq); | ||
1378 | cic->cfqq = NULL; | ||
1379 | spin_unlock(q->queue_lock); | ||
1047 | } | 1380 | } |
1048 | 1381 | ||
1049 | /* | 1382 | /* |
1050 | * locking hierarchy is: io_context lock -> queue locks | 1383 | * Another task may update the task cic list, if it is doing a queue lookup |
1384 | * on its behalf. cfq_cic_lock excludes such concurrent updates | ||
1051 | */ | 1385 | */ |
1052 | static void cfq_exit_io_context(struct cfq_io_context *cic) | 1386 | static void cfq_exit_io_context(struct cfq_io_context *cic) |
1053 | { | 1387 | { |
1054 | struct cfq_queue *cfqq = cic->cfqq; | 1388 | struct cfq_io_context *__cic; |
1055 | struct list_head *entry = &cic->list; | 1389 | struct list_head *entry; |
1056 | request_queue_t *q; | ||
1057 | unsigned long flags; | 1390 | unsigned long flags; |
1058 | 1391 | ||
1392 | local_irq_save(flags); | ||
1393 | |||
1059 | /* | 1394 | /* |
1060 | * put the reference this task is holding to the various queues | 1395 | * put the reference this task is holding to the various queues |
1061 | */ | 1396 | */ |
1062 | spin_lock_irqsave(&cic->ioc->lock, flags); | 1397 | list_for_each(entry, &cic->list) { |
1063 | while ((entry = cic->list.next) != &cic->list) { | ||
1064 | struct cfq_io_context *__cic; | ||
1065 | |||
1066 | __cic = list_entry(entry, struct cfq_io_context, list); | 1398 | __cic = list_entry(entry, struct cfq_io_context, list); |
1067 | list_del(entry); | 1399 | cfq_exit_single_io_context(__cic); |
1068 | |||
1069 | q = __cic->cfqq->cfqd->queue; | ||
1070 | spin_lock(q->queue_lock); | ||
1071 | cfq_put_queue(__cic->cfqq); | ||
1072 | spin_unlock(q->queue_lock); | ||
1073 | } | 1400 | } |
1074 | 1401 | ||
1075 | q = cfqq->cfqd->queue; | 1402 | cfq_exit_single_io_context(cic); |
1076 | spin_lock(q->queue_lock); | 1403 | local_irq_restore(flags); |
1077 | cfq_put_queue(cfqq); | ||
1078 | spin_unlock(q->queue_lock); | ||
1079 | |||
1080 | cic->cfqq = NULL; | ||
1081 | spin_unlock_irqrestore(&cic->ioc->lock, flags); | ||
1082 | } | 1404 | } |
1083 | 1405 | ||
1084 | static struct cfq_io_context *cfq_alloc_io_context(int gfp_flags) | 1406 | static struct cfq_io_context * |
1407 | cfq_alloc_io_context(struct cfq_data *cfqd, int gfp_mask) | ||
1085 | { | 1408 | { |
1086 | struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_flags); | 1409 | struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask); |
1087 | 1410 | ||
1088 | if (cic) { | 1411 | if (cic) { |
1089 | cic->dtor = cfq_free_io_context; | ||
1090 | cic->exit = cfq_exit_io_context; | ||
1091 | INIT_LIST_HEAD(&cic->list); | 1412 | INIT_LIST_HEAD(&cic->list); |
1092 | cic->cfqq = NULL; | 1413 | cic->cfqq = NULL; |
1414 | cic->key = NULL; | ||
1415 | cic->last_end_request = jiffies; | ||
1416 | cic->ttime_total = 0; | ||
1417 | cic->ttime_samples = 0; | ||
1418 | cic->ttime_mean = 0; | ||
1419 | cic->dtor = cfq_free_io_context; | ||
1420 | cic->exit = cfq_exit_io_context; | ||
1093 | } | 1421 | } |
1094 | 1422 | ||
1095 | return cic; | 1423 | return cic; |
1096 | } | 1424 | } |
1097 | 1425 | ||
1426 | static void cfq_init_prio_data(struct cfq_queue *cfqq) | ||
1427 | { | ||
1428 | struct task_struct *tsk = current; | ||
1429 | int ioprio_class; | ||
1430 | |||
1431 | if (!cfq_cfqq_prio_changed(cfqq)) | ||
1432 | return; | ||
1433 | |||
1434 | ioprio_class = IOPRIO_PRIO_CLASS(tsk->ioprio); | ||
1435 | switch (ioprio_class) { | ||
1436 | default: | ||
1437 | printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class); | ||
1438 | case IOPRIO_CLASS_NONE: | ||
1439 | /* | ||
1440 | * no prio set, place us in the middle of the BE classes | ||
1441 | */ | ||
1442 | cfqq->ioprio = task_nice_ioprio(tsk); | ||
1443 | cfqq->ioprio_class = IOPRIO_CLASS_BE; | ||
1444 | break; | ||
1445 | case IOPRIO_CLASS_RT: | ||
1446 | cfqq->ioprio = task_ioprio(tsk); | ||
1447 | cfqq->ioprio_class = IOPRIO_CLASS_RT; | ||
1448 | break; | ||
1449 | case IOPRIO_CLASS_BE: | ||
1450 | cfqq->ioprio = task_ioprio(tsk); | ||
1451 | cfqq->ioprio_class = IOPRIO_CLASS_BE; | ||
1452 | break; | ||
1453 | case IOPRIO_CLASS_IDLE: | ||
1454 | cfqq->ioprio_class = IOPRIO_CLASS_IDLE; | ||
1455 | cfqq->ioprio = 7; | ||
1456 | cfq_clear_cfqq_idle_window(cfqq); | ||
1457 | break; | ||
1458 | } | ||
1459 | |||
1460 | /* | ||
1461 | * keep track of original prio settings in case we have to temporarily | ||
1462 | * elevate the priority of this queue | ||
1463 | */ | ||
1464 | cfqq->org_ioprio = cfqq->ioprio; | ||
1465 | cfqq->org_ioprio_class = cfqq->ioprio_class; | ||
1466 | |||
1467 | if (cfq_cfqq_on_rr(cfqq)) | ||
1468 | cfq_resort_rr_list(cfqq, 0); | ||
1469 | |||
1470 | cfq_clear_cfqq_prio_changed(cfqq); | ||
1471 | } | ||
1472 | |||
1473 | static inline void changed_ioprio(struct cfq_queue *cfqq) | ||
1474 | { | ||
1475 | if (cfqq) { | ||
1476 | struct cfq_data *cfqd = cfqq->cfqd; | ||
1477 | |||
1478 | spin_lock(cfqd->queue->queue_lock); | ||
1479 | cfq_mark_cfqq_prio_changed(cfqq); | ||
1480 | cfq_init_prio_data(cfqq); | ||
1481 | spin_unlock(cfqd->queue->queue_lock); | ||
1482 | } | ||
1483 | } | ||
1484 | |||
1485 | /* | ||
1486 | * callback from sys_ioprio_set, irqs are disabled | ||
1487 | */ | ||
1488 | static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio) | ||
1489 | { | ||
1490 | struct cfq_io_context *cic = ioc->cic; | ||
1491 | |||
1492 | changed_ioprio(cic->cfqq); | ||
1493 | |||
1494 | list_for_each_entry(cic, &cic->list, list) | ||
1495 | changed_ioprio(cic->cfqq); | ||
1496 | |||
1497 | return 0; | ||
1498 | } | ||
1499 | |||
1500 | static struct cfq_queue * | ||
1501 | cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio, | ||
1502 | int gfp_mask) | ||
1503 | { | ||
1504 | const int hashval = hash_long(key, CFQ_QHASH_SHIFT); | ||
1505 | struct cfq_queue *cfqq, *new_cfqq = NULL; | ||
1506 | |||
1507 | retry: | ||
1508 | cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval); | ||
1509 | |||
1510 | if (!cfqq) { | ||
1511 | if (new_cfqq) { | ||
1512 | cfqq = new_cfqq; | ||
1513 | new_cfqq = NULL; | ||
1514 | } else if (gfp_mask & __GFP_WAIT) { | ||
1515 | spin_unlock_irq(cfqd->queue->queue_lock); | ||
1516 | new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); | ||
1517 | spin_lock_irq(cfqd->queue->queue_lock); | ||
1518 | goto retry; | ||
1519 | } else { | ||
1520 | cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); | ||
1521 | if (!cfqq) | ||
1522 | goto out; | ||
1523 | } | ||
1524 | |||
1525 | memset(cfqq, 0, sizeof(*cfqq)); | ||
1526 | |||
1527 | INIT_HLIST_NODE(&cfqq->cfq_hash); | ||
1528 | INIT_LIST_HEAD(&cfqq->cfq_list); | ||
1529 | RB_CLEAR_ROOT(&cfqq->sort_list); | ||
1530 | INIT_LIST_HEAD(&cfqq->fifo); | ||
1531 | |||
1532 | cfqq->key = key; | ||
1533 | hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); | ||
1534 | atomic_set(&cfqq->ref, 0); | ||
1535 | cfqq->cfqd = cfqd; | ||
1536 | atomic_inc(&cfqd->ref); | ||
1537 | cfqq->service_last = 0; | ||
1538 | /* | ||
1539 | * set ->slice_left to allow preemption for a new process | ||
1540 | */ | ||
1541 | cfqq->slice_left = 2 * cfqd->cfq_slice_idle; | ||
1542 | cfq_mark_cfqq_idle_window(cfqq); | ||
1543 | cfq_mark_cfqq_prio_changed(cfqq); | ||
1544 | cfq_init_prio_data(cfqq); | ||
1545 | } | ||
1546 | |||
1547 | if (new_cfqq) | ||
1548 | kmem_cache_free(cfq_pool, new_cfqq); | ||
1549 | |||
1550 | atomic_inc(&cfqq->ref); | ||
1551 | out: | ||
1552 | WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq); | ||
1553 | return cfqq; | ||
1554 | } | ||
1555 | |||
1098 | /* | 1556 | /* |
1099 | * Setup general io context and cfq io context. There can be several cfq | 1557 | * Setup general io context and cfq io context. There can be several cfq |
1100 | * io contexts per general io context, if this process is doing io to more | 1558 | * io contexts per general io context, if this process is doing io to more |
@@ -1102,39 +1560,39 @@ static struct cfq_io_context *cfq_alloc_io_context(int gfp_flags) | |||
1102 | * cfqq, so we don't need to worry about it disappearing | 1560 | * cfqq, so we don't need to worry about it disappearing |
1103 | */ | 1561 | */ |
1104 | static struct cfq_io_context * | 1562 | static struct cfq_io_context * |
1105 | cfq_get_io_context(struct cfq_queue **cfqq, int gfp_flags) | 1563 | cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask) |
1106 | { | 1564 | { |
1107 | struct cfq_data *cfqd = (*cfqq)->cfqd; | 1565 | struct io_context *ioc = NULL; |
1108 | struct cfq_queue *__cfqq = *cfqq; | ||
1109 | struct cfq_io_context *cic; | 1566 | struct cfq_io_context *cic; |
1110 | struct io_context *ioc; | ||
1111 | 1567 | ||
1112 | might_sleep_if(gfp_flags & __GFP_WAIT); | 1568 | might_sleep_if(gfp_mask & __GFP_WAIT); |
1113 | 1569 | ||
1114 | ioc = get_io_context(gfp_flags); | 1570 | ioc = get_io_context(gfp_mask); |
1115 | if (!ioc) | 1571 | if (!ioc) |
1116 | return NULL; | 1572 | return NULL; |
1117 | 1573 | ||
1118 | if ((cic = ioc->cic) == NULL) { | 1574 | if ((cic = ioc->cic) == NULL) { |
1119 | cic = cfq_alloc_io_context(gfp_flags); | 1575 | cic = cfq_alloc_io_context(cfqd, gfp_mask); |
1120 | 1576 | ||
1121 | if (cic == NULL) | 1577 | if (cic == NULL) |
1122 | goto err; | 1578 | goto err; |
1123 | 1579 | ||
1580 | /* | ||
1581 | * manually increment generic io_context usage count, it | ||
1582 | * cannot go away since we are already holding one ref to it | ||
1583 | */ | ||
1124 | ioc->cic = cic; | 1584 | ioc->cic = cic; |
1585 | ioc->set_ioprio = cfq_ioc_set_ioprio; | ||
1125 | cic->ioc = ioc; | 1586 | cic->ioc = ioc; |
1126 | cic->cfqq = __cfqq; | 1587 | cic->key = cfqd; |
1127 | atomic_inc(&__cfqq->ref); | 1588 | atomic_inc(&cfqd->ref); |
1128 | } else { | 1589 | } else { |
1129 | struct cfq_io_context *__cic; | 1590 | struct cfq_io_context *__cic; |
1130 | unsigned long flags; | ||
1131 | 1591 | ||
1132 | /* | 1592 | /* |
1133 | * since the first cic on the list is actually the head | 1593 | * the first cic on the list is actually the head itself |
1134 | * itself, need to check this here or we'll duplicate an | ||
1135 | * cic per ioc for no reason | ||
1136 | */ | 1594 | */ |
1137 | if (cic->cfqq == __cfqq) | 1595 | if (cic->key == cfqd) |
1138 | goto out; | 1596 | goto out; |
1139 | 1597 | ||
1140 | /* | 1598 | /* |
@@ -1142,152 +1600,262 @@ cfq_get_io_context(struct cfq_queue **cfqq, int gfp_flags) | |||
1142 | * should be ok here, the list will usually not be more than | 1600 | * should be ok here, the list will usually not be more than |
1143 | * 1 or a few entries long | 1601 | * 1 or a few entries long |
1144 | */ | 1602 | */ |
1145 | spin_lock_irqsave(&ioc->lock, flags); | ||
1146 | list_for_each_entry(__cic, &cic->list, list) { | 1603 | list_for_each_entry(__cic, &cic->list, list) { |
1147 | /* | 1604 | /* |
1148 | * this process is already holding a reference to | 1605 | * this process is already holding a reference to |
1149 | * this queue, so no need to get one more | 1606 | * this queue, so no need to get one more |
1150 | */ | 1607 | */ |
1151 | if (__cic->cfqq == __cfqq) { | 1608 | if (__cic->key == cfqd) { |
1152 | cic = __cic; | 1609 | cic = __cic; |
1153 | spin_unlock_irqrestore(&ioc->lock, flags); | ||
1154 | goto out; | 1610 | goto out; |
1155 | } | 1611 | } |
1156 | } | 1612 | } |
1157 | spin_unlock_irqrestore(&ioc->lock, flags); | ||
1158 | 1613 | ||
1159 | /* | 1614 | /* |
1160 | * nope, process doesn't have a cic assoicated with this | 1615 | * nope, process doesn't have a cic assoicated with this |
1161 | * cfqq yet. get a new one and add to list | 1616 | * cfqq yet. get a new one and add to list |
1162 | */ | 1617 | */ |
1163 | __cic = cfq_alloc_io_context(gfp_flags); | 1618 | __cic = cfq_alloc_io_context(cfqd, gfp_mask); |
1164 | if (__cic == NULL) | 1619 | if (__cic == NULL) |
1165 | goto err; | 1620 | goto err; |
1166 | 1621 | ||
1167 | __cic->ioc = ioc; | 1622 | __cic->ioc = ioc; |
1168 | __cic->cfqq = __cfqq; | 1623 | __cic->key = cfqd; |
1169 | atomic_inc(&__cfqq->ref); | 1624 | atomic_inc(&cfqd->ref); |
1170 | spin_lock_irqsave(&ioc->lock, flags); | ||
1171 | list_add(&__cic->list, &cic->list); | 1625 | list_add(&__cic->list, &cic->list); |
1172 | spin_unlock_irqrestore(&ioc->lock, flags); | ||
1173 | |||
1174 | cic = __cic; | 1626 | cic = __cic; |
1175 | *cfqq = __cfqq; | ||
1176 | } | 1627 | } |
1177 | 1628 | ||
1178 | out: | 1629 | out: |
1179 | /* | ||
1180 | * if key_type has been changed on the fly, we lazily rehash | ||
1181 | * each queue at lookup time | ||
1182 | */ | ||
1183 | if ((*cfqq)->key_type != cfqd->key_type) | ||
1184 | cfq_rehash_cfqq(cfqd, cfqq, cic); | ||
1185 | |||
1186 | return cic; | 1630 | return cic; |
1187 | err: | 1631 | err: |
1188 | put_io_context(ioc); | 1632 | put_io_context(ioc); |
1189 | return NULL; | 1633 | return NULL; |
1190 | } | 1634 | } |
1191 | 1635 | ||
1192 | static struct cfq_queue * | 1636 | static void |
1193 | __cfq_get_queue(struct cfq_data *cfqd, unsigned long key, int gfp_mask) | 1637 | cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic) |
1194 | { | 1638 | { |
1195 | const int hashval = hash_long(key, CFQ_QHASH_SHIFT); | 1639 | unsigned long elapsed, ttime; |
1196 | struct cfq_queue *cfqq, *new_cfqq = NULL; | ||
1197 | 1640 | ||
1198 | retry: | 1641 | /* |
1199 | cfqq = __cfq_find_cfq_hash(cfqd, key, hashval); | 1642 | * if this context already has stuff queued, thinktime is from |
1200 | 1643 | * last queue not last end | |
1201 | if (!cfqq) { | 1644 | */ |
1202 | if (new_cfqq) { | 1645 | #if 0 |
1203 | cfqq = new_cfqq; | 1646 | if (time_after(cic->last_end_request, cic->last_queue)) |
1204 | new_cfqq = NULL; | 1647 | elapsed = jiffies - cic->last_end_request; |
1205 | } else { | 1648 | else |
1206 | spin_unlock_irq(cfqd->queue->queue_lock); | 1649 | elapsed = jiffies - cic->last_queue; |
1207 | new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); | 1650 | #else |
1208 | spin_lock_irq(cfqd->queue->queue_lock); | 1651 | elapsed = jiffies - cic->last_end_request; |
1652 | #endif | ||
1209 | 1653 | ||
1210 | if (!new_cfqq && !(gfp_mask & __GFP_WAIT)) | 1654 | ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle); |
1211 | goto out; | ||
1212 | 1655 | ||
1213 | goto retry; | 1656 | cic->ttime_samples = (7*cic->ttime_samples + 256) / 8; |
1214 | } | 1657 | cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8; |
1658 | cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples; | ||
1659 | } | ||
1215 | 1660 | ||
1216 | memset(cfqq, 0, sizeof(*cfqq)); | 1661 | #define sample_valid(samples) ((samples) > 80) |
1217 | 1662 | ||
1218 | INIT_HLIST_NODE(&cfqq->cfq_hash); | 1663 | /* |
1219 | INIT_LIST_HEAD(&cfqq->cfq_list); | 1664 | * Disable idle window if the process thinks too long or seeks so much that |
1220 | RB_CLEAR_ROOT(&cfqq->sort_list); | 1665 | * it doesn't matter |
1221 | INIT_LIST_HEAD(&cfqq->fifo[0]); | 1666 | */ |
1222 | INIT_LIST_HEAD(&cfqq->fifo[1]); | 1667 | static void |
1668 | cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, | ||
1669 | struct cfq_io_context *cic) | ||
1670 | { | ||
1671 | int enable_idle = cfq_cfqq_idle_window(cfqq); | ||
1223 | 1672 | ||
1224 | cfqq->key = key; | 1673 | if (!cic->ioc->task || !cfqd->cfq_slice_idle) |
1225 | hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); | 1674 | enable_idle = 0; |
1226 | atomic_set(&cfqq->ref, 0); | 1675 | else if (sample_valid(cic->ttime_samples)) { |
1227 | cfqq->cfqd = cfqd; | 1676 | if (cic->ttime_mean > cfqd->cfq_slice_idle) |
1228 | atomic_inc(&cfqd->ref); | 1677 | enable_idle = 0; |
1229 | cfqq->key_type = cfqd->key_type; | 1678 | else |
1230 | cfqq->service_start = ~0UL; | 1679 | enable_idle = 1; |
1231 | } | 1680 | } |
1232 | 1681 | ||
1233 | if (new_cfqq) | 1682 | if (enable_idle) |
1234 | kmem_cache_free(cfq_pool, new_cfqq); | 1683 | cfq_mark_cfqq_idle_window(cfqq); |
1684 | else | ||
1685 | cfq_clear_cfqq_idle_window(cfqq); | ||
1686 | } | ||
1235 | 1687 | ||
1236 | atomic_inc(&cfqq->ref); | 1688 | |
1237 | out: | 1689 | /* |
1238 | WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq); | 1690 | * Check if new_cfqq should preempt the currently active queue. Return 0 for |
1239 | return cfqq; | 1691 | * no or if we aren't sure, a 1 will cause a preempt. |
1692 | */ | ||
1693 | static int | ||
1694 | cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | ||
1695 | struct cfq_rq *crq) | ||
1696 | { | ||
1697 | struct cfq_queue *cfqq = cfqd->active_queue; | ||
1698 | |||
1699 | if (cfq_class_idle(new_cfqq)) | ||
1700 | return 0; | ||
1701 | |||
1702 | if (!cfqq) | ||
1703 | return 1; | ||
1704 | |||
1705 | if (cfq_class_idle(cfqq)) | ||
1706 | return 1; | ||
1707 | if (!cfq_cfqq_wait_request(new_cfqq)) | ||
1708 | return 0; | ||
1709 | /* | ||
1710 | * if it doesn't have slice left, forget it | ||
1711 | */ | ||
1712 | if (new_cfqq->slice_left < cfqd->cfq_slice_idle) | ||
1713 | return 0; | ||
1714 | if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq)) | ||
1715 | return 1; | ||
1716 | |||
1717 | return 0; | ||
1718 | } | ||
1719 | |||
1720 | /* | ||
1721 | * cfqq preempts the active queue. if we allowed preempt with no slice left, | ||
1722 | * let it have half of its nominal slice. | ||
1723 | */ | ||
1724 | static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
1725 | { | ||
1726 | struct cfq_queue *__cfqq, *next; | ||
1727 | |||
1728 | list_for_each_entry_safe(__cfqq, next, &cfqd->cur_rr, cfq_list) | ||
1729 | cfq_resort_rr_list(__cfqq, 1); | ||
1730 | |||
1731 | if (!cfqq->slice_left) | ||
1732 | cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2; | ||
1733 | |||
1734 | cfqq->slice_end = cfqq->slice_left + jiffies; | ||
1735 | __cfq_slice_expired(cfqd, cfqq, 1); | ||
1736 | __cfq_set_active_queue(cfqd, cfqq); | ||
1737 | } | ||
1738 | |||
1739 | /* | ||
1740 | * should really be a ll_rw_blk.c helper | ||
1741 | */ | ||
1742 | static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
1743 | { | ||
1744 | request_queue_t *q = cfqd->queue; | ||
1745 | |||
1746 | if (!blk_queue_plugged(q)) | ||
1747 | q->request_fn(q); | ||
1748 | else | ||
1749 | __generic_unplug_device(q); | ||
1240 | } | 1750 | } |
1241 | 1751 | ||
1242 | static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq) | 1752 | /* |
1753 | * Called when a new fs request (crq) is added (to cfqq). Check if there's | ||
1754 | * something we should do about it | ||
1755 | */ | ||
1756 | static void | ||
1757 | cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | ||
1758 | struct cfq_rq *crq) | ||
1243 | { | 1759 | { |
1244 | crq->is_sync = 0; | 1760 | const int sync = cfq_crq_is_sync(crq); |
1245 | if (rq_data_dir(crq->request) == READ || current->flags & PF_SYNCWRITE) | 1761 | |
1246 | crq->is_sync = 1; | 1762 | cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); |
1763 | |||
1764 | if (sync) { | ||
1765 | struct cfq_io_context *cic = crq->io_context; | ||
1766 | |||
1767 | cfq_update_io_thinktime(cfqd, cic); | ||
1768 | cfq_update_idle_window(cfqd, cfqq, cic); | ||
1769 | |||
1770 | cic->last_queue = jiffies; | ||
1771 | } | ||
1772 | |||
1773 | if (cfqq == cfqd->active_queue) { | ||
1774 | /* | ||
1775 | * if we are waiting for a request for this queue, let it rip | ||
1776 | * immediately and flag that we must not expire this queue | ||
1777 | * just now | ||
1778 | */ | ||
1779 | if (cfq_cfqq_wait_request(cfqq)) { | ||
1780 | cfq_mark_cfqq_must_dispatch(cfqq); | ||
1781 | del_timer(&cfqd->idle_slice_timer); | ||
1782 | cfq_start_queueing(cfqd, cfqq); | ||
1783 | } | ||
1784 | } else if (cfq_should_preempt(cfqd, cfqq, crq)) { | ||
1785 | /* | ||
1786 | * not the active queue - expire current slice if it is | ||
1787 | * idle and has expired it's mean thinktime or this new queue | ||
1788 | * has some old slice time left and is of higher priority | ||
1789 | */ | ||
1790 | cfq_preempt_queue(cfqd, cfqq); | ||
1791 | cfq_mark_cfqq_must_dispatch(cfqq); | ||
1792 | cfq_start_queueing(cfqd, cfqq); | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq) | ||
1797 | { | ||
1798 | struct cfq_rq *crq = RQ_DATA(rq); | ||
1799 | struct cfq_queue *cfqq = crq->cfq_queue; | ||
1800 | |||
1801 | cfq_init_prio_data(cfqq); | ||
1247 | 1802 | ||
1248 | cfq_add_crq_rb(crq); | 1803 | cfq_add_crq_rb(crq); |
1249 | crq->queue_start = jiffies; | ||
1250 | 1804 | ||
1251 | list_add_tail(&crq->request->queuelist, &crq->cfq_queue->fifo[crq->is_sync]); | 1805 | list_add_tail(&rq->queuelist, &cfqq->fifo); |
1806 | |||
1807 | if (rq_mergeable(rq)) { | ||
1808 | cfq_add_crq_hash(cfqd, crq); | ||
1809 | |||
1810 | if (!cfqd->queue->last_merge) | ||
1811 | cfqd->queue->last_merge = rq; | ||
1812 | } | ||
1813 | |||
1814 | cfq_crq_enqueued(cfqd, cfqq, crq); | ||
1252 | } | 1815 | } |
1253 | 1816 | ||
1254 | static void | 1817 | static void |
1255 | cfq_insert_request(request_queue_t *q, struct request *rq, int where) | 1818 | cfq_insert_request(request_queue_t *q, struct request *rq, int where) |
1256 | { | 1819 | { |
1257 | struct cfq_data *cfqd = q->elevator->elevator_data; | 1820 | struct cfq_data *cfqd = q->elevator->elevator_data; |
1258 | struct cfq_rq *crq = RQ_DATA(rq); | ||
1259 | 1821 | ||
1260 | switch (where) { | 1822 | switch (where) { |
1261 | case ELEVATOR_INSERT_BACK: | 1823 | case ELEVATOR_INSERT_BACK: |
1262 | while (cfq_dispatch_requests(q, cfqd->cfq_quantum)) | 1824 | while (cfq_dispatch_requests(q, INT_MAX, 1)) |
1263 | ; | 1825 | ; |
1264 | list_add_tail(&rq->queuelist, &q->queue_head); | 1826 | list_add_tail(&rq->queuelist, &q->queue_head); |
1827 | /* | ||
1828 | * If we were idling with pending requests on | ||
1829 | * inactive cfqqs, force dispatching will | ||
1830 | * remove the idle timer and the queue won't | ||
1831 | * be kicked by __make_request() afterward. | ||
1832 | * Kick it here. | ||
1833 | */ | ||
1834 | cfq_schedule_dispatch(cfqd); | ||
1265 | break; | 1835 | break; |
1266 | case ELEVATOR_INSERT_FRONT: | 1836 | case ELEVATOR_INSERT_FRONT: |
1267 | list_add(&rq->queuelist, &q->queue_head); | 1837 | list_add(&rq->queuelist, &q->queue_head); |
1268 | break; | 1838 | break; |
1269 | case ELEVATOR_INSERT_SORT: | 1839 | case ELEVATOR_INSERT_SORT: |
1270 | BUG_ON(!blk_fs_request(rq)); | 1840 | BUG_ON(!blk_fs_request(rq)); |
1271 | cfq_enqueue(cfqd, crq); | 1841 | cfq_enqueue(cfqd, rq); |
1272 | break; | 1842 | break; |
1273 | default: | 1843 | default: |
1274 | printk("%s: bad insert point %d\n", __FUNCTION__,where); | 1844 | printk("%s: bad insert point %d\n", __FUNCTION__,where); |
1275 | return; | 1845 | return; |
1276 | } | 1846 | } |
1847 | } | ||
1277 | 1848 | ||
1278 | if (rq_mergeable(rq)) { | 1849 | static inline int cfq_pending_requests(struct cfq_data *cfqd) |
1279 | cfq_add_crq_hash(cfqd, crq); | 1850 | { |
1280 | 1851 | return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues; | |
1281 | if (!q->last_merge) | ||
1282 | q->last_merge = rq; | ||
1283 | } | ||
1284 | } | 1852 | } |
1285 | 1853 | ||
1286 | static int cfq_queue_empty(request_queue_t *q) | 1854 | static int cfq_queue_empty(request_queue_t *q) |
1287 | { | 1855 | { |
1288 | struct cfq_data *cfqd = q->elevator->elevator_data; | 1856 | struct cfq_data *cfqd = q->elevator->elevator_data; |
1289 | 1857 | ||
1290 | return list_empty(&q->queue_head) && list_empty(&cfqd->rr_list); | 1858 | return !cfq_pending_requests(cfqd); |
1291 | } | 1859 | } |
1292 | 1860 | ||
1293 | static void cfq_completed_request(request_queue_t *q, struct request *rq) | 1861 | static void cfq_completed_request(request_queue_t *q, struct request *rq) |
@@ -1300,9 +1868,11 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq) | |||
1300 | 1868 | ||
1301 | cfqq = crq->cfq_queue; | 1869 | cfqq = crq->cfq_queue; |
1302 | 1870 | ||
1303 | if (crq->in_flight) { | 1871 | if (cfq_crq_in_flight(crq)) { |
1304 | WARN_ON(!cfqq->in_flight); | 1872 | const int sync = cfq_crq_is_sync(crq); |
1305 | cfqq->in_flight--; | 1873 | |
1874 | WARN_ON(!cfqq->on_dispatch[sync]); | ||
1875 | cfqq->on_dispatch[sync]--; | ||
1306 | } | 1876 | } |
1307 | 1877 | ||
1308 | cfq_account_completion(cfqq, crq); | 1878 | cfq_account_completion(cfqq, crq); |
@@ -1332,51 +1902,136 @@ cfq_latter_request(request_queue_t *q, struct request *rq) | |||
1332 | return NULL; | 1902 | return NULL; |
1333 | } | 1903 | } |
1334 | 1904 | ||
1335 | static int cfq_may_queue(request_queue_t *q, int rw) | 1905 | /* |
1906 | * we temporarily boost lower priority queues if they are holding fs exclusive | ||
1907 | * resources. they are boosted to normal prio (CLASS_BE/4) | ||
1908 | */ | ||
1909 | static void cfq_prio_boost(struct cfq_queue *cfqq) | ||
1336 | { | 1910 | { |
1337 | struct cfq_data *cfqd = q->elevator->elevator_data; | 1911 | const int ioprio_class = cfqq->ioprio_class; |
1338 | struct cfq_queue *cfqq; | 1912 | const int ioprio = cfqq->ioprio; |
1339 | int ret = ELV_MQUEUE_MAY; | ||
1340 | 1913 | ||
1341 | if (current->flags & PF_MEMALLOC) | 1914 | if (has_fs_excl()) { |
1342 | return ELV_MQUEUE_MAY; | 1915 | /* |
1916 | * boost idle prio on transactions that would lock out other | ||
1917 | * users of the filesystem | ||
1918 | */ | ||
1919 | if (cfq_class_idle(cfqq)) | ||
1920 | cfqq->ioprio_class = IOPRIO_CLASS_BE; | ||
1921 | if (cfqq->ioprio > IOPRIO_NORM) | ||
1922 | cfqq->ioprio = IOPRIO_NORM; | ||
1923 | } else { | ||
1924 | /* | ||
1925 | * check if we need to unboost the queue | ||
1926 | */ | ||
1927 | if (cfqq->ioprio_class != cfqq->org_ioprio_class) | ||
1928 | cfqq->ioprio_class = cfqq->org_ioprio_class; | ||
1929 | if (cfqq->ioprio != cfqq->org_ioprio) | ||
1930 | cfqq->ioprio = cfqq->org_ioprio; | ||
1931 | } | ||
1343 | 1932 | ||
1344 | cfqq = cfq_find_cfq_hash(cfqd, cfq_hash_key(cfqd, current)); | 1933 | /* |
1345 | if (cfqq) { | 1934 | * refile between round-robin lists if we moved the priority class |
1346 | int limit = cfqd->max_queued; | 1935 | */ |
1936 | if ((ioprio_class != cfqq->ioprio_class || ioprio != cfqq->ioprio) && | ||
1937 | cfq_cfqq_on_rr(cfqq)) | ||
1938 | cfq_resort_rr_list(cfqq, 0); | ||
1939 | } | ||
1347 | 1940 | ||
1348 | if (cfqq->allocated[rw] < cfqd->cfq_queued) | 1941 | static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) |
1349 | return ELV_MQUEUE_MUST; | 1942 | { |
1943 | if (rw == READ || process_sync(task)) | ||
1944 | return task->pid; | ||
1350 | 1945 | ||
1351 | if (cfqd->busy_queues) | 1946 | return CFQ_KEY_ASYNC; |
1352 | limit = q->nr_requests / cfqd->busy_queues; | 1947 | } |
1353 | 1948 | ||
1354 | if (limit < cfqd->cfq_queued) | 1949 | static inline int |
1355 | limit = cfqd->cfq_queued; | 1950 | __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
1356 | else if (limit > cfqd->max_queued) | 1951 | struct task_struct *task, int rw) |
1357 | limit = cfqd->max_queued; | 1952 | { |
1953 | #if 1 | ||
1954 | if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && | ||
1955 | !cfq_cfqq_must_alloc_slice) { | ||
1956 | cfq_mark_cfqq_must_alloc_slice(cfqq); | ||
1957 | return ELV_MQUEUE_MUST; | ||
1958 | } | ||
1358 | 1959 | ||
1359 | if (cfqq->allocated[rw] >= limit) { | 1960 | return ELV_MQUEUE_MAY; |
1360 | if (limit > cfqq->alloc_limit[rw]) | 1961 | #else |
1361 | cfqq->alloc_limit[rw] = limit; | 1962 | if (!cfqq || task->flags & PF_MEMALLOC) |
1963 | return ELV_MQUEUE_MAY; | ||
1964 | if (!cfqq->allocated[rw] || cfq_cfqq_must_alloc(cfqq)) { | ||
1965 | if (cfq_cfqq_wait_request(cfqq)) | ||
1966 | return ELV_MQUEUE_MUST; | ||
1362 | 1967 | ||
1363 | ret = ELV_MQUEUE_NO; | 1968 | /* |
1969 | * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we | ||
1970 | * can quickly flood the queue with writes from a single task | ||
1971 | */ | ||
1972 | if (rw == READ || !cfq_cfqq_must_alloc_slice) { | ||
1973 | cfq_mark_cfqq_must_alloc_slice(cfqq); | ||
1974 | return ELV_MQUEUE_MUST; | ||
1364 | } | 1975 | } |
1976 | |||
1977 | return ELV_MQUEUE_MAY; | ||
1365 | } | 1978 | } |
1979 | if (cfq_class_idle(cfqq)) | ||
1980 | return ELV_MQUEUE_NO; | ||
1981 | if (cfqq->allocated[rw] >= cfqd->max_queued) { | ||
1982 | struct io_context *ioc = get_io_context(GFP_ATOMIC); | ||
1983 | int ret = ELV_MQUEUE_NO; | ||
1366 | 1984 | ||
1367 | return ret; | 1985 | if (ioc && ioc->nr_batch_requests) |
1986 | ret = ELV_MQUEUE_MAY; | ||
1987 | |||
1988 | put_io_context(ioc); | ||
1989 | return ret; | ||
1990 | } | ||
1991 | |||
1992 | return ELV_MQUEUE_MAY; | ||
1993 | #endif | ||
1994 | } | ||
1995 | |||
1996 | static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio) | ||
1997 | { | ||
1998 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
1999 | struct task_struct *tsk = current; | ||
2000 | struct cfq_queue *cfqq; | ||
2001 | |||
2002 | /* | ||
2003 | * don't force setup of a queue from here, as a call to may_queue | ||
2004 | * does not necessarily imply that a request actually will be queued. | ||
2005 | * so just lookup a possibly existing queue, or return 'may queue' | ||
2006 | * if that fails | ||
2007 | */ | ||
2008 | cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio); | ||
2009 | if (cfqq) { | ||
2010 | cfq_init_prio_data(cfqq); | ||
2011 | cfq_prio_boost(cfqq); | ||
2012 | |||
2013 | return __cfq_may_queue(cfqd, cfqq, tsk, rw); | ||
2014 | } | ||
2015 | |||
2016 | return ELV_MQUEUE_MAY; | ||
1368 | } | 2017 | } |
1369 | 2018 | ||
1370 | static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq) | 2019 | static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq) |
1371 | { | 2020 | { |
2021 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
1372 | struct request_list *rl = &q->rq; | 2022 | struct request_list *rl = &q->rq; |
1373 | const int write = waitqueue_active(&rl->wait[WRITE]); | ||
1374 | const int read = waitqueue_active(&rl->wait[READ]); | ||
1375 | 2023 | ||
1376 | if (read && cfqq->allocated[READ] < cfqq->alloc_limit[READ]) | 2024 | if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) { |
1377 | wake_up(&rl->wait[READ]); | 2025 | smp_mb(); |
1378 | if (write && cfqq->allocated[WRITE] < cfqq->alloc_limit[WRITE]) | 2026 | if (waitqueue_active(&rl->wait[READ])) |
1379 | wake_up(&rl->wait[WRITE]); | 2027 | wake_up(&rl->wait[READ]); |
2028 | } | ||
2029 | |||
2030 | if (cfqq->allocated[WRITE] <= cfqd->max_queued || cfqd->rq_starved) { | ||
2031 | smp_mb(); | ||
2032 | if (waitqueue_active(&rl->wait[WRITE])) | ||
2033 | wake_up(&rl->wait[WRITE]); | ||
2034 | } | ||
1380 | } | 2035 | } |
1381 | 2036 | ||
1382 | /* | 2037 | /* |
@@ -1389,69 +2044,61 @@ static void cfq_put_request(request_queue_t *q, struct request *rq) | |||
1389 | 2044 | ||
1390 | if (crq) { | 2045 | if (crq) { |
1391 | struct cfq_queue *cfqq = crq->cfq_queue; | 2046 | struct cfq_queue *cfqq = crq->cfq_queue; |
2047 | const int rw = rq_data_dir(rq); | ||
1392 | 2048 | ||
1393 | BUG_ON(q->last_merge == rq); | 2049 | BUG_ON(!cfqq->allocated[rw]); |
1394 | BUG_ON(!hlist_unhashed(&crq->hash)); | 2050 | cfqq->allocated[rw]--; |
1395 | 2051 | ||
1396 | if (crq->io_context) | 2052 | put_io_context(crq->io_context->ioc); |
1397 | put_io_context(crq->io_context->ioc); | ||
1398 | |||
1399 | BUG_ON(!cfqq->allocated[crq->is_write]); | ||
1400 | cfqq->allocated[crq->is_write]--; | ||
1401 | 2053 | ||
1402 | mempool_free(crq, cfqd->crq_pool); | 2054 | mempool_free(crq, cfqd->crq_pool); |
1403 | rq->elevator_private = NULL; | 2055 | rq->elevator_private = NULL; |
1404 | 2056 | ||
1405 | smp_mb(); | ||
1406 | cfq_check_waiters(q, cfqq); | 2057 | cfq_check_waiters(q, cfqq); |
1407 | cfq_put_queue(cfqq); | 2058 | cfq_put_queue(cfqq); |
1408 | } | 2059 | } |
1409 | } | 2060 | } |
1410 | 2061 | ||
1411 | /* | 2062 | /* |
1412 | * Allocate cfq data structures associated with this request. A queue and | 2063 | * Allocate cfq data structures associated with this request. |
1413 | */ | 2064 | */ |
1414 | static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask) | 2065 | static int |
2066 | cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, | ||
2067 | int gfp_mask) | ||
1415 | { | 2068 | { |
1416 | struct cfq_data *cfqd = q->elevator->elevator_data; | 2069 | struct cfq_data *cfqd = q->elevator->elevator_data; |
2070 | struct task_struct *tsk = current; | ||
1417 | struct cfq_io_context *cic; | 2071 | struct cfq_io_context *cic; |
1418 | const int rw = rq_data_dir(rq); | 2072 | const int rw = rq_data_dir(rq); |
1419 | struct cfq_queue *cfqq, *saved_cfqq; | 2073 | pid_t key = cfq_queue_pid(tsk, rw); |
2074 | struct cfq_queue *cfqq; | ||
1420 | struct cfq_rq *crq; | 2075 | struct cfq_rq *crq; |
1421 | unsigned long flags; | 2076 | unsigned long flags; |
1422 | 2077 | ||
1423 | might_sleep_if(gfp_mask & __GFP_WAIT); | 2078 | might_sleep_if(gfp_mask & __GFP_WAIT); |
1424 | 2079 | ||
2080 | cic = cfq_get_io_context(cfqd, key, gfp_mask); | ||
2081 | |||
1425 | spin_lock_irqsave(q->queue_lock, flags); | 2082 | spin_lock_irqsave(q->queue_lock, flags); |
1426 | 2083 | ||
1427 | cfqq = __cfq_get_queue(cfqd, cfq_hash_key(cfqd, current), gfp_mask); | 2084 | if (!cic) |
1428 | if (!cfqq) | 2085 | goto queue_fail; |
1429 | goto out_lock; | 2086 | |
2087 | if (!cic->cfqq) { | ||
2088 | cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask); | ||
2089 | if (!cfqq) | ||
2090 | goto queue_fail; | ||
1430 | 2091 | ||
1431 | repeat: | 2092 | cic->cfqq = cfqq; |
1432 | if (cfqq->allocated[rw] >= cfqd->max_queued) | 2093 | } else |
1433 | goto out_lock; | 2094 | cfqq = cic->cfqq; |
1434 | 2095 | ||
1435 | cfqq->allocated[rw]++; | 2096 | cfqq->allocated[rw]++; |
2097 | cfq_clear_cfqq_must_alloc(cfqq); | ||
2098 | cfqd->rq_starved = 0; | ||
2099 | atomic_inc(&cfqq->ref); | ||
1436 | spin_unlock_irqrestore(q->queue_lock, flags); | 2100 | spin_unlock_irqrestore(q->queue_lock, flags); |
1437 | 2101 | ||
1438 | /* | ||
1439 | * if hashing type has changed, the cfq_queue might change here. | ||
1440 | */ | ||
1441 | saved_cfqq = cfqq; | ||
1442 | cic = cfq_get_io_context(&cfqq, gfp_mask); | ||
1443 | if (!cic) | ||
1444 | goto err; | ||
1445 | |||
1446 | /* | ||
1447 | * repeat allocation checks on queue change | ||
1448 | */ | ||
1449 | if (unlikely(saved_cfqq != cfqq)) { | ||
1450 | spin_lock_irqsave(q->queue_lock, flags); | ||
1451 | saved_cfqq->allocated[rw]--; | ||
1452 | goto repeat; | ||
1453 | } | ||
1454 | |||
1455 | crq = mempool_alloc(cfqd->crq_pool, gfp_mask); | 2102 | crq = mempool_alloc(cfqd->crq_pool, gfp_mask); |
1456 | if (crq) { | 2103 | if (crq) { |
1457 | RB_CLEAR(&crq->rb_node); | 2104 | RB_CLEAR(&crq->rb_node); |
@@ -1460,24 +2107,141 @@ repeat: | |||
1460 | INIT_HLIST_NODE(&crq->hash); | 2107 | INIT_HLIST_NODE(&crq->hash); |
1461 | crq->cfq_queue = cfqq; | 2108 | crq->cfq_queue = cfqq; |
1462 | crq->io_context = cic; | 2109 | crq->io_context = cic; |
1463 | crq->service_start = crq->queue_start = 0; | 2110 | cfq_clear_crq_in_flight(crq); |
1464 | crq->in_flight = crq->accounted = crq->is_sync = 0; | 2111 | cfq_clear_crq_in_driver(crq); |
1465 | crq->is_write = rw; | 2112 | cfq_clear_crq_requeued(crq); |
2113 | |||
2114 | if (rw == READ || process_sync(tsk)) | ||
2115 | cfq_mark_crq_is_sync(crq); | ||
2116 | else | ||
2117 | cfq_clear_crq_is_sync(crq); | ||
2118 | |||
1466 | rq->elevator_private = crq; | 2119 | rq->elevator_private = crq; |
1467 | cfqq->alloc_limit[rw] = 0; | ||
1468 | return 0; | 2120 | return 0; |
1469 | } | 2121 | } |
1470 | 2122 | ||
1471 | put_io_context(cic->ioc); | ||
1472 | err: | ||
1473 | spin_lock_irqsave(q->queue_lock, flags); | 2123 | spin_lock_irqsave(q->queue_lock, flags); |
1474 | cfqq->allocated[rw]--; | 2124 | cfqq->allocated[rw]--; |
2125 | if (!(cfqq->allocated[0] + cfqq->allocated[1])) | ||
2126 | cfq_mark_cfqq_must_alloc(cfqq); | ||
1475 | cfq_put_queue(cfqq); | 2127 | cfq_put_queue(cfqq); |
1476 | out_lock: | 2128 | queue_fail: |
2129 | if (cic) | ||
2130 | put_io_context(cic->ioc); | ||
2131 | /* | ||
2132 | * mark us rq allocation starved. we need to kickstart the process | ||
2133 | * ourselves if there are no pending requests that can do it for us. | ||
2134 | * that would be an extremely rare OOM situation | ||
2135 | */ | ||
2136 | cfqd->rq_starved = 1; | ||
2137 | cfq_schedule_dispatch(cfqd); | ||
1477 | spin_unlock_irqrestore(q->queue_lock, flags); | 2138 | spin_unlock_irqrestore(q->queue_lock, flags); |
1478 | return 1; | 2139 | return 1; |
1479 | } | 2140 | } |
1480 | 2141 | ||
2142 | static void cfq_kick_queue(void *data) | ||
2143 | { | ||
2144 | request_queue_t *q = data; | ||
2145 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
2146 | unsigned long flags; | ||
2147 | |||
2148 | spin_lock_irqsave(q->queue_lock, flags); | ||
2149 | |||
2150 | if (cfqd->rq_starved) { | ||
2151 | struct request_list *rl = &q->rq; | ||
2152 | |||
2153 | /* | ||
2154 | * we aren't guaranteed to get a request after this, but we | ||
2155 | * have to be opportunistic | ||
2156 | */ | ||
2157 | smp_mb(); | ||
2158 | if (waitqueue_active(&rl->wait[READ])) | ||
2159 | wake_up(&rl->wait[READ]); | ||
2160 | if (waitqueue_active(&rl->wait[WRITE])) | ||
2161 | wake_up(&rl->wait[WRITE]); | ||
2162 | } | ||
2163 | |||
2164 | blk_remove_plug(q); | ||
2165 | q->request_fn(q); | ||
2166 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
2167 | } | ||
2168 | |||
2169 | /* | ||
2170 | * Timer running if the active_queue is currently idling inside its time slice | ||
2171 | */ | ||
2172 | static void cfq_idle_slice_timer(unsigned long data) | ||
2173 | { | ||
2174 | struct cfq_data *cfqd = (struct cfq_data *) data; | ||
2175 | struct cfq_queue *cfqq; | ||
2176 | unsigned long flags; | ||
2177 | |||
2178 | spin_lock_irqsave(cfqd->queue->queue_lock, flags); | ||
2179 | |||
2180 | if ((cfqq = cfqd->active_queue) != NULL) { | ||
2181 | unsigned long now = jiffies; | ||
2182 | |||
2183 | /* | ||
2184 | * expired | ||
2185 | */ | ||
2186 | if (time_after(now, cfqq->slice_end)) | ||
2187 | goto expire; | ||
2188 | |||
2189 | /* | ||
2190 | * only expire and reinvoke request handler, if there are | ||
2191 | * other queues with pending requests | ||
2192 | */ | ||
2193 | if (!cfq_pending_requests(cfqd)) { | ||
2194 | cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end); | ||
2195 | add_timer(&cfqd->idle_slice_timer); | ||
2196 | goto out_cont; | ||
2197 | } | ||
2198 | |||
2199 | /* | ||
2200 | * not expired and it has a request pending, let it dispatch | ||
2201 | */ | ||
2202 | if (!RB_EMPTY(&cfqq->sort_list)) { | ||
2203 | cfq_mark_cfqq_must_dispatch(cfqq); | ||
2204 | goto out_kick; | ||
2205 | } | ||
2206 | } | ||
2207 | expire: | ||
2208 | cfq_slice_expired(cfqd, 0); | ||
2209 | out_kick: | ||
2210 | cfq_schedule_dispatch(cfqd); | ||
2211 | out_cont: | ||
2212 | spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); | ||
2213 | } | ||
2214 | |||
2215 | /* | ||
2216 | * Timer running if an idle class queue is waiting for service | ||
2217 | */ | ||
2218 | static void cfq_idle_class_timer(unsigned long data) | ||
2219 | { | ||
2220 | struct cfq_data *cfqd = (struct cfq_data *) data; | ||
2221 | unsigned long flags, end; | ||
2222 | |||
2223 | spin_lock_irqsave(cfqd->queue->queue_lock, flags); | ||
2224 | |||
2225 | /* | ||
2226 | * race with a non-idle queue, reset timer | ||
2227 | */ | ||
2228 | end = cfqd->last_end_request + CFQ_IDLE_GRACE; | ||
2229 | if (!time_after_eq(jiffies, end)) { | ||
2230 | cfqd->idle_class_timer.expires = end; | ||
2231 | add_timer(&cfqd->idle_class_timer); | ||
2232 | } else | ||
2233 | cfq_schedule_dispatch(cfqd); | ||
2234 | |||
2235 | spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); | ||
2236 | } | ||
2237 | |||
2238 | static void cfq_shutdown_timer_wq(struct cfq_data *cfqd) | ||
2239 | { | ||
2240 | del_timer_sync(&cfqd->idle_slice_timer); | ||
2241 | del_timer_sync(&cfqd->idle_class_timer); | ||
2242 | blk_sync_queue(cfqd->queue); | ||
2243 | } | ||
2244 | |||
1481 | static void cfq_put_cfqd(struct cfq_data *cfqd) | 2245 | static void cfq_put_cfqd(struct cfq_data *cfqd) |
1482 | { | 2246 | { |
1483 | request_queue_t *q = cfqd->queue; | 2247 | request_queue_t *q = cfqd->queue; |
@@ -1487,6 +2251,9 @@ static void cfq_put_cfqd(struct cfq_data *cfqd) | |||
1487 | 2251 | ||
1488 | blk_put_queue(q); | 2252 | blk_put_queue(q); |
1489 | 2253 | ||
2254 | cfq_shutdown_timer_wq(cfqd); | ||
2255 | q->elevator->elevator_data = NULL; | ||
2256 | |||
1490 | mempool_destroy(cfqd->crq_pool); | 2257 | mempool_destroy(cfqd->crq_pool); |
1491 | kfree(cfqd->crq_hash); | 2258 | kfree(cfqd->crq_hash); |
1492 | kfree(cfqd->cfq_hash); | 2259 | kfree(cfqd->cfq_hash); |
@@ -1495,7 +2262,10 @@ static void cfq_put_cfqd(struct cfq_data *cfqd) | |||
1495 | 2262 | ||
1496 | static void cfq_exit_queue(elevator_t *e) | 2263 | static void cfq_exit_queue(elevator_t *e) |
1497 | { | 2264 | { |
1498 | cfq_put_cfqd(e->elevator_data); | 2265 | struct cfq_data *cfqd = e->elevator_data; |
2266 | |||
2267 | cfq_shutdown_timer_wq(cfqd); | ||
2268 | cfq_put_cfqd(cfqd); | ||
1499 | } | 2269 | } |
1500 | 2270 | ||
1501 | static int cfq_init_queue(request_queue_t *q, elevator_t *e) | 2271 | static int cfq_init_queue(request_queue_t *q, elevator_t *e) |
@@ -1508,7 +2278,13 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e) | |||
1508 | return -ENOMEM; | 2278 | return -ENOMEM; |
1509 | 2279 | ||
1510 | memset(cfqd, 0, sizeof(*cfqd)); | 2280 | memset(cfqd, 0, sizeof(*cfqd)); |
1511 | INIT_LIST_HEAD(&cfqd->rr_list); | 2281 | |
2282 | for (i = 0; i < CFQ_PRIO_LISTS; i++) | ||
2283 | INIT_LIST_HEAD(&cfqd->rr_list[i]); | ||
2284 | |||
2285 | INIT_LIST_HEAD(&cfqd->busy_rr); | ||
2286 | INIT_LIST_HEAD(&cfqd->cur_rr); | ||
2287 | INIT_LIST_HEAD(&cfqd->idle_rr); | ||
1512 | INIT_LIST_HEAD(&cfqd->empty_list); | 2288 | INIT_LIST_HEAD(&cfqd->empty_list); |
1513 | 2289 | ||
1514 | cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); | 2290 | cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); |
@@ -1533,24 +2309,32 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e) | |||
1533 | cfqd->queue = q; | 2309 | cfqd->queue = q; |
1534 | atomic_inc(&q->refcnt); | 2310 | atomic_inc(&q->refcnt); |
1535 | 2311 | ||
1536 | /* | 2312 | cfqd->max_queued = q->nr_requests / 4; |
1537 | * just set it to some high value, we want anyone to be able to queue | ||
1538 | * some requests. fairness is handled differently | ||
1539 | */ | ||
1540 | q->nr_requests = 1024; | ||
1541 | cfqd->max_queued = q->nr_requests / 16; | ||
1542 | q->nr_batching = cfq_queued; | 2313 | q->nr_batching = cfq_queued; |
1543 | cfqd->key_type = CFQ_KEY_TGID; | 2314 | |
1544 | cfqd->find_best_crq = 1; | 2315 | init_timer(&cfqd->idle_slice_timer); |
2316 | cfqd->idle_slice_timer.function = cfq_idle_slice_timer; | ||
2317 | cfqd->idle_slice_timer.data = (unsigned long) cfqd; | ||
2318 | |||
2319 | init_timer(&cfqd->idle_class_timer); | ||
2320 | cfqd->idle_class_timer.function = cfq_idle_class_timer; | ||
2321 | cfqd->idle_class_timer.data = (unsigned long) cfqd; | ||
2322 | |||
2323 | INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); | ||
2324 | |||
1545 | atomic_set(&cfqd->ref, 1); | 2325 | atomic_set(&cfqd->ref, 1); |
1546 | 2326 | ||
1547 | cfqd->cfq_queued = cfq_queued; | 2327 | cfqd->cfq_queued = cfq_queued; |
1548 | cfqd->cfq_quantum = cfq_quantum; | 2328 | cfqd->cfq_quantum = cfq_quantum; |
1549 | cfqd->cfq_fifo_expire_r = cfq_fifo_expire_r; | 2329 | cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; |
1550 | cfqd->cfq_fifo_expire_w = cfq_fifo_expire_w; | 2330 | cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1]; |
1551 | cfqd->cfq_fifo_batch_expire = cfq_fifo_rate; | ||
1552 | cfqd->cfq_back_max = cfq_back_max; | 2331 | cfqd->cfq_back_max = cfq_back_max; |
1553 | cfqd->cfq_back_penalty = cfq_back_penalty; | 2332 | cfqd->cfq_back_penalty = cfq_back_penalty; |
2333 | cfqd->cfq_slice[0] = cfq_slice_async; | ||
2334 | cfqd->cfq_slice[1] = cfq_slice_sync; | ||
2335 | cfqd->cfq_slice_async_rq = cfq_slice_async_rq; | ||
2336 | cfqd->cfq_slice_idle = cfq_slice_idle; | ||
2337 | cfqd->cfq_max_depth = cfq_max_depth; | ||
1554 | 2338 | ||
1555 | return 0; | 2339 | return 0; |
1556 | out_crqpool: | 2340 | out_crqpool: |
@@ -1595,7 +2379,6 @@ fail: | |||
1595 | return -ENOMEM; | 2379 | return -ENOMEM; |
1596 | } | 2380 | } |
1597 | 2381 | ||
1598 | |||
1599 | /* | 2382 | /* |
1600 | * sysfs parts below --> | 2383 | * sysfs parts below --> |
1601 | */ | 2384 | */ |
@@ -1620,45 +2403,6 @@ cfq_var_store(unsigned int *var, const char *page, size_t count) | |||
1620 | return count; | 2403 | return count; |
1621 | } | 2404 | } |
1622 | 2405 | ||
1623 | static ssize_t | ||
1624 | cfq_clear_elapsed(struct cfq_data *cfqd, const char *page, size_t count) | ||
1625 | { | ||
1626 | max_elapsed_dispatch = max_elapsed_crq = 0; | ||
1627 | return count; | ||
1628 | } | ||
1629 | |||
1630 | static ssize_t | ||
1631 | cfq_set_key_type(struct cfq_data *cfqd, const char *page, size_t count) | ||
1632 | { | ||
1633 | spin_lock_irq(cfqd->queue->queue_lock); | ||
1634 | if (!strncmp(page, "pgid", 4)) | ||
1635 | cfqd->key_type = CFQ_KEY_PGID; | ||
1636 | else if (!strncmp(page, "tgid", 4)) | ||
1637 | cfqd->key_type = CFQ_KEY_TGID; | ||
1638 | else if (!strncmp(page, "uid", 3)) | ||
1639 | cfqd->key_type = CFQ_KEY_UID; | ||
1640 | else if (!strncmp(page, "gid", 3)) | ||
1641 | cfqd->key_type = CFQ_KEY_GID; | ||
1642 | spin_unlock_irq(cfqd->queue->queue_lock); | ||
1643 | return count; | ||
1644 | } | ||
1645 | |||
1646 | static ssize_t | ||
1647 | cfq_read_key_type(struct cfq_data *cfqd, char *page) | ||
1648 | { | ||
1649 | ssize_t len = 0; | ||
1650 | int i; | ||
1651 | |||
1652 | for (i = CFQ_KEY_PGID; i < CFQ_KEY_LAST; i++) { | ||
1653 | if (cfqd->key_type == i) | ||
1654 | len += sprintf(page+len, "[%s] ", cfq_key_types[i]); | ||
1655 | else | ||
1656 | len += sprintf(page+len, "%s ", cfq_key_types[i]); | ||
1657 | } | ||
1658 | len += sprintf(page+len, "\n"); | ||
1659 | return len; | ||
1660 | } | ||
1661 | |||
1662 | #define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ | 2406 | #define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ |
1663 | static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ | 2407 | static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ |
1664 | { \ | 2408 | { \ |
@@ -1669,12 +2413,15 @@ static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ | |||
1669 | } | 2413 | } |
1670 | SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0); | 2414 | SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0); |
1671 | SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0); | 2415 | SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0); |
1672 | SHOW_FUNCTION(cfq_fifo_expire_r_show, cfqd->cfq_fifo_expire_r, 1); | 2416 | SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1); |
1673 | SHOW_FUNCTION(cfq_fifo_expire_w_show, cfqd->cfq_fifo_expire_w, 1); | 2417 | SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1); |
1674 | SHOW_FUNCTION(cfq_fifo_batch_expire_show, cfqd->cfq_fifo_batch_expire, 1); | ||
1675 | SHOW_FUNCTION(cfq_find_best_show, cfqd->find_best_crq, 0); | ||
1676 | SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0); | 2418 | SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0); |
1677 | SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0); | 2419 | SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0); |
2420 | SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1); | ||
2421 | SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); | ||
2422 | SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); | ||
2423 | SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); | ||
2424 | SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0); | ||
1678 | #undef SHOW_FUNCTION | 2425 | #undef SHOW_FUNCTION |
1679 | 2426 | ||
1680 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ | 2427 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ |
@@ -1694,12 +2441,15 @@ static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \ | |||
1694 | } | 2441 | } |
1695 | STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0); | 2442 | STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0); |
1696 | STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0); | 2443 | STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0); |
1697 | STORE_FUNCTION(cfq_fifo_expire_r_store, &cfqd->cfq_fifo_expire_r, 1, UINT_MAX, 1); | 2444 | STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1); |
1698 | STORE_FUNCTION(cfq_fifo_expire_w_store, &cfqd->cfq_fifo_expire_w, 1, UINT_MAX, 1); | 2445 | STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1); |
1699 | STORE_FUNCTION(cfq_fifo_batch_expire_store, &cfqd->cfq_fifo_batch_expire, 0, UINT_MAX, 1); | ||
1700 | STORE_FUNCTION(cfq_find_best_store, &cfqd->find_best_crq, 0, 1, 0); | ||
1701 | STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); | 2446 | STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); |
1702 | STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0); | 2447 | STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0); |
2448 | STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1); | ||
2449 | STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); | ||
2450 | STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); | ||
2451 | STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0); | ||
2452 | STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); | ||
1703 | #undef STORE_FUNCTION | 2453 | #undef STORE_FUNCTION |
1704 | 2454 | ||
1705 | static struct cfq_fs_entry cfq_quantum_entry = { | 2455 | static struct cfq_fs_entry cfq_quantum_entry = { |
@@ -1712,25 +2462,15 @@ static struct cfq_fs_entry cfq_queued_entry = { | |||
1712 | .show = cfq_queued_show, | 2462 | .show = cfq_queued_show, |
1713 | .store = cfq_queued_store, | 2463 | .store = cfq_queued_store, |
1714 | }; | 2464 | }; |
1715 | static struct cfq_fs_entry cfq_fifo_expire_r_entry = { | 2465 | static struct cfq_fs_entry cfq_fifo_expire_sync_entry = { |
1716 | .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, | 2466 | .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, |
1717 | .show = cfq_fifo_expire_r_show, | 2467 | .show = cfq_fifo_expire_sync_show, |
1718 | .store = cfq_fifo_expire_r_store, | 2468 | .store = cfq_fifo_expire_sync_store, |
1719 | }; | 2469 | }; |
1720 | static struct cfq_fs_entry cfq_fifo_expire_w_entry = { | 2470 | static struct cfq_fs_entry cfq_fifo_expire_async_entry = { |
1721 | .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR }, | 2471 | .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR }, |
1722 | .show = cfq_fifo_expire_w_show, | 2472 | .show = cfq_fifo_expire_async_show, |
1723 | .store = cfq_fifo_expire_w_store, | 2473 | .store = cfq_fifo_expire_async_store, |
1724 | }; | ||
1725 | static struct cfq_fs_entry cfq_fifo_batch_expire_entry = { | ||
1726 | .attr = {.name = "fifo_batch_expire", .mode = S_IRUGO | S_IWUSR }, | ||
1727 | .show = cfq_fifo_batch_expire_show, | ||
1728 | .store = cfq_fifo_batch_expire_store, | ||
1729 | }; | ||
1730 | static struct cfq_fs_entry cfq_find_best_entry = { | ||
1731 | .attr = {.name = "find_best_crq", .mode = S_IRUGO | S_IWUSR }, | ||
1732 | .show = cfq_find_best_show, | ||
1733 | .store = cfq_find_best_store, | ||
1734 | }; | 2474 | }; |
1735 | static struct cfq_fs_entry cfq_back_max_entry = { | 2475 | static struct cfq_fs_entry cfq_back_max_entry = { |
1736 | .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR }, | 2476 | .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR }, |
@@ -1742,27 +2482,44 @@ static struct cfq_fs_entry cfq_back_penalty_entry = { | |||
1742 | .show = cfq_back_penalty_show, | 2482 | .show = cfq_back_penalty_show, |
1743 | .store = cfq_back_penalty_store, | 2483 | .store = cfq_back_penalty_store, |
1744 | }; | 2484 | }; |
1745 | static struct cfq_fs_entry cfq_clear_elapsed_entry = { | 2485 | static struct cfq_fs_entry cfq_slice_sync_entry = { |
1746 | .attr = {.name = "clear_elapsed", .mode = S_IWUSR }, | 2486 | .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR }, |
1747 | .store = cfq_clear_elapsed, | 2487 | .show = cfq_slice_sync_show, |
2488 | .store = cfq_slice_sync_store, | ||
2489 | }; | ||
2490 | static struct cfq_fs_entry cfq_slice_async_entry = { | ||
2491 | .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR }, | ||
2492 | .show = cfq_slice_async_show, | ||
2493 | .store = cfq_slice_async_store, | ||
1748 | }; | 2494 | }; |
1749 | static struct cfq_fs_entry cfq_key_type_entry = { | 2495 | static struct cfq_fs_entry cfq_slice_async_rq_entry = { |
1750 | .attr = {.name = "key_type", .mode = S_IRUGO | S_IWUSR }, | 2496 | .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR }, |
1751 | .show = cfq_read_key_type, | 2497 | .show = cfq_slice_async_rq_show, |
1752 | .store = cfq_set_key_type, | 2498 | .store = cfq_slice_async_rq_store, |
2499 | }; | ||
2500 | static struct cfq_fs_entry cfq_slice_idle_entry = { | ||
2501 | .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR }, | ||
2502 | .show = cfq_slice_idle_show, | ||
2503 | .store = cfq_slice_idle_store, | ||
2504 | }; | ||
2505 | static struct cfq_fs_entry cfq_max_depth_entry = { | ||
2506 | .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR }, | ||
2507 | .show = cfq_max_depth_show, | ||
2508 | .store = cfq_max_depth_store, | ||
1753 | }; | 2509 | }; |
1754 | 2510 | ||
1755 | static struct attribute *default_attrs[] = { | 2511 | static struct attribute *default_attrs[] = { |
1756 | &cfq_quantum_entry.attr, | 2512 | &cfq_quantum_entry.attr, |
1757 | &cfq_queued_entry.attr, | 2513 | &cfq_queued_entry.attr, |
1758 | &cfq_fifo_expire_r_entry.attr, | 2514 | &cfq_fifo_expire_sync_entry.attr, |
1759 | &cfq_fifo_expire_w_entry.attr, | 2515 | &cfq_fifo_expire_async_entry.attr, |
1760 | &cfq_fifo_batch_expire_entry.attr, | ||
1761 | &cfq_key_type_entry.attr, | ||
1762 | &cfq_find_best_entry.attr, | ||
1763 | &cfq_back_max_entry.attr, | 2516 | &cfq_back_max_entry.attr, |
1764 | &cfq_back_penalty_entry.attr, | 2517 | &cfq_back_penalty_entry.attr, |
1765 | &cfq_clear_elapsed_entry.attr, | 2518 | &cfq_slice_sync_entry.attr, |
2519 | &cfq_slice_async_entry.attr, | ||
2520 | &cfq_slice_async_rq_entry.attr, | ||
2521 | &cfq_slice_idle_entry.attr, | ||
2522 | &cfq_max_depth_entry.attr, | ||
1766 | NULL, | 2523 | NULL, |
1767 | }; | 2524 | }; |
1768 | 2525 | ||
@@ -1832,21 +2589,46 @@ static int __init cfq_init(void) | |||
1832 | { | 2589 | { |
1833 | int ret; | 2590 | int ret; |
1834 | 2591 | ||
2592 | /* | ||
2593 | * could be 0 on HZ < 1000 setups | ||
2594 | */ | ||
2595 | if (!cfq_slice_async) | ||
2596 | cfq_slice_async = 1; | ||
2597 | if (!cfq_slice_idle) | ||
2598 | cfq_slice_idle = 1; | ||
2599 | |||
1835 | if (cfq_slab_setup()) | 2600 | if (cfq_slab_setup()) |
1836 | return -ENOMEM; | 2601 | return -ENOMEM; |
1837 | 2602 | ||
1838 | ret = elv_register(&iosched_cfq); | 2603 | ret = elv_register(&iosched_cfq); |
1839 | if (!ret) { | 2604 | if (ret) |
1840 | __module_get(THIS_MODULE); | 2605 | cfq_slab_kill(); |
1841 | return 0; | ||
1842 | } | ||
1843 | 2606 | ||
1844 | cfq_slab_kill(); | ||
1845 | return ret; | 2607 | return ret; |
1846 | } | 2608 | } |
1847 | 2609 | ||
1848 | static void __exit cfq_exit(void) | 2610 | static void __exit cfq_exit(void) |
1849 | { | 2611 | { |
2612 | struct task_struct *g, *p; | ||
2613 | unsigned long flags; | ||
2614 | |||
2615 | read_lock_irqsave(&tasklist_lock, flags); | ||
2616 | |||
2617 | /* | ||
2618 | * iterate each process in the system, removing our io_context | ||
2619 | */ | ||
2620 | do_each_thread(g, p) { | ||
2621 | struct io_context *ioc = p->io_context; | ||
2622 | |||
2623 | if (ioc && ioc->cic) { | ||
2624 | ioc->cic->exit(ioc->cic); | ||
2625 | cfq_free_io_context(ioc->cic); | ||
2626 | ioc->cic = NULL; | ||
2627 | } | ||
2628 | } while_each_thread(g, p); | ||
2629 | |||
2630 | read_unlock_irqrestore(&tasklist_lock, flags); | ||
2631 | |||
1850 | cfq_slab_kill(); | 2632 | cfq_slab_kill(); |
1851 | elv_unregister(&iosched_cfq); | 2633 | elv_unregister(&iosched_cfq); |
1852 | } | 2634 | } |
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c index 4bc2fea73273..ff5201e02153 100644 --- a/drivers/block/deadline-iosched.c +++ b/drivers/block/deadline-iosched.c | |||
@@ -760,7 +760,8 @@ static void deadline_put_request(request_queue_t *q, struct request *rq) | |||
760 | } | 760 | } |
761 | 761 | ||
762 | static int | 762 | static int |
763 | deadline_set_request(request_queue_t *q, struct request *rq, int gfp_mask) | 763 | deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio, |
764 | int gfp_mask) | ||
764 | { | 765 | { |
765 | struct deadline_data *dd = q->elevator->elevator_data; | 766 | struct deadline_data *dd = q->elevator->elevator_data; |
766 | struct deadline_rq *drq; | 767 | struct deadline_rq *drq; |
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c index f831f08f839c..98f0126a2deb 100644 --- a/drivers/block/elevator.c +++ b/drivers/block/elevator.c | |||
@@ -486,12 +486,13 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq) | |||
486 | return NULL; | 486 | return NULL; |
487 | } | 487 | } |
488 | 488 | ||
489 | int elv_set_request(request_queue_t *q, struct request *rq, int gfp_mask) | 489 | int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio, |
490 | int gfp_mask) | ||
490 | { | 491 | { |
491 | elevator_t *e = q->elevator; | 492 | elevator_t *e = q->elevator; |
492 | 493 | ||
493 | if (e->ops->elevator_set_req_fn) | 494 | if (e->ops->elevator_set_req_fn) |
494 | return e->ops->elevator_set_req_fn(q, rq, gfp_mask); | 495 | return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask); |
495 | 496 | ||
496 | rq->elevator_private = NULL; | 497 | rq->elevator_private = NULL; |
497 | return 0; | 498 | return 0; |
@@ -505,12 +506,12 @@ void elv_put_request(request_queue_t *q, struct request *rq) | |||
505 | e->ops->elevator_put_req_fn(q, rq); | 506 | e->ops->elevator_put_req_fn(q, rq); |
506 | } | 507 | } |
507 | 508 | ||
508 | int elv_may_queue(request_queue_t *q, int rw) | 509 | int elv_may_queue(request_queue_t *q, int rw, struct bio *bio) |
509 | { | 510 | { |
510 | elevator_t *e = q->elevator; | 511 | elevator_t *e = q->elevator; |
511 | 512 | ||
512 | if (e->ops->elevator_may_queue_fn) | 513 | if (e->ops->elevator_may_queue_fn) |
513 | return e->ops->elevator_may_queue_fn(q, rw); | 514 | return e->ops->elevator_may_queue_fn(q, rw, bio); |
514 | 515 | ||
515 | return ELV_MQUEUE_MAY; | 516 | return ELV_MQUEUE_MAY; |
516 | } | 517 | } |
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 60e64091de1b..234fdcfbdf01 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c | |||
@@ -276,6 +276,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq) | |||
276 | rq->errors = 0; | 276 | rq->errors = 0; |
277 | rq->rq_status = RQ_ACTIVE; | 277 | rq->rq_status = RQ_ACTIVE; |
278 | rq->bio = rq->biotail = NULL; | 278 | rq->bio = rq->biotail = NULL; |
279 | rq->ioprio = 0; | ||
279 | rq->buffer = NULL; | 280 | rq->buffer = NULL; |
280 | rq->ref_count = 1; | 281 | rq->ref_count = 1; |
281 | rq->q = q; | 282 | rq->q = q; |
@@ -1442,11 +1443,7 @@ void __generic_unplug_device(request_queue_t *q) | |||
1442 | if (!blk_remove_plug(q)) | 1443 | if (!blk_remove_plug(q)) |
1443 | return; | 1444 | return; |
1444 | 1445 | ||
1445 | /* | 1446 | q->request_fn(q); |
1446 | * was plugged, fire request_fn if queue has stuff to do | ||
1447 | */ | ||
1448 | if (elv_next_request(q)) | ||
1449 | q->request_fn(q); | ||
1450 | } | 1447 | } |
1451 | EXPORT_SYMBOL(__generic_unplug_device); | 1448 | EXPORT_SYMBOL(__generic_unplug_device); |
1452 | 1449 | ||
@@ -1776,8 +1773,8 @@ static inline void blk_free_request(request_queue_t *q, struct request *rq) | |||
1776 | mempool_free(rq, q->rq.rq_pool); | 1773 | mempool_free(rq, q->rq.rq_pool); |
1777 | } | 1774 | } |
1778 | 1775 | ||
1779 | static inline struct request *blk_alloc_request(request_queue_t *q, int rw, | 1776 | static inline struct request * |
1780 | int gfp_mask) | 1777 | blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask) |
1781 | { | 1778 | { |
1782 | struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); | 1779 | struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); |
1783 | 1780 | ||
@@ -1790,7 +1787,7 @@ static inline struct request *blk_alloc_request(request_queue_t *q, int rw, | |||
1790 | */ | 1787 | */ |
1791 | rq->flags = rw; | 1788 | rq->flags = rw; |
1792 | 1789 | ||
1793 | if (!elv_set_request(q, rq, gfp_mask)) | 1790 | if (!elv_set_request(q, rq, bio, gfp_mask)) |
1794 | return rq; | 1791 | return rq; |
1795 | 1792 | ||
1796 | mempool_free(rq, q->rq.rq_pool); | 1793 | mempool_free(rq, q->rq.rq_pool); |
@@ -1872,7 +1869,8 @@ static void freed_request(request_queue_t *q, int rw) | |||
1872 | /* | 1869 | /* |
1873 | * Get a free request, queue_lock must not be held | 1870 | * Get a free request, queue_lock must not be held |
1874 | */ | 1871 | */ |
1875 | static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) | 1872 | static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, |
1873 | int gfp_mask) | ||
1876 | { | 1874 | { |
1877 | struct request *rq = NULL; | 1875 | struct request *rq = NULL; |
1878 | struct request_list *rl = &q->rq; | 1876 | struct request_list *rl = &q->rq; |
@@ -1895,7 +1893,7 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) | |||
1895 | } | 1893 | } |
1896 | } | 1894 | } |
1897 | 1895 | ||
1898 | switch (elv_may_queue(q, rw)) { | 1896 | switch (elv_may_queue(q, rw, bio)) { |
1899 | case ELV_MQUEUE_NO: | 1897 | case ELV_MQUEUE_NO: |
1900 | goto rq_starved; | 1898 | goto rq_starved; |
1901 | case ELV_MQUEUE_MAY: | 1899 | case ELV_MQUEUE_MAY: |
@@ -1920,7 +1918,7 @@ get_rq: | |||
1920 | set_queue_congested(q, rw); | 1918 | set_queue_congested(q, rw); |
1921 | spin_unlock_irq(q->queue_lock); | 1919 | spin_unlock_irq(q->queue_lock); |
1922 | 1920 | ||
1923 | rq = blk_alloc_request(q, rw, gfp_mask); | 1921 | rq = blk_alloc_request(q, rw, bio, gfp_mask); |
1924 | if (!rq) { | 1922 | if (!rq) { |
1925 | /* | 1923 | /* |
1926 | * Allocation failed presumably due to memory. Undo anything | 1924 | * Allocation failed presumably due to memory. Undo anything |
@@ -1961,7 +1959,8 @@ out: | |||
1961 | * No available requests for this queue, unplug the device and wait for some | 1959 | * No available requests for this queue, unplug the device and wait for some |
1962 | * requests to become available. | 1960 | * requests to become available. |
1963 | */ | 1961 | */ |
1964 | static struct request *get_request_wait(request_queue_t *q, int rw) | 1962 | static struct request *get_request_wait(request_queue_t *q, int rw, |
1963 | struct bio *bio) | ||
1965 | { | 1964 | { |
1966 | DEFINE_WAIT(wait); | 1965 | DEFINE_WAIT(wait); |
1967 | struct request *rq; | 1966 | struct request *rq; |
@@ -1972,7 +1971,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw) | |||
1972 | prepare_to_wait_exclusive(&rl->wait[rw], &wait, | 1971 | prepare_to_wait_exclusive(&rl->wait[rw], &wait, |
1973 | TASK_UNINTERRUPTIBLE); | 1972 | TASK_UNINTERRUPTIBLE); |
1974 | 1973 | ||
1975 | rq = get_request(q, rw, GFP_NOIO); | 1974 | rq = get_request(q, rw, bio, GFP_NOIO); |
1976 | 1975 | ||
1977 | if (!rq) { | 1976 | if (!rq) { |
1978 | struct io_context *ioc; | 1977 | struct io_context *ioc; |
@@ -2003,9 +2002,9 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask) | |||
2003 | BUG_ON(rw != READ && rw != WRITE); | 2002 | BUG_ON(rw != READ && rw != WRITE); |
2004 | 2003 | ||
2005 | if (gfp_mask & __GFP_WAIT) | 2004 | if (gfp_mask & __GFP_WAIT) |
2006 | rq = get_request_wait(q, rw); | 2005 | rq = get_request_wait(q, rw, NULL); |
2007 | else | 2006 | else |
2008 | rq = get_request(q, rw, gfp_mask); | 2007 | rq = get_request(q, rw, NULL, gfp_mask); |
2009 | 2008 | ||
2010 | return rq; | 2009 | return rq; |
2011 | } | 2010 | } |
@@ -2333,7 +2332,6 @@ static void __blk_put_request(request_queue_t *q, struct request *req) | |||
2333 | return; | 2332 | return; |
2334 | 2333 | ||
2335 | req->rq_status = RQ_INACTIVE; | 2334 | req->rq_status = RQ_INACTIVE; |
2336 | req->q = NULL; | ||
2337 | req->rl = NULL; | 2335 | req->rl = NULL; |
2338 | 2336 | ||
2339 | /* | 2337 | /* |
@@ -2462,6 +2460,8 @@ static int attempt_merge(request_queue_t *q, struct request *req, | |||
2462 | req->rq_disk->in_flight--; | 2460 | req->rq_disk->in_flight--; |
2463 | } | 2461 | } |
2464 | 2462 | ||
2463 | req->ioprio = ioprio_best(req->ioprio, next->ioprio); | ||
2464 | |||
2465 | __blk_put_request(q, next); | 2465 | __blk_put_request(q, next); |
2466 | return 1; | 2466 | return 1; |
2467 | } | 2467 | } |
@@ -2514,11 +2514,13 @@ static int __make_request(request_queue_t *q, struct bio *bio) | |||
2514 | { | 2514 | { |
2515 | struct request *req, *freereq = NULL; | 2515 | struct request *req, *freereq = NULL; |
2516 | int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync; | 2516 | int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync; |
2517 | unsigned short prio; | ||
2517 | sector_t sector; | 2518 | sector_t sector; |
2518 | 2519 | ||
2519 | sector = bio->bi_sector; | 2520 | sector = bio->bi_sector; |
2520 | nr_sectors = bio_sectors(bio); | 2521 | nr_sectors = bio_sectors(bio); |
2521 | cur_nr_sectors = bio_cur_sectors(bio); | 2522 | cur_nr_sectors = bio_cur_sectors(bio); |
2523 | prio = bio_prio(bio); | ||
2522 | 2524 | ||
2523 | rw = bio_data_dir(bio); | 2525 | rw = bio_data_dir(bio); |
2524 | sync = bio_sync(bio); | 2526 | sync = bio_sync(bio); |
@@ -2559,6 +2561,7 @@ again: | |||
2559 | req->biotail->bi_next = bio; | 2561 | req->biotail->bi_next = bio; |
2560 | req->biotail = bio; | 2562 | req->biotail = bio; |
2561 | req->nr_sectors = req->hard_nr_sectors += nr_sectors; | 2563 | req->nr_sectors = req->hard_nr_sectors += nr_sectors; |
2564 | req->ioprio = ioprio_best(req->ioprio, prio); | ||
2562 | drive_stat_acct(req, nr_sectors, 0); | 2565 | drive_stat_acct(req, nr_sectors, 0); |
2563 | if (!attempt_back_merge(q, req)) | 2566 | if (!attempt_back_merge(q, req)) |
2564 | elv_merged_request(q, req); | 2567 | elv_merged_request(q, req); |
@@ -2583,6 +2586,7 @@ again: | |||
2583 | req->hard_cur_sectors = cur_nr_sectors; | 2586 | req->hard_cur_sectors = cur_nr_sectors; |
2584 | req->sector = req->hard_sector = sector; | 2587 | req->sector = req->hard_sector = sector; |
2585 | req->nr_sectors = req->hard_nr_sectors += nr_sectors; | 2588 | req->nr_sectors = req->hard_nr_sectors += nr_sectors; |
2589 | req->ioprio = ioprio_best(req->ioprio, prio); | ||
2586 | drive_stat_acct(req, nr_sectors, 0); | 2590 | drive_stat_acct(req, nr_sectors, 0); |
2587 | if (!attempt_front_merge(q, req)) | 2591 | if (!attempt_front_merge(q, req)) |
2588 | elv_merged_request(q, req); | 2592 | elv_merged_request(q, req); |
@@ -2610,7 +2614,7 @@ get_rq: | |||
2610 | freereq = NULL; | 2614 | freereq = NULL; |
2611 | } else { | 2615 | } else { |
2612 | spin_unlock_irq(q->queue_lock); | 2616 | spin_unlock_irq(q->queue_lock); |
2613 | if ((freereq = get_request(q, rw, GFP_ATOMIC)) == NULL) { | 2617 | if ((freereq = get_request(q, rw, bio, GFP_ATOMIC)) == NULL) { |
2614 | /* | 2618 | /* |
2615 | * READA bit set | 2619 | * READA bit set |
2616 | */ | 2620 | */ |
@@ -2618,7 +2622,7 @@ get_rq: | |||
2618 | if (bio_rw_ahead(bio)) | 2622 | if (bio_rw_ahead(bio)) |
2619 | goto end_io; | 2623 | goto end_io; |
2620 | 2624 | ||
2621 | freereq = get_request_wait(q, rw); | 2625 | freereq = get_request_wait(q, rw, bio); |
2622 | } | 2626 | } |
2623 | goto again; | 2627 | goto again; |
2624 | } | 2628 | } |
@@ -2646,6 +2650,7 @@ get_rq: | |||
2646 | req->buffer = bio_data(bio); /* see ->buffer comment above */ | 2650 | req->buffer = bio_data(bio); /* see ->buffer comment above */ |
2647 | req->waiting = NULL; | 2651 | req->waiting = NULL; |
2648 | req->bio = req->biotail = bio; | 2652 | req->bio = req->biotail = bio; |
2653 | req->ioprio = prio; | ||
2649 | req->rq_disk = bio->bi_bdev->bd_disk; | 2654 | req->rq_disk = bio->bi_bdev->bd_disk; |
2650 | req->start_time = jiffies; | 2655 | req->start_time = jiffies; |
2651 | 2656 | ||
@@ -2674,7 +2679,7 @@ static inline void blk_partition_remap(struct bio *bio) | |||
2674 | if (bdev != bdev->bd_contains) { | 2679 | if (bdev != bdev->bd_contains) { |
2675 | struct hd_struct *p = bdev->bd_part; | 2680 | struct hd_struct *p = bdev->bd_part; |
2676 | 2681 | ||
2677 | switch (bio->bi_rw) { | 2682 | switch (bio_data_dir(bio)) { |
2678 | case READ: | 2683 | case READ: |
2679 | p->read_sectors += bio_sectors(bio); | 2684 | p->read_sectors += bio_sectors(bio); |
2680 | p->reads++; | 2685 | p->reads++; |
@@ -2693,6 +2698,7 @@ void blk_finish_queue_drain(request_queue_t *q) | |||
2693 | { | 2698 | { |
2694 | struct request_list *rl = &q->rq; | 2699 | struct request_list *rl = &q->rq; |
2695 | struct request *rq; | 2700 | struct request *rq; |
2701 | int requeued = 0; | ||
2696 | 2702 | ||
2697 | spin_lock_irq(q->queue_lock); | 2703 | spin_lock_irq(q->queue_lock); |
2698 | clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags); | 2704 | clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags); |
@@ -2701,9 +2707,13 @@ void blk_finish_queue_drain(request_queue_t *q) | |||
2701 | rq = list_entry_rq(q->drain_list.next); | 2707 | rq = list_entry_rq(q->drain_list.next); |
2702 | 2708 | ||
2703 | list_del_init(&rq->queuelist); | 2709 | list_del_init(&rq->queuelist); |
2704 | __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); | 2710 | elv_requeue_request(q, rq); |
2711 | requeued++; | ||
2705 | } | 2712 | } |
2706 | 2713 | ||
2714 | if (requeued) | ||
2715 | q->request_fn(q); | ||
2716 | |||
2707 | spin_unlock_irq(q->queue_lock); | 2717 | spin_unlock_irq(q->queue_lock); |
2708 | 2718 | ||
2709 | wake_up(&rl->wait[0]); | 2719 | wake_up(&rl->wait[0]); |
@@ -2900,7 +2910,7 @@ void submit_bio(int rw, struct bio *bio) | |||
2900 | 2910 | ||
2901 | BIO_BUG_ON(!bio->bi_size); | 2911 | BIO_BUG_ON(!bio->bi_size); |
2902 | BIO_BUG_ON(!bio->bi_io_vec); | 2912 | BIO_BUG_ON(!bio->bi_io_vec); |
2903 | bio->bi_rw = rw; | 2913 | bio->bi_rw |= rw; |
2904 | if (rw & WRITE) | 2914 | if (rw & WRITE) |
2905 | mod_page_state(pgpgout, count); | 2915 | mod_page_state(pgpgout, count); |
2906 | else | 2916 | else |
@@ -3257,8 +3267,11 @@ void exit_io_context(void) | |||
3257 | struct io_context *ioc; | 3267 | struct io_context *ioc; |
3258 | 3268 | ||
3259 | local_irq_save(flags); | 3269 | local_irq_save(flags); |
3270 | task_lock(current); | ||
3260 | ioc = current->io_context; | 3271 | ioc = current->io_context; |
3261 | current->io_context = NULL; | 3272 | current->io_context = NULL; |
3273 | ioc->task = NULL; | ||
3274 | task_unlock(current); | ||
3262 | local_irq_restore(flags); | 3275 | local_irq_restore(flags); |
3263 | 3276 | ||
3264 | if (ioc->aic && ioc->aic->exit) | 3277 | if (ioc->aic && ioc->aic->exit) |
@@ -3293,12 +3306,12 @@ struct io_context *get_io_context(int gfp_flags) | |||
3293 | ret = kmem_cache_alloc(iocontext_cachep, gfp_flags); | 3306 | ret = kmem_cache_alloc(iocontext_cachep, gfp_flags); |
3294 | if (ret) { | 3307 | if (ret) { |
3295 | atomic_set(&ret->refcount, 1); | 3308 | atomic_set(&ret->refcount, 1); |
3296 | ret->pid = tsk->pid; | 3309 | ret->task = current; |
3310 | ret->set_ioprio = NULL; | ||
3297 | ret->last_waited = jiffies; /* doesn't matter... */ | 3311 | ret->last_waited = jiffies; /* doesn't matter... */ |
3298 | ret->nr_batch_requests = 0; /* because this is 0 */ | 3312 | ret->nr_batch_requests = 0; /* because this is 0 */ |
3299 | ret->aic = NULL; | 3313 | ret->aic = NULL; |
3300 | ret->cic = NULL; | 3314 | ret->cic = NULL; |
3301 | spin_lock_init(&ret->lock); | ||
3302 | 3315 | ||
3303 | local_irq_save(flags); | 3316 | local_irq_save(flags); |
3304 | 3317 | ||
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 5b09cf154ac7..e5f7494c00ee 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c | |||
@@ -253,7 +253,7 @@ static int floppy_revalidate(struct gendisk *disk); | |||
253 | static int swim3_add_device(struct device_node *swims); | 253 | static int swim3_add_device(struct device_node *swims); |
254 | int swim3_init(void); | 254 | int swim3_init(void); |
255 | 255 | ||
256 | #ifndef CONFIG_PMAC_PBOOK | 256 | #ifndef CONFIG_PMAC_MEDIABAY |
257 | #define check_media_bay(which, what) 1 | 257 | #define check_media_bay(which, what) 1 |
258 | #endif | 258 | #endif |
259 | 259 | ||
@@ -297,9 +297,11 @@ static void do_fd_request(request_queue_t * q) | |||
297 | int i; | 297 | int i; |
298 | for(i=0;i<floppy_count;i++) | 298 | for(i=0;i<floppy_count;i++) |
299 | { | 299 | { |
300 | #ifdef CONFIG_PMAC_MEDIABAY | ||
300 | if (floppy_states[i].media_bay && | 301 | if (floppy_states[i].media_bay && |
301 | check_media_bay(floppy_states[i].media_bay, MB_FD)) | 302 | check_media_bay(floppy_states[i].media_bay, MB_FD)) |
302 | continue; | 303 | continue; |
304 | #endif /* CONFIG_PMAC_MEDIABAY */ | ||
303 | start_request(&floppy_states[i]); | 305 | start_request(&floppy_states[i]); |
304 | } | 306 | } |
305 | sti(); | 307 | sti(); |
@@ -856,8 +858,10 @@ static int floppy_ioctl(struct inode *inode, struct file *filp, | |||
856 | if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)) | 858 | if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)) |
857 | return -EPERM; | 859 | return -EPERM; |
858 | 860 | ||
861 | #ifdef CONFIG_PMAC_MEDIABAY | ||
859 | if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) | 862 | if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) |
860 | return -ENXIO; | 863 | return -ENXIO; |
864 | #endif | ||
861 | 865 | ||
862 | switch (cmd) { | 866 | switch (cmd) { |
863 | case FDEJECT: | 867 | case FDEJECT: |
@@ -881,8 +885,10 @@ static int floppy_open(struct inode *inode, struct file *filp) | |||
881 | int n, err = 0; | 885 | int n, err = 0; |
882 | 886 | ||
883 | if (fs->ref_count == 0) { | 887 | if (fs->ref_count == 0) { |
888 | #ifdef CONFIG_PMAC_MEDIABAY | ||
884 | if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) | 889 | if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) |
885 | return -ENXIO; | 890 | return -ENXIO; |
891 | #endif | ||
886 | out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2); | 892 | out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2); |
887 | out_8(&sw->control_bic, 0xff); | 893 | out_8(&sw->control_bic, 0xff); |
888 | out_8(&sw->mode, 0x95); | 894 | out_8(&sw->mode, 0x95); |
@@ -967,8 +973,10 @@ static int floppy_revalidate(struct gendisk *disk) | |||
967 | struct swim3 __iomem *sw; | 973 | struct swim3 __iomem *sw; |
968 | int ret, n; | 974 | int ret, n; |
969 | 975 | ||
976 | #ifdef CONFIG_PMAC_MEDIABAY | ||
970 | if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) | 977 | if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) |
971 | return -ENXIO; | 978 | return -ENXIO; |
979 | #endif | ||
972 | 980 | ||
973 | sw = fs->swim3; | 981 | sw = fs->swim3; |
974 | grab_drive(fs, revalidating, 0); | 982 | grab_drive(fs, revalidating, 0); |
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index 5ed3a6379452..9db0a9e3e59c 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/time.h> | 27 | #include <linux/time.h> |
28 | #include <linux/hdreg.h> | 28 | #include <linux/hdreg.h> |
29 | #include <linux/dma-mapping.h> | ||
29 | #include <asm/io.h> | 30 | #include <asm/io.h> |
30 | #include <asm/semaphore.h> | 31 | #include <asm/semaphore.h> |
31 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
@@ -1582,9 +1583,9 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1582 | goto err_out; | 1583 | goto err_out; |
1583 | 1584 | ||
1584 | #if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */ | 1585 | #if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */ |
1585 | rc = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); | 1586 | rc = pci_set_dma_mask(pdev, DMA_64BIT_MASK); |
1586 | if (!rc) { | 1587 | if (!rc) { |
1587 | rc = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); | 1588 | rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); |
1588 | if (rc) { | 1589 | if (rc) { |
1589 | printk(KERN_ERR DRV_NAME "(%s): consistent DMA mask failure\n", | 1590 | printk(KERN_ERR DRV_NAME "(%s): consistent DMA mask failure\n", |
1590 | pci_name(pdev)); | 1591 | pci_name(pdev)); |
@@ -1593,7 +1594,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1593 | pci_dac = 1; | 1594 | pci_dac = 1; |
1594 | } else { | 1595 | } else { |
1595 | #endif | 1596 | #endif |
1596 | rc = pci_set_dma_mask(pdev, 0xffffffffULL); | 1597 | rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
1597 | if (rc) { | 1598 | if (rc) { |
1598 | printk(KERN_ERR DRV_NAME "(%s): DMA mask failure\n", | 1599 | printk(KERN_ERR DRV_NAME "(%s): DMA mask failure\n", |
1599 | pci_name(pdev)); | 1600 | pci_name(pdev)); |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 31cf84d69026..931efd58f87a 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
@@ -309,9 +309,6 @@ static int __init misc_init(void) | |||
309 | #ifdef CONFIG_BVME6000 | 309 | #ifdef CONFIG_BVME6000 |
310 | rtc_DP8570A_init(); | 310 | rtc_DP8570A_init(); |
311 | #endif | 311 | #endif |
312 | #ifdef CONFIG_PMAC_PBOOK | ||
313 | pmu_device_init(); | ||
314 | #endif | ||
315 | if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { | 312 | if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { |
316 | printk("unable to get major %d for misc devices\n", | 313 | printk("unable to get major %d for misc devices\n", |
317 | MISC_MAJOR); | 314 | MISC_MAJOR); |
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 569f16767442..818380b5fd27 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c | |||
@@ -1324,9 +1324,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) | |||
1324 | /* XXX FIXME: Media bay stuff need re-organizing */ | 1324 | /* XXX FIXME: Media bay stuff need re-organizing */ |
1325 | if (np->parent && np->parent->name | 1325 | if (np->parent && np->parent->name |
1326 | && strcasecmp(np->parent->name, "media-bay") == 0) { | 1326 | && strcasecmp(np->parent->name, "media-bay") == 0) { |
1327 | #ifdef CONFIG_PMAC_PBOOK | 1327 | #ifdef CONFIG_PMAC_MEDIABAY |
1328 | media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index); | 1328 | media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index); |
1329 | #endif /* CONFIG_PMAC_PBOOK */ | 1329 | #endif /* CONFIG_PMAC_MEDIABAY */ |
1330 | pmif->mediabay = 1; | 1330 | pmif->mediabay = 1; |
1331 | if (!bidp) | 1331 | if (!bidp) |
1332 | pmif->aapl_bus_id = 1; | 1332 | pmif->aapl_bus_id = 1; |
@@ -1382,10 +1382,10 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) | |||
1382 | hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, | 1382 | hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, |
1383 | pmif->mediabay ? " (mediabay)" : "", hwif->irq); | 1383 | pmif->mediabay ? " (mediabay)" : "", hwif->irq); |
1384 | 1384 | ||
1385 | #ifdef CONFIG_PMAC_PBOOK | 1385 | #ifdef CONFIG_PMAC_MEDIABAY |
1386 | if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0) | 1386 | if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0) |
1387 | hwif->noprobe = 0; | 1387 | hwif->noprobe = 0; |
1388 | #endif /* CONFIG_PMAC_PBOOK */ | 1388 | #endif /* CONFIG_PMAC_MEDIABAY */ |
1389 | 1389 | ||
1390 | hwif->sg_max_nents = MAX_DCMDS; | 1390 | hwif->sg_max_nents = MAX_DCMDS; |
1391 | 1391 | ||
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 36e25ac823dc..b3d3d22fde64 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c | |||
@@ -3538,8 +3538,8 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) | |||
3538 | 3538 | ||
3539 | static int ohci1394_pci_resume (struct pci_dev *pdev) | 3539 | static int ohci1394_pci_resume (struct pci_dev *pdev) |
3540 | { | 3540 | { |
3541 | #ifdef CONFIG_PMAC_PBOOK | 3541 | #ifdef CONFIG_PPC_PMAC |
3542 | { | 3542 | if (_machine == _MACH_Pmac) { |
3543 | struct device_node *of_node; | 3543 | struct device_node *of_node; |
3544 | 3544 | ||
3545 | /* Re-enable 1394 */ | 3545 | /* Re-enable 1394 */ |
@@ -3547,7 +3547,7 @@ static int ohci1394_pci_resume (struct pci_dev *pdev) | |||
3547 | if (of_node) | 3547 | if (of_node) |
3548 | pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1); | 3548 | pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1); |
3549 | } | 3549 | } |
3550 | #endif | 3550 | #endif /* CONFIG_PPC_PMAC */ |
3551 | 3551 | ||
3552 | pci_enable_device(pdev); | 3552 | pci_enable_device(pdev); |
3553 | 3553 | ||
@@ -3557,8 +3557,8 @@ static int ohci1394_pci_resume (struct pci_dev *pdev) | |||
3557 | 3557 | ||
3558 | static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) | 3558 | static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) |
3559 | { | 3559 | { |
3560 | #ifdef CONFIG_PMAC_PBOOK | 3560 | #ifdef CONFIG_PPC_PMAC |
3561 | { | 3561 | if (_machine == _MACH_Pmac) { |
3562 | struct device_node *of_node; | 3562 | struct device_node *of_node; |
3563 | 3563 | ||
3564 | /* Disable 1394 */ | 3564 | /* Disable 1394 */ |
diff --git a/drivers/infiniband/core/packer.c b/drivers/infiniband/core/packer.c index 5f15feffeae2..eb5ff54c10d7 100644 --- a/drivers/infiniband/core/packer.c +++ b/drivers/infiniband/core/packer.c | |||
@@ -96,7 +96,7 @@ void ib_pack(const struct ib_field *desc, | |||
96 | else | 96 | else |
97 | val = 0; | 97 | val = 0; |
98 | 98 | ||
99 | mask = cpu_to_be64(((1ull << desc[i].size_bits) - 1) << shift); | 99 | mask = cpu_to_be64((~0ull >> (64 - desc[i].size_bits)) << shift); |
100 | addr = (__be64 *) ((__be32 *) buf + desc[i].offset_words); | 100 | addr = (__be64 *) ((__be32 *) buf + desc[i].offset_words); |
101 | *addr = (*addr & ~mask) | (cpu_to_be64(val) & mask); | 101 | *addr = (*addr & ~mask) | (cpu_to_be64(val) & mask); |
102 | } else { | 102 | } else { |
@@ -176,7 +176,7 @@ void ib_unpack(const struct ib_field *desc, | |||
176 | __be64 *addr; | 176 | __be64 *addr; |
177 | 177 | ||
178 | shift = 64 - desc[i].offset_bits - desc[i].size_bits; | 178 | shift = 64 - desc[i].offset_bits - desc[i].size_bits; |
179 | mask = ((1ull << desc[i].size_bits) - 1) << shift; | 179 | mask = (~0ull >> (64 - desc[i].size_bits)) << shift; |
180 | addr = (__be64 *) buf + desc[i].offset_words; | 180 | addr = (__be64 *) buf + desc[i].offset_words; |
181 | val = (be64_to_cpup(addr) & mask) >> shift; | 181 | val = (be64_to_cpup(addr) & mask) >> shift; |
182 | value_write(desc[i].struct_offset_bytes, | 182 | value_write(desc[i].struct_offset_bytes, |
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 276e1a53010d..5a08e81fa827 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
@@ -507,7 +507,13 @@ retry: | |||
507 | spin_unlock_irqrestore(&idr_lock, flags); | 507 | spin_unlock_irqrestore(&idr_lock, flags); |
508 | } | 508 | } |
509 | 509 | ||
510 | return ret; | 510 | /* |
511 | * It's not safe to dereference query any more, because the | ||
512 | * send may already have completed and freed the query in | ||
513 | * another context. So use wr.wr_id, which has a copy of the | ||
514 | * query's id. | ||
515 | */ | ||
516 | return ret ? ret : wr.wr_id; | ||
511 | } | 517 | } |
512 | 518 | ||
513 | static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, | 519 | static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, |
@@ -598,14 +604,15 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num, | |||
598 | rec, query->sa_query.mad->data); | 604 | rec, query->sa_query.mad->data); |
599 | 605 | ||
600 | *sa_query = &query->sa_query; | 606 | *sa_query = &query->sa_query; |
607 | |||
601 | ret = send_mad(&query->sa_query, timeout_ms); | 608 | ret = send_mad(&query->sa_query, timeout_ms); |
602 | if (ret) { | 609 | if (ret < 0) { |
603 | *sa_query = NULL; | 610 | *sa_query = NULL; |
604 | kfree(query->sa_query.mad); | 611 | kfree(query->sa_query.mad); |
605 | kfree(query); | 612 | kfree(query); |
606 | } | 613 | } |
607 | 614 | ||
608 | return ret ? ret : query->sa_query.id; | 615 | return ret; |
609 | } | 616 | } |
610 | EXPORT_SYMBOL(ib_sa_path_rec_get); | 617 | EXPORT_SYMBOL(ib_sa_path_rec_get); |
611 | 618 | ||
@@ -674,14 +681,15 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num, | |||
674 | rec, query->sa_query.mad->data); | 681 | rec, query->sa_query.mad->data); |
675 | 682 | ||
676 | *sa_query = &query->sa_query; | 683 | *sa_query = &query->sa_query; |
684 | |||
677 | ret = send_mad(&query->sa_query, timeout_ms); | 685 | ret = send_mad(&query->sa_query, timeout_ms); |
678 | if (ret) { | 686 | if (ret < 0) { |
679 | *sa_query = NULL; | 687 | *sa_query = NULL; |
680 | kfree(query->sa_query.mad); | 688 | kfree(query->sa_query.mad); |
681 | kfree(query); | 689 | kfree(query); |
682 | } | 690 | } |
683 | 691 | ||
684 | return ret ? ret : query->sa_query.id; | 692 | return ret; |
685 | } | 693 | } |
686 | EXPORT_SYMBOL(ib_sa_mcmember_rec_query); | 694 | EXPORT_SYMBOL(ib_sa_mcmember_rec_query); |
687 | 695 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 085baf393ca4..d58dcbe66488 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 Topspin Communications. All rights reserved. | 2 | * Copyright (c) 2004 Topspin Communications. All rights reserved. |
3 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index cd9ed958d92f..1557a522d831 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -431,6 +431,36 @@ static int mthca_cmd_imm(struct mthca_dev *dev, | |||
431 | timeout, status); | 431 | timeout, status); |
432 | } | 432 | } |
433 | 433 | ||
434 | int mthca_cmd_init(struct mthca_dev *dev) | ||
435 | { | ||
436 | sema_init(&dev->cmd.hcr_sem, 1); | ||
437 | sema_init(&dev->cmd.poll_sem, 1); | ||
438 | dev->cmd.use_events = 0; | ||
439 | |||
440 | dev->hcr = ioremap(pci_resource_start(dev->pdev, 0) + MTHCA_HCR_BASE, | ||
441 | MTHCA_HCR_SIZE); | ||
442 | if (!dev->hcr) { | ||
443 | mthca_err(dev, "Couldn't map command register."); | ||
444 | return -ENOMEM; | ||
445 | } | ||
446 | |||
447 | dev->cmd.pool = pci_pool_create("mthca_cmd", dev->pdev, | ||
448 | MTHCA_MAILBOX_SIZE, | ||
449 | MTHCA_MAILBOX_SIZE, 0); | ||
450 | if (!dev->cmd.pool) { | ||
451 | iounmap(dev->hcr); | ||
452 | return -ENOMEM; | ||
453 | } | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | void mthca_cmd_cleanup(struct mthca_dev *dev) | ||
459 | { | ||
460 | pci_pool_destroy(dev->cmd.pool); | ||
461 | iounmap(dev->hcr); | ||
462 | } | ||
463 | |||
434 | /* | 464 | /* |
435 | * Switch to using events to issue FW commands (should be called after | 465 | * Switch to using events to issue FW commands (should be called after |
436 | * event queue to command events has been initialized). | 466 | * event queue to command events has been initialized). |
@@ -489,6 +519,33 @@ void mthca_cmd_use_polling(struct mthca_dev *dev) | |||
489 | up(&dev->cmd.poll_sem); | 519 | up(&dev->cmd.poll_sem); |
490 | } | 520 | } |
491 | 521 | ||
522 | struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev, | ||
523 | unsigned int gfp_mask) | ||
524 | { | ||
525 | struct mthca_mailbox *mailbox; | ||
526 | |||
527 | mailbox = kmalloc(sizeof *mailbox, gfp_mask); | ||
528 | if (!mailbox) | ||
529 | return ERR_PTR(-ENOMEM); | ||
530 | |||
531 | mailbox->buf = pci_pool_alloc(dev->cmd.pool, gfp_mask, &mailbox->dma); | ||
532 | if (!mailbox->buf) { | ||
533 | kfree(mailbox); | ||
534 | return ERR_PTR(-ENOMEM); | ||
535 | } | ||
536 | |||
537 | return mailbox; | ||
538 | } | ||
539 | |||
540 | void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox) | ||
541 | { | ||
542 | if (!mailbox) | ||
543 | return; | ||
544 | |||
545 | pci_pool_free(dev->cmd.pool, mailbox->buf, mailbox->dma); | ||
546 | kfree(mailbox); | ||
547 | } | ||
548 | |||
492 | int mthca_SYS_EN(struct mthca_dev *dev, u8 *status) | 549 | int mthca_SYS_EN(struct mthca_dev *dev, u8 *status) |
493 | { | 550 | { |
494 | u64 out; | 551 | u64 out; |
@@ -513,20 +570,20 @@ int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status) | |||
513 | static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, | 570 | static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, |
514 | u64 virt, u8 *status) | 571 | u64 virt, u8 *status) |
515 | { | 572 | { |
516 | u32 *inbox; | 573 | struct mthca_mailbox *mailbox; |
517 | dma_addr_t indma; | ||
518 | struct mthca_icm_iter iter; | 574 | struct mthca_icm_iter iter; |
575 | __be64 *pages; | ||
519 | int lg; | 576 | int lg; |
520 | int nent = 0; | 577 | int nent = 0; |
521 | int i; | 578 | int i; |
522 | int err = 0; | 579 | int err = 0; |
523 | int ts = 0, tc = 0; | 580 | int ts = 0, tc = 0; |
524 | 581 | ||
525 | inbox = pci_alloc_consistent(dev->pdev, PAGE_SIZE, &indma); | 582 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
526 | if (!inbox) | 583 | if (IS_ERR(mailbox)) |
527 | return -ENOMEM; | 584 | return PTR_ERR(mailbox); |
528 | 585 | memset(mailbox->buf, 0, MTHCA_MAILBOX_SIZE); | |
529 | memset(inbox, 0, PAGE_SIZE); | 586 | pages = mailbox->buf; |
530 | 587 | ||
531 | for (mthca_icm_first(icm, &iter); | 588 | for (mthca_icm_first(icm, &iter); |
532 | !mthca_icm_last(&iter); | 589 | !mthca_icm_last(&iter); |
@@ -546,19 +603,17 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, | |||
546 | } | 603 | } |
547 | for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i, ++nent) { | 604 | for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i, ++nent) { |
548 | if (virt != -1) { | 605 | if (virt != -1) { |
549 | *((__be64 *) (inbox + nent * 4)) = | 606 | pages[nent * 2] = cpu_to_be64(virt); |
550 | cpu_to_be64(virt); | ||
551 | virt += 1 << lg; | 607 | virt += 1 << lg; |
552 | } | 608 | } |
553 | 609 | ||
554 | *((__be64 *) (inbox + nent * 4 + 2)) = | 610 | pages[nent * 2 + 1] = cpu_to_be64((mthca_icm_addr(&iter) + |
555 | cpu_to_be64((mthca_icm_addr(&iter) + | 611 | (i << lg)) | (lg - 12)); |
556 | (i << lg)) | (lg - 12)); | ||
557 | ts += 1 << (lg - 10); | 612 | ts += 1 << (lg - 10); |
558 | ++tc; | 613 | ++tc; |
559 | 614 | ||
560 | if (nent == PAGE_SIZE / 16) { | 615 | if (nent == MTHCA_MAILBOX_SIZE / 16) { |
561 | err = mthca_cmd(dev, indma, nent, 0, op, | 616 | err = mthca_cmd(dev, mailbox->dma, nent, 0, op, |
562 | CMD_TIME_CLASS_B, status); | 617 | CMD_TIME_CLASS_B, status); |
563 | if (err || *status) | 618 | if (err || *status) |
564 | goto out; | 619 | goto out; |
@@ -568,7 +623,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, | |||
568 | } | 623 | } |
569 | 624 | ||
570 | if (nent) | 625 | if (nent) |
571 | err = mthca_cmd(dev, indma, nent, 0, op, | 626 | err = mthca_cmd(dev, mailbox->dma, nent, 0, op, |
572 | CMD_TIME_CLASS_B, status); | 627 | CMD_TIME_CLASS_B, status); |
573 | 628 | ||
574 | switch (op) { | 629 | switch (op) { |
@@ -585,7 +640,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, | |||
585 | } | 640 | } |
586 | 641 | ||
587 | out: | 642 | out: |
588 | pci_free_consistent(dev->pdev, PAGE_SIZE, inbox, indma); | 643 | mthca_free_mailbox(dev, mailbox); |
589 | return err; | 644 | return err; |
590 | } | 645 | } |
591 | 646 | ||
@@ -606,8 +661,8 @@ int mthca_RUN_FW(struct mthca_dev *dev, u8 *status) | |||
606 | 661 | ||
607 | int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) | 662 | int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) |
608 | { | 663 | { |
664 | struct mthca_mailbox *mailbox; | ||
609 | u32 *outbox; | 665 | u32 *outbox; |
610 | dma_addr_t outdma; | ||
611 | int err = 0; | 666 | int err = 0; |
612 | u8 lg; | 667 | u8 lg; |
613 | 668 | ||
@@ -625,12 +680,12 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) | |||
625 | #define QUERY_FW_EQ_ARM_BASE_OFFSET 0x40 | 680 | #define QUERY_FW_EQ_ARM_BASE_OFFSET 0x40 |
626 | #define QUERY_FW_EQ_SET_CI_BASE_OFFSET 0x48 | 681 | #define QUERY_FW_EQ_SET_CI_BASE_OFFSET 0x48 |
627 | 682 | ||
628 | outbox = pci_alloc_consistent(dev->pdev, QUERY_FW_OUT_SIZE, &outdma); | 683 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
629 | if (!outbox) { | 684 | if (IS_ERR(mailbox)) |
630 | return -ENOMEM; | 685 | return PTR_ERR(mailbox); |
631 | } | 686 | outbox = mailbox->buf; |
632 | 687 | ||
633 | err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_QUERY_FW, | 688 | err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_FW, |
634 | CMD_TIME_CLASS_A, status); | 689 | CMD_TIME_CLASS_A, status); |
635 | 690 | ||
636 | if (err) | 691 | if (err) |
@@ -681,15 +736,15 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) | |||
681 | } | 736 | } |
682 | 737 | ||
683 | out: | 738 | out: |
684 | pci_free_consistent(dev->pdev, QUERY_FW_OUT_SIZE, outbox, outdma); | 739 | mthca_free_mailbox(dev, mailbox); |
685 | return err; | 740 | return err; |
686 | } | 741 | } |
687 | 742 | ||
688 | int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status) | 743 | int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status) |
689 | { | 744 | { |
745 | struct mthca_mailbox *mailbox; | ||
690 | u8 info; | 746 | u8 info; |
691 | u32 *outbox; | 747 | u32 *outbox; |
692 | dma_addr_t outdma; | ||
693 | int err = 0; | 748 | int err = 0; |
694 | 749 | ||
695 | #define ENABLE_LAM_OUT_SIZE 0x100 | 750 | #define ENABLE_LAM_OUT_SIZE 0x100 |
@@ -700,11 +755,12 @@ int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status) | |||
700 | #define ENABLE_LAM_INFO_HIDDEN_FLAG (1 << 4) | 755 | #define ENABLE_LAM_INFO_HIDDEN_FLAG (1 << 4) |
701 | #define ENABLE_LAM_INFO_ECC_MASK 0x3 | 756 | #define ENABLE_LAM_INFO_ECC_MASK 0x3 |
702 | 757 | ||
703 | outbox = pci_alloc_consistent(dev->pdev, ENABLE_LAM_OUT_SIZE, &outdma); | 758 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
704 | if (!outbox) | 759 | if (IS_ERR(mailbox)) |
705 | return -ENOMEM; | 760 | return PTR_ERR(mailbox); |
761 | outbox = mailbox->buf; | ||
706 | 762 | ||
707 | err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_ENABLE_LAM, | 763 | err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_ENABLE_LAM, |
708 | CMD_TIME_CLASS_C, status); | 764 | CMD_TIME_CLASS_C, status); |
709 | 765 | ||
710 | if (err) | 766 | if (err) |
@@ -733,7 +789,7 @@ int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status) | |||
733 | (unsigned long long) dev->ddr_end); | 789 | (unsigned long long) dev->ddr_end); |
734 | 790 | ||
735 | out: | 791 | out: |
736 | pci_free_consistent(dev->pdev, ENABLE_LAM_OUT_SIZE, outbox, outdma); | 792 | mthca_free_mailbox(dev, mailbox); |
737 | return err; | 793 | return err; |
738 | } | 794 | } |
739 | 795 | ||
@@ -744,9 +800,9 @@ int mthca_DISABLE_LAM(struct mthca_dev *dev, u8 *status) | |||
744 | 800 | ||
745 | int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status) | 801 | int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status) |
746 | { | 802 | { |
803 | struct mthca_mailbox *mailbox; | ||
747 | u8 info; | 804 | u8 info; |
748 | u32 *outbox; | 805 | u32 *outbox; |
749 | dma_addr_t outdma; | ||
750 | int err = 0; | 806 | int err = 0; |
751 | 807 | ||
752 | #define QUERY_DDR_OUT_SIZE 0x100 | 808 | #define QUERY_DDR_OUT_SIZE 0x100 |
@@ -757,11 +813,12 @@ int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status) | |||
757 | #define QUERY_DDR_INFO_HIDDEN_FLAG (1 << 4) | 813 | #define QUERY_DDR_INFO_HIDDEN_FLAG (1 << 4) |
758 | #define QUERY_DDR_INFO_ECC_MASK 0x3 | 814 | #define QUERY_DDR_INFO_ECC_MASK 0x3 |
759 | 815 | ||
760 | outbox = pci_alloc_consistent(dev->pdev, QUERY_DDR_OUT_SIZE, &outdma); | 816 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
761 | if (!outbox) | 817 | if (IS_ERR(mailbox)) |
762 | return -ENOMEM; | 818 | return PTR_ERR(mailbox); |
819 | outbox = mailbox->buf; | ||
763 | 820 | ||
764 | err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_QUERY_DDR, | 821 | err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DDR, |
765 | CMD_TIME_CLASS_A, status); | 822 | CMD_TIME_CLASS_A, status); |
766 | 823 | ||
767 | if (err) | 824 | if (err) |
@@ -787,15 +844,15 @@ int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status) | |||
787 | (unsigned long long) dev->ddr_end); | 844 | (unsigned long long) dev->ddr_end); |
788 | 845 | ||
789 | out: | 846 | out: |
790 | pci_free_consistent(dev->pdev, QUERY_DDR_OUT_SIZE, outbox, outdma); | 847 | mthca_free_mailbox(dev, mailbox); |
791 | return err; | 848 | return err; |
792 | } | 849 | } |
793 | 850 | ||
794 | int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, | 851 | int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, |
795 | struct mthca_dev_lim *dev_lim, u8 *status) | 852 | struct mthca_dev_lim *dev_lim, u8 *status) |
796 | { | 853 | { |
854 | struct mthca_mailbox *mailbox; | ||
797 | u32 *outbox; | 855 | u32 *outbox; |
798 | dma_addr_t outdma; | ||
799 | u8 field; | 856 | u8 field; |
800 | u16 size; | 857 | u16 size; |
801 | int err; | 858 | int err; |
@@ -860,11 +917,12 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, | |||
860 | #define QUERY_DEV_LIM_LAMR_OFFSET 0x9f | 917 | #define QUERY_DEV_LIM_LAMR_OFFSET 0x9f |
861 | #define QUERY_DEV_LIM_MAX_ICM_SZ_OFFSET 0xa0 | 918 | #define QUERY_DEV_LIM_MAX_ICM_SZ_OFFSET 0xa0 |
862 | 919 | ||
863 | outbox = pci_alloc_consistent(dev->pdev, QUERY_DEV_LIM_OUT_SIZE, &outdma); | 920 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
864 | if (!outbox) | 921 | if (IS_ERR(mailbox)) |
865 | return -ENOMEM; | 922 | return PTR_ERR(mailbox); |
923 | outbox = mailbox->buf; | ||
866 | 924 | ||
867 | err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_QUERY_DEV_LIM, | 925 | err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DEV_LIM, |
868 | CMD_TIME_CLASS_A, status); | 926 | CMD_TIME_CLASS_A, status); |
869 | 927 | ||
870 | if (err) | 928 | if (err) |
@@ -1020,15 +1078,15 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, | |||
1020 | } | 1078 | } |
1021 | 1079 | ||
1022 | out: | 1080 | out: |
1023 | pci_free_consistent(dev->pdev, QUERY_DEV_LIM_OUT_SIZE, outbox, outdma); | 1081 | mthca_free_mailbox(dev, mailbox); |
1024 | return err; | 1082 | return err; |
1025 | } | 1083 | } |
1026 | 1084 | ||
1027 | int mthca_QUERY_ADAPTER(struct mthca_dev *dev, | 1085 | int mthca_QUERY_ADAPTER(struct mthca_dev *dev, |
1028 | struct mthca_adapter *adapter, u8 *status) | 1086 | struct mthca_adapter *adapter, u8 *status) |
1029 | { | 1087 | { |
1088 | struct mthca_mailbox *mailbox; | ||
1030 | u32 *outbox; | 1089 | u32 *outbox; |
1031 | dma_addr_t outdma; | ||
1032 | int err; | 1090 | int err; |
1033 | 1091 | ||
1034 | #define QUERY_ADAPTER_OUT_SIZE 0x100 | 1092 | #define QUERY_ADAPTER_OUT_SIZE 0x100 |
@@ -1037,23 +1095,24 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev, | |||
1037 | #define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08 | 1095 | #define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08 |
1038 | #define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10 | 1096 | #define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10 |
1039 | 1097 | ||
1040 | outbox = pci_alloc_consistent(dev->pdev, QUERY_ADAPTER_OUT_SIZE, &outdma); | 1098 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
1041 | if (!outbox) | 1099 | if (IS_ERR(mailbox)) |
1042 | return -ENOMEM; | 1100 | return PTR_ERR(mailbox); |
1101 | outbox = mailbox->buf; | ||
1043 | 1102 | ||
1044 | err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_QUERY_ADAPTER, | 1103 | err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_ADAPTER, |
1045 | CMD_TIME_CLASS_A, status); | 1104 | CMD_TIME_CLASS_A, status); |
1046 | 1105 | ||
1047 | if (err) | 1106 | if (err) |
1048 | goto out; | 1107 | goto out; |
1049 | 1108 | ||
1050 | MTHCA_GET(adapter->vendor_id, outbox, QUERY_ADAPTER_VENDOR_ID_OFFSET); | 1109 | MTHCA_GET(adapter->vendor_id, outbox, QUERY_ADAPTER_VENDOR_ID_OFFSET); |
1051 | MTHCA_GET(adapter->device_id, outbox, QUERY_ADAPTER_DEVICE_ID_OFFSET); | 1110 | MTHCA_GET(adapter->device_id, outbox, QUERY_ADAPTER_DEVICE_ID_OFFSET); |
1052 | MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET); | 1111 | MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET); |
1053 | MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET); | 1112 | MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET); |
1054 | 1113 | ||
1055 | out: | 1114 | out: |
1056 | pci_free_consistent(dev->pdev, QUERY_DEV_LIM_OUT_SIZE, outbox, outdma); | 1115 | mthca_free_mailbox(dev, mailbox); |
1057 | return err; | 1116 | return err; |
1058 | } | 1117 | } |
1059 | 1118 | ||
@@ -1061,8 +1120,8 @@ int mthca_INIT_HCA(struct mthca_dev *dev, | |||
1061 | struct mthca_init_hca_param *param, | 1120 | struct mthca_init_hca_param *param, |
1062 | u8 *status) | 1121 | u8 *status) |
1063 | { | 1122 | { |
1123 | struct mthca_mailbox *mailbox; | ||
1064 | u32 *inbox; | 1124 | u32 *inbox; |
1065 | dma_addr_t indma; | ||
1066 | int err; | 1125 | int err; |
1067 | 1126 | ||
1068 | #define INIT_HCA_IN_SIZE 0x200 | 1127 | #define INIT_HCA_IN_SIZE 0x200 |
@@ -1102,9 +1161,10 @@ int mthca_INIT_HCA(struct mthca_dev *dev, | |||
1102 | #define INIT_HCA_UAR_SCATCH_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x10) | 1161 | #define INIT_HCA_UAR_SCATCH_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x10) |
1103 | #define INIT_HCA_UAR_CTX_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x18) | 1162 | #define INIT_HCA_UAR_CTX_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x18) |
1104 | 1163 | ||
1105 | inbox = pci_alloc_consistent(dev->pdev, INIT_HCA_IN_SIZE, &indma); | 1164 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
1106 | if (!inbox) | 1165 | if (IS_ERR(mailbox)) |
1107 | return -ENOMEM; | 1166 | return PTR_ERR(mailbox); |
1167 | inbox = mailbox->buf; | ||
1108 | 1168 | ||
1109 | memset(inbox, 0, INIT_HCA_IN_SIZE); | 1169 | memset(inbox, 0, INIT_HCA_IN_SIZE); |
1110 | 1170 | ||
@@ -1167,10 +1227,9 @@ int mthca_INIT_HCA(struct mthca_dev *dev, | |||
1167 | MTHCA_PUT(inbox, param->uarc_base, INIT_HCA_UAR_CTX_BASE_OFFSET); | 1227 | MTHCA_PUT(inbox, param->uarc_base, INIT_HCA_UAR_CTX_BASE_OFFSET); |
1168 | } | 1228 | } |
1169 | 1229 | ||
1170 | err = mthca_cmd(dev, indma, 0, 0, CMD_INIT_HCA, | 1230 | err = mthca_cmd(dev, mailbox->dma, 0, 0, CMD_INIT_HCA, HZ, status); |
1171 | HZ, status); | ||
1172 | 1231 | ||
1173 | pci_free_consistent(dev->pdev, INIT_HCA_IN_SIZE, inbox, indma); | 1232 | mthca_free_mailbox(dev, mailbox); |
1174 | return err; | 1233 | return err; |
1175 | } | 1234 | } |
1176 | 1235 | ||
@@ -1178,8 +1237,8 @@ int mthca_INIT_IB(struct mthca_dev *dev, | |||
1178 | struct mthca_init_ib_param *param, | 1237 | struct mthca_init_ib_param *param, |
1179 | int port, u8 *status) | 1238 | int port, u8 *status) |
1180 | { | 1239 | { |
1240 | struct mthca_mailbox *mailbox; | ||
1181 | u32 *inbox; | 1241 | u32 *inbox; |
1182 | dma_addr_t indma; | ||
1183 | int err; | 1242 | int err; |
1184 | u32 flags; | 1243 | u32 flags; |
1185 | 1244 | ||
@@ -1199,9 +1258,10 @@ int mthca_INIT_IB(struct mthca_dev *dev, | |||
1199 | #define INIT_IB_NODE_GUID_OFFSET 0x18 | 1258 | #define INIT_IB_NODE_GUID_OFFSET 0x18 |
1200 | #define INIT_IB_SI_GUID_OFFSET 0x20 | 1259 | #define INIT_IB_SI_GUID_OFFSET 0x20 |
1201 | 1260 | ||
1202 | inbox = pci_alloc_consistent(dev->pdev, INIT_IB_IN_SIZE, &indma); | 1261 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
1203 | if (!inbox) | 1262 | if (IS_ERR(mailbox)) |
1204 | return -ENOMEM; | 1263 | return PTR_ERR(mailbox); |
1264 | inbox = mailbox->buf; | ||
1205 | 1265 | ||
1206 | memset(inbox, 0, INIT_IB_IN_SIZE); | 1266 | memset(inbox, 0, INIT_IB_IN_SIZE); |
1207 | 1267 | ||
@@ -1221,10 +1281,10 @@ int mthca_INIT_IB(struct mthca_dev *dev, | |||
1221 | MTHCA_PUT(inbox, param->node_guid, INIT_IB_NODE_GUID_OFFSET); | 1281 | MTHCA_PUT(inbox, param->node_guid, INIT_IB_NODE_GUID_OFFSET); |
1222 | MTHCA_PUT(inbox, param->si_guid, INIT_IB_SI_GUID_OFFSET); | 1282 | MTHCA_PUT(inbox, param->si_guid, INIT_IB_SI_GUID_OFFSET); |
1223 | 1283 | ||
1224 | err = mthca_cmd(dev, indma, port, 0, CMD_INIT_IB, | 1284 | err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_INIT_IB, |
1225 | CMD_TIME_CLASS_A, status); | 1285 | CMD_TIME_CLASS_A, status); |
1226 | 1286 | ||
1227 | pci_free_consistent(dev->pdev, INIT_HCA_IN_SIZE, inbox, indma); | 1287 | mthca_free_mailbox(dev, mailbox); |
1228 | return err; | 1288 | return err; |
1229 | } | 1289 | } |
1230 | 1290 | ||
@@ -1241,8 +1301,8 @@ int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status) | |||
1241 | int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param, | 1301 | int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param, |
1242 | int port, u8 *status) | 1302 | int port, u8 *status) |
1243 | { | 1303 | { |
1304 | struct mthca_mailbox *mailbox; | ||
1244 | u32 *inbox; | 1305 | u32 *inbox; |
1245 | dma_addr_t indma; | ||
1246 | int err; | 1306 | int err; |
1247 | u32 flags = 0; | 1307 | u32 flags = 0; |
1248 | 1308 | ||
@@ -1253,9 +1313,10 @@ int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param, | |||
1253 | #define SET_IB_CAP_MASK_OFFSET 0x04 | 1313 | #define SET_IB_CAP_MASK_OFFSET 0x04 |
1254 | #define SET_IB_SI_GUID_OFFSET 0x08 | 1314 | #define SET_IB_SI_GUID_OFFSET 0x08 |
1255 | 1315 | ||
1256 | inbox = pci_alloc_consistent(dev->pdev, SET_IB_IN_SIZE, &indma); | 1316 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
1257 | if (!inbox) | 1317 | if (IS_ERR(mailbox)) |
1258 | return -ENOMEM; | 1318 | return PTR_ERR(mailbox); |
1319 | inbox = mailbox->buf; | ||
1259 | 1320 | ||
1260 | memset(inbox, 0, SET_IB_IN_SIZE); | 1321 | memset(inbox, 0, SET_IB_IN_SIZE); |
1261 | 1322 | ||
@@ -1266,10 +1327,10 @@ int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param, | |||
1266 | MTHCA_PUT(inbox, param->cap_mask, SET_IB_CAP_MASK_OFFSET); | 1327 | MTHCA_PUT(inbox, param->cap_mask, SET_IB_CAP_MASK_OFFSET); |
1267 | MTHCA_PUT(inbox, param->si_guid, SET_IB_SI_GUID_OFFSET); | 1328 | MTHCA_PUT(inbox, param->si_guid, SET_IB_SI_GUID_OFFSET); |
1268 | 1329 | ||
1269 | err = mthca_cmd(dev, indma, port, 0, CMD_SET_IB, | 1330 | err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_SET_IB, |
1270 | CMD_TIME_CLASS_B, status); | 1331 | CMD_TIME_CLASS_B, status); |
1271 | 1332 | ||
1272 | pci_free_consistent(dev->pdev, INIT_HCA_IN_SIZE, inbox, indma); | 1333 | mthca_free_mailbox(dev, mailbox); |
1273 | return err; | 1334 | return err; |
1274 | } | 1335 | } |
1275 | 1336 | ||
@@ -1280,20 +1341,22 @@ int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *st | |||
1280 | 1341 | ||
1281 | int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status) | 1342 | int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status) |
1282 | { | 1343 | { |
1344 | struct mthca_mailbox *mailbox; | ||
1283 | u64 *inbox; | 1345 | u64 *inbox; |
1284 | dma_addr_t indma; | ||
1285 | int err; | 1346 | int err; |
1286 | 1347 | ||
1287 | inbox = pci_alloc_consistent(dev->pdev, 16, &indma); | 1348 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
1288 | if (!inbox) | 1349 | if (IS_ERR(mailbox)) |
1289 | return -ENOMEM; | 1350 | return PTR_ERR(mailbox); |
1351 | inbox = mailbox->buf; | ||
1290 | 1352 | ||
1291 | inbox[0] = cpu_to_be64(virt); | 1353 | inbox[0] = cpu_to_be64(virt); |
1292 | inbox[1] = cpu_to_be64(dma_addr); | 1354 | inbox[1] = cpu_to_be64(dma_addr); |
1293 | 1355 | ||
1294 | err = mthca_cmd(dev, indma, 1, 0, CMD_MAP_ICM, CMD_TIME_CLASS_B, status); | 1356 | err = mthca_cmd(dev, mailbox->dma, 1, 0, CMD_MAP_ICM, |
1357 | CMD_TIME_CLASS_B, status); | ||
1295 | 1358 | ||
1296 | pci_free_consistent(dev->pdev, 16, inbox, indma); | 1359 | mthca_free_mailbox(dev, mailbox); |
1297 | 1360 | ||
1298 | if (!err) | 1361 | if (!err) |
1299 | mthca_dbg(dev, "Mapped page at %llx to %llx for ICM.\n", | 1362 | mthca_dbg(dev, "Mapped page at %llx to %llx for ICM.\n", |
@@ -1338,69 +1401,26 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages, | |||
1338 | return 0; | 1401 | return 0; |
1339 | } | 1402 | } |
1340 | 1403 | ||
1341 | int mthca_SW2HW_MPT(struct mthca_dev *dev, void *mpt_entry, | 1404 | int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
1342 | int mpt_index, u8 *status) | 1405 | int mpt_index, u8 *status) |
1343 | { | 1406 | { |
1344 | dma_addr_t indma; | 1407 | return mthca_cmd(dev, mailbox->dma, mpt_index, 0, CMD_SW2HW_MPT, |
1345 | int err; | 1408 | CMD_TIME_CLASS_B, status); |
1346 | |||
1347 | indma = pci_map_single(dev->pdev, mpt_entry, | ||
1348 | MTHCA_MPT_ENTRY_SIZE, | ||
1349 | PCI_DMA_TODEVICE); | ||
1350 | if (pci_dma_mapping_error(indma)) | ||
1351 | return -ENOMEM; | ||
1352 | |||
1353 | err = mthca_cmd(dev, indma, mpt_index, 0, CMD_SW2HW_MPT, | ||
1354 | CMD_TIME_CLASS_B, status); | ||
1355 | |||
1356 | pci_unmap_single(dev->pdev, indma, | ||
1357 | MTHCA_MPT_ENTRY_SIZE, PCI_DMA_TODEVICE); | ||
1358 | return err; | ||
1359 | } | 1409 | } |
1360 | 1410 | ||
1361 | int mthca_HW2SW_MPT(struct mthca_dev *dev, void *mpt_entry, | 1411 | int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
1362 | int mpt_index, u8 *status) | 1412 | int mpt_index, u8 *status) |
1363 | { | 1413 | { |
1364 | dma_addr_t outdma = 0; | 1414 | return mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index, |
1365 | int err; | 1415 | !mailbox, CMD_HW2SW_MPT, |
1366 | 1416 | CMD_TIME_CLASS_B, status); | |
1367 | if (mpt_entry) { | ||
1368 | outdma = pci_map_single(dev->pdev, mpt_entry, | ||
1369 | MTHCA_MPT_ENTRY_SIZE, | ||
1370 | PCI_DMA_FROMDEVICE); | ||
1371 | if (pci_dma_mapping_error(outdma)) | ||
1372 | return -ENOMEM; | ||
1373 | } | ||
1374 | |||
1375 | err = mthca_cmd_box(dev, 0, outdma, mpt_index, !mpt_entry, | ||
1376 | CMD_HW2SW_MPT, | ||
1377 | CMD_TIME_CLASS_B, status); | ||
1378 | |||
1379 | if (mpt_entry) | ||
1380 | pci_unmap_single(dev->pdev, outdma, | ||
1381 | MTHCA_MPT_ENTRY_SIZE, | ||
1382 | PCI_DMA_FROMDEVICE); | ||
1383 | return err; | ||
1384 | } | 1417 | } |
1385 | 1418 | ||
1386 | int mthca_WRITE_MTT(struct mthca_dev *dev, u64 *mtt_entry, | 1419 | int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
1387 | int num_mtt, u8 *status) | 1420 | int num_mtt, u8 *status) |
1388 | { | 1421 | { |
1389 | dma_addr_t indma; | 1422 | return mthca_cmd(dev, mailbox->dma, num_mtt, 0, CMD_WRITE_MTT, |
1390 | int err; | 1423 | CMD_TIME_CLASS_B, status); |
1391 | |||
1392 | indma = pci_map_single(dev->pdev, mtt_entry, | ||
1393 | (num_mtt + 2) * 8, | ||
1394 | PCI_DMA_TODEVICE); | ||
1395 | if (pci_dma_mapping_error(indma)) | ||
1396 | return -ENOMEM; | ||
1397 | |||
1398 | err = mthca_cmd(dev, indma, num_mtt, 0, CMD_WRITE_MTT, | ||
1399 | CMD_TIME_CLASS_B, status); | ||
1400 | |||
1401 | pci_unmap_single(dev->pdev, indma, | ||
1402 | (num_mtt + 2) * 8, PCI_DMA_TODEVICE); | ||
1403 | return err; | ||
1404 | } | 1424 | } |
1405 | 1425 | ||
1406 | int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status) | 1426 | int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status) |
@@ -1418,92 +1438,38 @@ int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap, | |||
1418 | 0, CMD_MAP_EQ, CMD_TIME_CLASS_B, status); | 1438 | 0, CMD_MAP_EQ, CMD_TIME_CLASS_B, status); |
1419 | } | 1439 | } |
1420 | 1440 | ||
1421 | int mthca_SW2HW_EQ(struct mthca_dev *dev, void *eq_context, | 1441 | int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
1422 | int eq_num, u8 *status) | 1442 | int eq_num, u8 *status) |
1423 | { | 1443 | { |
1424 | dma_addr_t indma; | 1444 | return mthca_cmd(dev, mailbox->dma, eq_num, 0, CMD_SW2HW_EQ, |
1425 | int err; | 1445 | CMD_TIME_CLASS_A, status); |
1426 | |||
1427 | indma = pci_map_single(dev->pdev, eq_context, | ||
1428 | MTHCA_EQ_CONTEXT_SIZE, | ||
1429 | PCI_DMA_TODEVICE); | ||
1430 | if (pci_dma_mapping_error(indma)) | ||
1431 | return -ENOMEM; | ||
1432 | |||
1433 | err = mthca_cmd(dev, indma, eq_num, 0, CMD_SW2HW_EQ, | ||
1434 | CMD_TIME_CLASS_A, status); | ||
1435 | |||
1436 | pci_unmap_single(dev->pdev, indma, | ||
1437 | MTHCA_EQ_CONTEXT_SIZE, PCI_DMA_TODEVICE); | ||
1438 | return err; | ||
1439 | } | 1446 | } |
1440 | 1447 | ||
1441 | int mthca_HW2SW_EQ(struct mthca_dev *dev, void *eq_context, | 1448 | int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
1442 | int eq_num, u8 *status) | 1449 | int eq_num, u8 *status) |
1443 | { | 1450 | { |
1444 | dma_addr_t outdma = 0; | 1451 | return mthca_cmd_box(dev, 0, mailbox->dma, eq_num, 0, |
1445 | int err; | 1452 | CMD_HW2SW_EQ, |
1446 | 1453 | CMD_TIME_CLASS_A, status); | |
1447 | outdma = pci_map_single(dev->pdev, eq_context, | ||
1448 | MTHCA_EQ_CONTEXT_SIZE, | ||
1449 | PCI_DMA_FROMDEVICE); | ||
1450 | if (pci_dma_mapping_error(outdma)) | ||
1451 | return -ENOMEM; | ||
1452 | |||
1453 | err = mthca_cmd_box(dev, 0, outdma, eq_num, 0, | ||
1454 | CMD_HW2SW_EQ, | ||
1455 | CMD_TIME_CLASS_A, status); | ||
1456 | |||
1457 | pci_unmap_single(dev->pdev, outdma, | ||
1458 | MTHCA_EQ_CONTEXT_SIZE, | ||
1459 | PCI_DMA_FROMDEVICE); | ||
1460 | return err; | ||
1461 | } | 1454 | } |
1462 | 1455 | ||
1463 | int mthca_SW2HW_CQ(struct mthca_dev *dev, void *cq_context, | 1456 | int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
1464 | int cq_num, u8 *status) | 1457 | int cq_num, u8 *status) |
1465 | { | 1458 | { |
1466 | dma_addr_t indma; | 1459 | return mthca_cmd(dev, mailbox->dma, cq_num, 0, CMD_SW2HW_CQ, |
1467 | int err; | ||
1468 | |||
1469 | indma = pci_map_single(dev->pdev, cq_context, | ||
1470 | MTHCA_CQ_CONTEXT_SIZE, | ||
1471 | PCI_DMA_TODEVICE); | ||
1472 | if (pci_dma_mapping_error(indma)) | ||
1473 | return -ENOMEM; | ||
1474 | |||
1475 | err = mthca_cmd(dev, indma, cq_num, 0, CMD_SW2HW_CQ, | ||
1476 | CMD_TIME_CLASS_A, status); | 1460 | CMD_TIME_CLASS_A, status); |
1477 | |||
1478 | pci_unmap_single(dev->pdev, indma, | ||
1479 | MTHCA_CQ_CONTEXT_SIZE, PCI_DMA_TODEVICE); | ||
1480 | return err; | ||
1481 | } | 1461 | } |
1482 | 1462 | ||
1483 | int mthca_HW2SW_CQ(struct mthca_dev *dev, void *cq_context, | 1463 | int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
1484 | int cq_num, u8 *status) | 1464 | int cq_num, u8 *status) |
1485 | { | 1465 | { |
1486 | dma_addr_t outdma = 0; | 1466 | return mthca_cmd_box(dev, 0, mailbox->dma, cq_num, 0, |
1487 | int err; | 1467 | CMD_HW2SW_CQ, |
1488 | 1468 | CMD_TIME_CLASS_A, status); | |
1489 | outdma = pci_map_single(dev->pdev, cq_context, | ||
1490 | MTHCA_CQ_CONTEXT_SIZE, | ||
1491 | PCI_DMA_FROMDEVICE); | ||
1492 | if (pci_dma_mapping_error(outdma)) | ||
1493 | return -ENOMEM; | ||
1494 | |||
1495 | err = mthca_cmd_box(dev, 0, outdma, cq_num, 0, | ||
1496 | CMD_HW2SW_CQ, | ||
1497 | CMD_TIME_CLASS_A, status); | ||
1498 | |||
1499 | pci_unmap_single(dev->pdev, outdma, | ||
1500 | MTHCA_CQ_CONTEXT_SIZE, | ||
1501 | PCI_DMA_FROMDEVICE); | ||
1502 | return err; | ||
1503 | } | 1469 | } |
1504 | 1470 | ||
1505 | int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, | 1471 | int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, |
1506 | int is_ee, void *qp_context, u32 optmask, | 1472 | int is_ee, struct mthca_mailbox *mailbox, u32 optmask, |
1507 | u8 *status) | 1473 | u8 *status) |
1508 | { | 1474 | { |
1509 | static const u16 op[] = { | 1475 | static const u16 op[] = { |
@@ -1520,36 +1486,34 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, | |||
1520 | [MTHCA_TRANS_ANY2RST] = CMD_ERR2RST_QPEE | 1486 | [MTHCA_TRANS_ANY2RST] = CMD_ERR2RST_QPEE |
1521 | }; | 1487 | }; |
1522 | u8 op_mod = 0; | 1488 | u8 op_mod = 0; |
1523 | 1489 | int my_mailbox = 0; | |
1524 | dma_addr_t indma; | ||
1525 | int err; | 1490 | int err; |
1526 | 1491 | ||
1527 | if (trans < 0 || trans >= ARRAY_SIZE(op)) | 1492 | if (trans < 0 || trans >= ARRAY_SIZE(op)) |
1528 | return -EINVAL; | 1493 | return -EINVAL; |
1529 | 1494 | ||
1530 | if (trans == MTHCA_TRANS_ANY2RST) { | 1495 | if (trans == MTHCA_TRANS_ANY2RST) { |
1531 | indma = 0; | ||
1532 | op_mod = 3; /* don't write outbox, any->reset */ | 1496 | op_mod = 3; /* don't write outbox, any->reset */ |
1533 | 1497 | ||
1534 | /* For debugging */ | 1498 | /* For debugging */ |
1535 | qp_context = pci_alloc_consistent(dev->pdev, MTHCA_QP_CONTEXT_SIZE, | 1499 | if (!mailbox) { |
1536 | &indma); | 1500 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
1537 | op_mod = 2; /* write outbox, any->reset */ | 1501 | if (!IS_ERR(mailbox)) { |
1502 | my_mailbox = 1; | ||
1503 | op_mod = 2; /* write outbox, any->reset */ | ||
1504 | } else | ||
1505 | mailbox = NULL; | ||
1506 | } | ||
1538 | } else { | 1507 | } else { |
1539 | indma = pci_map_single(dev->pdev, qp_context, | ||
1540 | MTHCA_QP_CONTEXT_SIZE, | ||
1541 | PCI_DMA_TODEVICE); | ||
1542 | if (pci_dma_mapping_error(indma)) | ||
1543 | return -ENOMEM; | ||
1544 | |||
1545 | if (0) { | 1508 | if (0) { |
1546 | int i; | 1509 | int i; |
1547 | mthca_dbg(dev, "Dumping QP context:\n"); | 1510 | mthca_dbg(dev, "Dumping QP context:\n"); |
1548 | printk(" opt param mask: %08x\n", be32_to_cpup(qp_context)); | 1511 | printk(" opt param mask: %08x\n", be32_to_cpup(mailbox->buf)); |
1549 | for (i = 0; i < 0x100 / 4; ++i) { | 1512 | for (i = 0; i < 0x100 / 4; ++i) { |
1550 | if (i % 8 == 0) | 1513 | if (i % 8 == 0) |
1551 | printk(" [%02x] ", i * 4); | 1514 | printk(" [%02x] ", i * 4); |
1552 | printk(" %08x", be32_to_cpu(((u32 *) qp_context)[i + 2])); | 1515 | printk(" %08x", |
1516 | be32_to_cpu(((u32 *) mailbox->buf)[i + 2])); | ||
1553 | if ((i + 1) % 8 == 0) | 1517 | if ((i + 1) % 8 == 0) |
1554 | printk("\n"); | 1518 | printk("\n"); |
1555 | } | 1519 | } |
@@ -1557,55 +1521,39 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, | |||
1557 | } | 1521 | } |
1558 | 1522 | ||
1559 | if (trans == MTHCA_TRANS_ANY2RST) { | 1523 | if (trans == MTHCA_TRANS_ANY2RST) { |
1560 | err = mthca_cmd_box(dev, 0, indma, (!!is_ee << 24) | num, | 1524 | err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, |
1561 | op_mod, op[trans], CMD_TIME_CLASS_C, status); | 1525 | (!!is_ee << 24) | num, op_mod, |
1526 | op[trans], CMD_TIME_CLASS_C, status); | ||
1562 | 1527 | ||
1563 | if (0) { | 1528 | if (0 && mailbox) { |
1564 | int i; | 1529 | int i; |
1565 | mthca_dbg(dev, "Dumping QP context:\n"); | 1530 | mthca_dbg(dev, "Dumping QP context:\n"); |
1566 | printk(" %08x\n", be32_to_cpup(qp_context)); | 1531 | printk(" %08x\n", be32_to_cpup(mailbox->buf)); |
1567 | for (i = 0; i < 0x100 / 4; ++i) { | 1532 | for (i = 0; i < 0x100 / 4; ++i) { |
1568 | if (i % 8 == 0) | 1533 | if (i % 8 == 0) |
1569 | printk("[%02x] ", i * 4); | 1534 | printk("[%02x] ", i * 4); |
1570 | printk(" %08x", be32_to_cpu(((u32 *) qp_context)[i + 2])); | 1535 | printk(" %08x", |
1536 | be32_to_cpu(((u32 *) mailbox->buf)[i + 2])); | ||
1571 | if ((i + 1) % 8 == 0) | 1537 | if ((i + 1) % 8 == 0) |
1572 | printk("\n"); | 1538 | printk("\n"); |
1573 | } | 1539 | } |
1574 | } | 1540 | } |
1575 | 1541 | ||
1576 | } else | 1542 | } else |
1577 | err = mthca_cmd(dev, indma, (!!is_ee << 24) | num, | 1543 | err = mthca_cmd(dev, mailbox->dma, (!!is_ee << 24) | num, |
1578 | op_mod, op[trans], CMD_TIME_CLASS_C, status); | 1544 | op_mod, op[trans], CMD_TIME_CLASS_C, status); |
1579 | 1545 | ||
1580 | if (trans != MTHCA_TRANS_ANY2RST) | 1546 | if (my_mailbox) |
1581 | pci_unmap_single(dev->pdev, indma, | 1547 | mthca_free_mailbox(dev, mailbox); |
1582 | MTHCA_QP_CONTEXT_SIZE, PCI_DMA_TODEVICE); | 1548 | |
1583 | else | ||
1584 | pci_free_consistent(dev->pdev, MTHCA_QP_CONTEXT_SIZE, | ||
1585 | qp_context, indma); | ||
1586 | return err; | 1549 | return err; |
1587 | } | 1550 | } |
1588 | 1551 | ||
1589 | int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee, | 1552 | int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee, |
1590 | void *qp_context, u8 *status) | 1553 | struct mthca_mailbox *mailbox, u8 *status) |
1591 | { | 1554 | { |
1592 | dma_addr_t outdma = 0; | 1555 | return mthca_cmd_box(dev, 0, mailbox->dma, (!!is_ee << 24) | num, 0, |
1593 | int err; | 1556 | CMD_QUERY_QPEE, CMD_TIME_CLASS_A, status); |
1594 | |||
1595 | outdma = pci_map_single(dev->pdev, qp_context, | ||
1596 | MTHCA_QP_CONTEXT_SIZE, | ||
1597 | PCI_DMA_FROMDEVICE); | ||
1598 | if (pci_dma_mapping_error(outdma)) | ||
1599 | return -ENOMEM; | ||
1600 | |||
1601 | err = mthca_cmd_box(dev, 0, outdma, (!!is_ee << 24) | num, 0, | ||
1602 | CMD_QUERY_QPEE, | ||
1603 | CMD_TIME_CLASS_A, status); | ||
1604 | |||
1605 | pci_unmap_single(dev->pdev, outdma, | ||
1606 | MTHCA_QP_CONTEXT_SIZE, | ||
1607 | PCI_DMA_FROMDEVICE); | ||
1608 | return err; | ||
1609 | } | 1557 | } |
1610 | 1558 | ||
1611 | int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn, | 1559 | int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn, |
@@ -1635,11 +1583,11 @@ int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn, | |||
1635 | } | 1583 | } |
1636 | 1584 | ||
1637 | int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, | 1585 | int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, |
1638 | int port, struct ib_wc* in_wc, struct ib_grh* in_grh, | 1586 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, |
1639 | void *in_mad, void *response_mad, u8 *status) | 1587 | void *in_mad, void *response_mad, u8 *status) |
1640 | { | 1588 | { |
1641 | void *box; | 1589 | struct mthca_mailbox *inmailbox, *outmailbox; |
1642 | dma_addr_t dma; | 1590 | void *inbox; |
1643 | int err; | 1591 | int err; |
1644 | u32 in_modifier = port; | 1592 | u32 in_modifier = port; |
1645 | u8 op_modifier = 0; | 1593 | u8 op_modifier = 0; |
@@ -1653,11 +1601,18 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, | |||
1653 | #define MAD_IFC_PKEY_OFFSET 0x10e | 1601 | #define MAD_IFC_PKEY_OFFSET 0x10e |
1654 | #define MAD_IFC_GRH_OFFSET 0x140 | 1602 | #define MAD_IFC_GRH_OFFSET 0x140 |
1655 | 1603 | ||
1656 | box = pci_alloc_consistent(dev->pdev, MAD_IFC_BOX_SIZE, &dma); | 1604 | inmailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
1657 | if (!box) | 1605 | if (IS_ERR(inmailbox)) |
1658 | return -ENOMEM; | 1606 | return PTR_ERR(inmailbox); |
1607 | inbox = inmailbox->buf; | ||
1659 | 1608 | ||
1660 | memcpy(box, in_mad, 256); | 1609 | outmailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
1610 | if (IS_ERR(outmailbox)) { | ||
1611 | mthca_free_mailbox(dev, inmailbox); | ||
1612 | return PTR_ERR(outmailbox); | ||
1613 | } | ||
1614 | |||
1615 | memcpy(inbox, in_mad, 256); | ||
1661 | 1616 | ||
1662 | /* | 1617 | /* |
1663 | * Key check traps can't be generated unless we have in_wc to | 1618 | * Key check traps can't be generated unless we have in_wc to |
@@ -1671,97 +1626,65 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, | |||
1671 | if (in_wc) { | 1626 | if (in_wc) { |
1672 | u8 val; | 1627 | u8 val; |
1673 | 1628 | ||
1674 | memset(box + 256, 0, 256); | 1629 | memset(inbox + 256, 0, 256); |
1675 | 1630 | ||
1676 | MTHCA_PUT(box, in_wc->qp_num, MAD_IFC_MY_QPN_OFFSET); | 1631 | MTHCA_PUT(inbox, in_wc->qp_num, MAD_IFC_MY_QPN_OFFSET); |
1677 | MTHCA_PUT(box, in_wc->src_qp, MAD_IFC_RQPN_OFFSET); | 1632 | MTHCA_PUT(inbox, in_wc->src_qp, MAD_IFC_RQPN_OFFSET); |
1678 | 1633 | ||
1679 | val = in_wc->sl << 4; | 1634 | val = in_wc->sl << 4; |
1680 | MTHCA_PUT(box, val, MAD_IFC_SL_OFFSET); | 1635 | MTHCA_PUT(inbox, val, MAD_IFC_SL_OFFSET); |
1681 | 1636 | ||
1682 | val = in_wc->dlid_path_bits | | 1637 | val = in_wc->dlid_path_bits | |
1683 | (in_wc->wc_flags & IB_WC_GRH ? 0x80 : 0); | 1638 | (in_wc->wc_flags & IB_WC_GRH ? 0x80 : 0); |
1684 | MTHCA_PUT(box, val, MAD_IFC_GRH_OFFSET); | 1639 | MTHCA_PUT(inbox, val, MAD_IFC_GRH_OFFSET); |
1685 | 1640 | ||
1686 | MTHCA_PUT(box, in_wc->slid, MAD_IFC_RLID_OFFSET); | 1641 | MTHCA_PUT(inbox, in_wc->slid, MAD_IFC_RLID_OFFSET); |
1687 | MTHCA_PUT(box, in_wc->pkey_index, MAD_IFC_PKEY_OFFSET); | 1642 | MTHCA_PUT(inbox, in_wc->pkey_index, MAD_IFC_PKEY_OFFSET); |
1688 | 1643 | ||
1689 | if (in_grh) | 1644 | if (in_grh) |
1690 | memcpy((u8 *) box + MAD_IFC_GRH_OFFSET, in_grh, 40); | 1645 | memcpy(inbox + MAD_IFC_GRH_OFFSET, in_grh, 40); |
1691 | 1646 | ||
1692 | op_modifier |= 0x10; | 1647 | op_modifier |= 0x10; |
1693 | 1648 | ||
1694 | in_modifier |= in_wc->slid << 16; | 1649 | in_modifier |= in_wc->slid << 16; |
1695 | } | 1650 | } |
1696 | 1651 | ||
1697 | err = mthca_cmd_box(dev, dma, dma + 512, in_modifier, op_modifier, | 1652 | err = mthca_cmd_box(dev, inmailbox->dma, outmailbox->dma, |
1653 | in_modifier, op_modifier, | ||
1698 | CMD_MAD_IFC, CMD_TIME_CLASS_C, status); | 1654 | CMD_MAD_IFC, CMD_TIME_CLASS_C, status); |
1699 | 1655 | ||
1700 | if (!err && !*status) | 1656 | if (!err && !*status) |
1701 | memcpy(response_mad, box + 512, 256); | 1657 | memcpy(response_mad, outmailbox->buf, 256); |
1702 | 1658 | ||
1703 | pci_free_consistent(dev->pdev, MAD_IFC_BOX_SIZE, box, dma); | 1659 | mthca_free_mailbox(dev, inmailbox); |
1660 | mthca_free_mailbox(dev, outmailbox); | ||
1704 | return err; | 1661 | return err; |
1705 | } | 1662 | } |
1706 | 1663 | ||
1707 | int mthca_READ_MGM(struct mthca_dev *dev, int index, void *mgm, | 1664 | int mthca_READ_MGM(struct mthca_dev *dev, int index, |
1708 | u8 *status) | 1665 | struct mthca_mailbox *mailbox, u8 *status) |
1709 | { | 1666 | { |
1710 | dma_addr_t outdma = 0; | 1667 | return mthca_cmd_box(dev, 0, mailbox->dma, index, 0, |
1711 | int err; | 1668 | CMD_READ_MGM, CMD_TIME_CLASS_A, status); |
1712 | |||
1713 | outdma = pci_map_single(dev->pdev, mgm, | ||
1714 | MTHCA_MGM_ENTRY_SIZE, | ||
1715 | PCI_DMA_FROMDEVICE); | ||
1716 | if (pci_dma_mapping_error(outdma)) | ||
1717 | return -ENOMEM; | ||
1718 | |||
1719 | err = mthca_cmd_box(dev, 0, outdma, index, 0, | ||
1720 | CMD_READ_MGM, | ||
1721 | CMD_TIME_CLASS_A, status); | ||
1722 | |||
1723 | pci_unmap_single(dev->pdev, outdma, | ||
1724 | MTHCA_MGM_ENTRY_SIZE, | ||
1725 | PCI_DMA_FROMDEVICE); | ||
1726 | return err; | ||
1727 | } | 1669 | } |
1728 | 1670 | ||
1729 | int mthca_WRITE_MGM(struct mthca_dev *dev, int index, void *mgm, | 1671 | int mthca_WRITE_MGM(struct mthca_dev *dev, int index, |
1730 | u8 *status) | 1672 | struct mthca_mailbox *mailbox, u8 *status) |
1731 | { | 1673 | { |
1732 | dma_addr_t indma; | 1674 | return mthca_cmd(dev, mailbox->dma, index, 0, CMD_WRITE_MGM, |
1733 | int err; | 1675 | CMD_TIME_CLASS_A, status); |
1734 | |||
1735 | indma = pci_map_single(dev->pdev, mgm, | ||
1736 | MTHCA_MGM_ENTRY_SIZE, | ||
1737 | PCI_DMA_TODEVICE); | ||
1738 | if (pci_dma_mapping_error(indma)) | ||
1739 | return -ENOMEM; | ||
1740 | |||
1741 | err = mthca_cmd(dev, indma, index, 0, CMD_WRITE_MGM, | ||
1742 | CMD_TIME_CLASS_A, status); | ||
1743 | |||
1744 | pci_unmap_single(dev->pdev, indma, | ||
1745 | MTHCA_MGM_ENTRY_SIZE, PCI_DMA_TODEVICE); | ||
1746 | return err; | ||
1747 | } | 1676 | } |
1748 | 1677 | ||
1749 | int mthca_MGID_HASH(struct mthca_dev *dev, void *gid, u16 *hash, | 1678 | int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
1750 | u8 *status) | 1679 | u16 *hash, u8 *status) |
1751 | { | 1680 | { |
1752 | dma_addr_t indma; | ||
1753 | u64 imm; | 1681 | u64 imm; |
1754 | int err; | 1682 | int err; |
1755 | 1683 | ||
1756 | indma = pci_map_single(dev->pdev, gid, 16, PCI_DMA_TODEVICE); | 1684 | err = mthca_cmd_imm(dev, mailbox->dma, &imm, 0, 0, CMD_MGID_HASH, |
1757 | if (pci_dma_mapping_error(indma)) | ||
1758 | return -ENOMEM; | ||
1759 | |||
1760 | err = mthca_cmd_imm(dev, indma, &imm, 0, 0, CMD_MGID_HASH, | ||
1761 | CMD_TIME_CLASS_A, status); | 1685 | CMD_TIME_CLASS_A, status); |
1762 | *hash = imm; | ||
1763 | 1686 | ||
1764 | pci_unmap_single(dev->pdev, indma, 16, PCI_DMA_TODEVICE); | 1687 | *hash = imm; |
1765 | return err; | 1688 | return err; |
1766 | } | 1689 | } |
1767 | 1690 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h index adf039b3c540..ed517f175dd6 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.h +++ b/drivers/infiniband/hw/mthca/mthca_cmd.h | |||
@@ -37,8 +37,7 @@ | |||
37 | 37 | ||
38 | #include <ib_verbs.h> | 38 | #include <ib_verbs.h> |
39 | 39 | ||
40 | #define MTHCA_CMD_MAILBOX_ALIGN 16UL | 40 | #define MTHCA_MAILBOX_SIZE 4096 |
41 | #define MTHCA_CMD_MAILBOX_EXTRA (MTHCA_CMD_MAILBOX_ALIGN - 1) | ||
42 | 41 | ||
43 | enum { | 42 | enum { |
44 | /* command completed successfully: */ | 43 | /* command completed successfully: */ |
@@ -112,6 +111,11 @@ enum { | |||
112 | DEV_LIM_FLAG_UD_MULTI = 1 << 21, | 111 | DEV_LIM_FLAG_UD_MULTI = 1 << 21, |
113 | }; | 112 | }; |
114 | 113 | ||
114 | struct mthca_mailbox { | ||
115 | dma_addr_t dma; | ||
116 | void *buf; | ||
117 | }; | ||
118 | |||
115 | struct mthca_dev_lim { | 119 | struct mthca_dev_lim { |
116 | int max_srq_sz; | 120 | int max_srq_sz; |
117 | int max_qp_sz; | 121 | int max_qp_sz; |
@@ -235,11 +239,17 @@ struct mthca_set_ib_param { | |||
235 | u32 cap_mask; | 239 | u32 cap_mask; |
236 | }; | 240 | }; |
237 | 241 | ||
242 | int mthca_cmd_init(struct mthca_dev *dev); | ||
243 | void mthca_cmd_cleanup(struct mthca_dev *dev); | ||
238 | int mthca_cmd_use_events(struct mthca_dev *dev); | 244 | int mthca_cmd_use_events(struct mthca_dev *dev); |
239 | void mthca_cmd_use_polling(struct mthca_dev *dev); | 245 | void mthca_cmd_use_polling(struct mthca_dev *dev); |
240 | void mthca_cmd_event(struct mthca_dev *dev, u16 token, | 246 | void mthca_cmd_event(struct mthca_dev *dev, u16 token, |
241 | u8 status, u64 out_param); | 247 | u8 status, u64 out_param); |
242 | 248 | ||
249 | struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev, | ||
250 | unsigned int gfp_mask); | ||
251 | void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox); | ||
252 | |||
243 | int mthca_SYS_EN(struct mthca_dev *dev, u8 *status); | 253 | int mthca_SYS_EN(struct mthca_dev *dev, u8 *status); |
244 | int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status); | 254 | int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status); |
245 | int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status); | 255 | int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status); |
@@ -270,41 +280,39 @@ int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status); | |||
270 | int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status); | 280 | int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status); |
271 | int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages, | 281 | int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages, |
272 | u8 *status); | 282 | u8 *status); |
273 | int mthca_SW2HW_MPT(struct mthca_dev *dev, void *mpt_entry, | 283 | int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
274 | int mpt_index, u8 *status); | 284 | int mpt_index, u8 *status); |
275 | int mthca_HW2SW_MPT(struct mthca_dev *dev, void *mpt_entry, | 285 | int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
276 | int mpt_index, u8 *status); | 286 | int mpt_index, u8 *status); |
277 | int mthca_WRITE_MTT(struct mthca_dev *dev, u64 *mtt_entry, | 287 | int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
278 | int num_mtt, u8 *status); | 288 | int num_mtt, u8 *status); |
279 | int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status); | 289 | int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status); |
280 | int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap, | 290 | int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap, |
281 | int eq_num, u8 *status); | 291 | int eq_num, u8 *status); |
282 | int mthca_SW2HW_EQ(struct mthca_dev *dev, void *eq_context, | 292 | int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
283 | int eq_num, u8 *status); | 293 | int eq_num, u8 *status); |
284 | int mthca_HW2SW_EQ(struct mthca_dev *dev, void *eq_context, | 294 | int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
285 | int eq_num, u8 *status); | 295 | int eq_num, u8 *status); |
286 | int mthca_SW2HW_CQ(struct mthca_dev *dev, void *cq_context, | 296 | int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
287 | int cq_num, u8 *status); | 297 | int cq_num, u8 *status); |
288 | int mthca_HW2SW_CQ(struct mthca_dev *dev, void *cq_context, | 298 | int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
289 | int cq_num, u8 *status); | 299 | int cq_num, u8 *status); |
290 | int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, | 300 | int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, |
291 | int is_ee, void *qp_context, u32 optmask, | 301 | int is_ee, struct mthca_mailbox *mailbox, u32 optmask, |
292 | u8 *status); | 302 | u8 *status); |
293 | int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee, | 303 | int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee, |
294 | void *qp_context, u8 *status); | 304 | struct mthca_mailbox *mailbox, u8 *status); |
295 | int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn, | 305 | int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn, |
296 | u8 *status); | 306 | u8 *status); |
297 | int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, | 307 | int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, |
298 | int port, struct ib_wc* in_wc, struct ib_grh* in_grh, | 308 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, |
299 | void *in_mad, void *response_mad, u8 *status); | 309 | void *in_mad, void *response_mad, u8 *status); |
300 | int mthca_READ_MGM(struct mthca_dev *dev, int index, void *mgm, | 310 | int mthca_READ_MGM(struct mthca_dev *dev, int index, |
301 | u8 *status); | 311 | struct mthca_mailbox *mailbox, u8 *status); |
302 | int mthca_WRITE_MGM(struct mthca_dev *dev, int index, void *mgm, | 312 | int mthca_WRITE_MGM(struct mthca_dev *dev, int index, |
303 | u8 *status); | 313 | struct mthca_mailbox *mailbox, u8 *status); |
304 | int mthca_MGID_HASH(struct mthca_dev *dev, void *gid, u16 *hash, | 314 | int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox, |
305 | u8 *status); | 315 | u16 *hash, u8 *status); |
306 | int mthca_NOP(struct mthca_dev *dev, u8 *status); | 316 | int mthca_NOP(struct mthca_dev *dev, u8 *status); |
307 | 317 | ||
308 | #define MAILBOX_ALIGN(x) ((void *) ALIGN((unsigned long) (x), MTHCA_CMD_MAILBOX_ALIGN)) | ||
309 | |||
310 | #endif /* MTHCA_CMD_H */ | 318 | #endif /* MTHCA_CMD_H */ |
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 2bf347b84c31..766e9031ec45 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. | 2 | * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. |
3 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -171,6 +172,17 @@ static inline void set_cqe_hw(struct mthca_cqe *cqe) | |||
171 | cqe->owner = MTHCA_CQ_ENTRY_OWNER_HW; | 172 | cqe->owner = MTHCA_CQ_ENTRY_OWNER_HW; |
172 | } | 173 | } |
173 | 174 | ||
175 | static void dump_cqe(struct mthca_dev *dev, void *cqe_ptr) | ||
176 | { | ||
177 | __be32 *cqe = cqe_ptr; | ||
178 | |||
179 | (void) cqe; /* avoid warning if mthca_dbg compiled away... */ | ||
180 | mthca_dbg(dev, "CQE contents %08x %08x %08x %08x %08x %08x %08x %08x\n", | ||
181 | be32_to_cpu(cqe[0]), be32_to_cpu(cqe[1]), be32_to_cpu(cqe[2]), | ||
182 | be32_to_cpu(cqe[3]), be32_to_cpu(cqe[4]), be32_to_cpu(cqe[5]), | ||
183 | be32_to_cpu(cqe[6]), be32_to_cpu(cqe[7])); | ||
184 | } | ||
185 | |||
174 | /* | 186 | /* |
175 | * incr is ignored in native Arbel (mem-free) mode, so cq->cons_index | 187 | * incr is ignored in native Arbel (mem-free) mode, so cq->cons_index |
176 | * should be correct before calling update_cons_index(). | 188 | * should be correct before calling update_cons_index(). |
@@ -280,16 +292,12 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, | |||
280 | int dbd; | 292 | int dbd; |
281 | u32 new_wqe; | 293 | u32 new_wqe; |
282 | 294 | ||
283 | if (1 && cqe->syndrome != SYNDROME_WR_FLUSH_ERR) { | 295 | if (cqe->syndrome == SYNDROME_LOCAL_QP_OP_ERR) { |
284 | int j; | 296 | mthca_dbg(dev, "local QP operation err " |
285 | 297 | "(QPN %06x, WQE @ %08x, CQN %06x, index %d)\n", | |
286 | mthca_dbg(dev, "%x/%d: error CQE -> QPN %06x, WQE @ %08x\n", | 298 | be32_to_cpu(cqe->my_qpn), be32_to_cpu(cqe->wqe), |
287 | cq->cqn, cq->cons_index, be32_to_cpu(cqe->my_qpn), | 299 | cq->cqn, cq->cons_index); |
288 | be32_to_cpu(cqe->wqe)); | 300 | dump_cqe(dev, cqe); |
289 | |||
290 | for (j = 0; j < 8; ++j) | ||
291 | printk(KERN_DEBUG " [%2x] %08x\n", | ||
292 | j * 4, be32_to_cpu(((u32 *) cqe)[j])); | ||
293 | } | 301 | } |
294 | 302 | ||
295 | /* | 303 | /* |
@@ -377,15 +385,6 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, | |||
377 | return 0; | 385 | return 0; |
378 | } | 386 | } |
379 | 387 | ||
380 | static void dump_cqe(struct mthca_cqe *cqe) | ||
381 | { | ||
382 | int j; | ||
383 | |||
384 | for (j = 0; j < 8; ++j) | ||
385 | printk(KERN_DEBUG " [%2x] %08x\n", | ||
386 | j * 4, be32_to_cpu(((u32 *) cqe)[j])); | ||
387 | } | ||
388 | |||
389 | static inline int mthca_poll_one(struct mthca_dev *dev, | 388 | static inline int mthca_poll_one(struct mthca_dev *dev, |
390 | struct mthca_cq *cq, | 389 | struct mthca_cq *cq, |
391 | struct mthca_qp **cur_qp, | 390 | struct mthca_qp **cur_qp, |
@@ -414,8 +413,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev, | |||
414 | mthca_dbg(dev, "%x/%d: CQE -> QPN %06x, WQE @ %08x\n", | 413 | mthca_dbg(dev, "%x/%d: CQE -> QPN %06x, WQE @ %08x\n", |
415 | cq->cqn, cq->cons_index, be32_to_cpu(cqe->my_qpn), | 414 | cq->cqn, cq->cons_index, be32_to_cpu(cqe->my_qpn), |
416 | be32_to_cpu(cqe->wqe)); | 415 | be32_to_cpu(cqe->wqe)); |
417 | 416 | dump_cqe(dev, cqe); | |
418 | dump_cqe(cqe); | ||
419 | } | 417 | } |
420 | 418 | ||
421 | is_error = (cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) == | 419 | is_error = (cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) == |
@@ -638,19 +636,19 @@ static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq) | |||
638 | int size; | 636 | int size; |
639 | 637 | ||
640 | if (cq->is_direct) | 638 | if (cq->is_direct) |
641 | pci_free_consistent(dev->pdev, | 639 | dma_free_coherent(&dev->pdev->dev, |
642 | (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE, | 640 | (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE, |
643 | cq->queue.direct.buf, | 641 | cq->queue.direct.buf, |
644 | pci_unmap_addr(&cq->queue.direct, | 642 | pci_unmap_addr(&cq->queue.direct, |
645 | mapping)); | 643 | mapping)); |
646 | else { | 644 | else { |
647 | size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE; | 645 | size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE; |
648 | for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i) | 646 | for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i) |
649 | if (cq->queue.page_list[i].buf) | 647 | if (cq->queue.page_list[i].buf) |
650 | pci_free_consistent(dev->pdev, PAGE_SIZE, | 648 | dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, |
651 | cq->queue.page_list[i].buf, | 649 | cq->queue.page_list[i].buf, |
652 | pci_unmap_addr(&cq->queue.page_list[i], | 650 | pci_unmap_addr(&cq->queue.page_list[i], |
653 | mapping)); | 651 | mapping)); |
654 | 652 | ||
655 | kfree(cq->queue.page_list); | 653 | kfree(cq->queue.page_list); |
656 | } | 654 | } |
@@ -670,8 +668,8 @@ static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size, | |||
670 | npages = 1; | 668 | npages = 1; |
671 | shift = get_order(size) + PAGE_SHIFT; | 669 | shift = get_order(size) + PAGE_SHIFT; |
672 | 670 | ||
673 | cq->queue.direct.buf = pci_alloc_consistent(dev->pdev, | 671 | cq->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev, |
674 | size, &t); | 672 | size, &t, GFP_KERNEL); |
675 | if (!cq->queue.direct.buf) | 673 | if (!cq->queue.direct.buf) |
676 | return -ENOMEM; | 674 | return -ENOMEM; |
677 | 675 | ||
@@ -709,7 +707,8 @@ static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size, | |||
709 | 707 | ||
710 | for (i = 0; i < npages; ++i) { | 708 | for (i = 0; i < npages; ++i) { |
711 | cq->queue.page_list[i].buf = | 709 | cq->queue.page_list[i].buf = |
712 | pci_alloc_consistent(dev->pdev, PAGE_SIZE, &t); | 710 | dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE, |
711 | &t, GFP_KERNEL); | ||
713 | if (!cq->queue.page_list[i].buf) | 712 | if (!cq->queue.page_list[i].buf) |
714 | goto err_free; | 713 | goto err_free; |
715 | 714 | ||
@@ -746,7 +745,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, | |||
746 | struct mthca_cq *cq) | 745 | struct mthca_cq *cq) |
747 | { | 746 | { |
748 | int size = nent * MTHCA_CQ_ENTRY_SIZE; | 747 | int size = nent * MTHCA_CQ_ENTRY_SIZE; |
749 | void *mailbox = NULL; | 748 | struct mthca_mailbox *mailbox; |
750 | struct mthca_cq_context *cq_context; | 749 | struct mthca_cq_context *cq_context; |
751 | int err = -ENOMEM; | 750 | int err = -ENOMEM; |
752 | u8 status; | 751 | u8 status; |
@@ -780,12 +779,11 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, | |||
780 | goto err_out_ci; | 779 | goto err_out_ci; |
781 | } | 780 | } |
782 | 781 | ||
783 | mailbox = kmalloc(sizeof (struct mthca_cq_context) + MTHCA_CMD_MAILBOX_EXTRA, | 782 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
784 | GFP_KERNEL); | 783 | if (IS_ERR(mailbox)) |
785 | if (!mailbox) | 784 | goto err_out_arm; |
786 | goto err_out_mailbox; | ||
787 | 785 | ||
788 | cq_context = MAILBOX_ALIGN(mailbox); | 786 | cq_context = mailbox->buf; |
789 | 787 | ||
790 | err = mthca_alloc_cq_buf(dev, size, cq); | 788 | err = mthca_alloc_cq_buf(dev, size, cq); |
791 | if (err) | 789 | if (err) |
@@ -816,7 +814,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, | |||
816 | cq_context->state_db = cpu_to_be32(cq->arm_db_index); | 814 | cq_context->state_db = cpu_to_be32(cq->arm_db_index); |
817 | } | 815 | } |
818 | 816 | ||
819 | err = mthca_SW2HW_CQ(dev, cq_context, cq->cqn, &status); | 817 | err = mthca_SW2HW_CQ(dev, mailbox, cq->cqn, &status); |
820 | if (err) { | 818 | if (err) { |
821 | mthca_warn(dev, "SW2HW_CQ failed (%d)\n", err); | 819 | mthca_warn(dev, "SW2HW_CQ failed (%d)\n", err); |
822 | goto err_out_free_mr; | 820 | goto err_out_free_mr; |
@@ -840,7 +838,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, | |||
840 | 838 | ||
841 | cq->cons_index = 0; | 839 | cq->cons_index = 0; |
842 | 840 | ||
843 | kfree(mailbox); | 841 | mthca_free_mailbox(dev, mailbox); |
844 | 842 | ||
845 | return 0; | 843 | return 0; |
846 | 844 | ||
@@ -849,8 +847,9 @@ err_out_free_mr: | |||
849 | mthca_free_cq_buf(dev, cq); | 847 | mthca_free_cq_buf(dev, cq); |
850 | 848 | ||
851 | err_out_mailbox: | 849 | err_out_mailbox: |
852 | kfree(mailbox); | 850 | mthca_free_mailbox(dev, mailbox); |
853 | 851 | ||
852 | err_out_arm: | ||
854 | if (mthca_is_memfree(dev)) | 853 | if (mthca_is_memfree(dev)) |
855 | mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index); | 854 | mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index); |
856 | 855 | ||
@@ -870,28 +869,26 @@ err_out: | |||
870 | void mthca_free_cq(struct mthca_dev *dev, | 869 | void mthca_free_cq(struct mthca_dev *dev, |
871 | struct mthca_cq *cq) | 870 | struct mthca_cq *cq) |
872 | { | 871 | { |
873 | void *mailbox; | 872 | struct mthca_mailbox *mailbox; |
874 | int err; | 873 | int err; |
875 | u8 status; | 874 | u8 status; |
876 | 875 | ||
877 | might_sleep(); | 876 | might_sleep(); |
878 | 877 | ||
879 | mailbox = kmalloc(sizeof (struct mthca_cq_context) + MTHCA_CMD_MAILBOX_EXTRA, | 878 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
880 | GFP_KERNEL); | 879 | if (IS_ERR(mailbox)) { |
881 | if (!mailbox) { | ||
882 | mthca_warn(dev, "No memory for mailbox to free CQ.\n"); | 880 | mthca_warn(dev, "No memory for mailbox to free CQ.\n"); |
883 | return; | 881 | return; |
884 | } | 882 | } |
885 | 883 | ||
886 | err = mthca_HW2SW_CQ(dev, MAILBOX_ALIGN(mailbox), cq->cqn, &status); | 884 | err = mthca_HW2SW_CQ(dev, mailbox, cq->cqn, &status); |
887 | if (err) | 885 | if (err) |
888 | mthca_warn(dev, "HW2SW_CQ failed (%d)\n", err); | 886 | mthca_warn(dev, "HW2SW_CQ failed (%d)\n", err); |
889 | else if (status) | 887 | else if (status) |
890 | mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", | 888 | mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", status); |
891 | status); | ||
892 | 889 | ||
893 | if (0) { | 890 | if (0) { |
894 | u32 *ctx = MAILBOX_ALIGN(mailbox); | 891 | u32 *ctx = mailbox->buf; |
895 | int j; | 892 | int j; |
896 | 893 | ||
897 | printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n", | 894 | printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n", |
@@ -919,11 +916,11 @@ void mthca_free_cq(struct mthca_dev *dev, | |||
919 | if (mthca_is_memfree(dev)) { | 916 | if (mthca_is_memfree(dev)) { |
920 | mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index); | 917 | mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index); |
921 | mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index); | 918 | mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index); |
922 | mthca_table_put(dev, dev->cq_table.table, cq->cqn); | ||
923 | } | 919 | } |
924 | 920 | ||
921 | mthca_table_put(dev, dev->cq_table.table, cq->cqn); | ||
925 | mthca_free(&dev->cq_table.alloc, cq->cqn); | 922 | mthca_free(&dev->cq_table.alloc, cq->cqn); |
926 | kfree(mailbox); | 923 | mthca_free_mailbox(dev, mailbox); |
927 | } | 924 | } |
928 | 925 | ||
929 | int __devinit mthca_init_cq_table(struct mthca_dev *dev) | 926 | int __devinit mthca_init_cq_table(struct mthca_dev *dev) |
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index e3d79e267dc9..4127f09dc5ec 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. | 2 | * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. |
3 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -46,8 +47,8 @@ | |||
46 | 47 | ||
47 | #define DRV_NAME "ib_mthca" | 48 | #define DRV_NAME "ib_mthca" |
48 | #define PFX DRV_NAME ": " | 49 | #define PFX DRV_NAME ": " |
49 | #define DRV_VERSION "0.06-pre" | 50 | #define DRV_VERSION "0.06" |
50 | #define DRV_RELDATE "November 8, 2004" | 51 | #define DRV_RELDATE "June 23, 2005" |
51 | 52 | ||
52 | enum { | 53 | enum { |
53 | MTHCA_FLAG_DDR_HIDDEN = 1 << 1, | 54 | MTHCA_FLAG_DDR_HIDDEN = 1 << 1, |
@@ -98,6 +99,7 @@ enum { | |||
98 | }; | 99 | }; |
99 | 100 | ||
100 | struct mthca_cmd { | 101 | struct mthca_cmd { |
102 | struct pci_pool *pool; | ||
101 | int use_events; | 103 | int use_events; |
102 | struct semaphore hcr_sem; | 104 | struct semaphore hcr_sem; |
103 | struct semaphore poll_sem; | 105 | struct semaphore poll_sem; |
@@ -379,6 +381,12 @@ void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar); | |||
379 | int mthca_pd_alloc(struct mthca_dev *dev, struct mthca_pd *pd); | 381 | int mthca_pd_alloc(struct mthca_dev *dev, struct mthca_pd *pd); |
380 | void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd); | 382 | void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd); |
381 | 383 | ||
384 | struct mthca_mtt *mthca_alloc_mtt(struct mthca_dev *dev, int size); | ||
385 | void mthca_free_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt); | ||
386 | int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt, | ||
387 | int start_index, u64 *buffer_list, int list_len); | ||
388 | int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, | ||
389 | u64 iova, u64 total_size, u32 access, struct mthca_mr *mr); | ||
382 | int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd, | 390 | int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd, |
383 | u32 access, struct mthca_mr *mr); | 391 | u32 access, struct mthca_mr *mr); |
384 | int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd, | 392 | int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd, |
diff --git a/drivers/infiniband/hw/mthca/mthca_doorbell.h b/drivers/infiniband/hw/mthca/mthca_doorbell.h index 821039a49049..535fad7710fb 100644 --- a/drivers/infiniband/hw/mthca/mthca_doorbell.h +++ b/drivers/infiniband/hw/mthca/mthca_doorbell.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 Topspin Communications. All rights reserved. | 2 | * Copyright (c) 2004 Topspin Communications. All rights reserved. |
3 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index f46d615d396f..cbcf2b4722e4 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c | |||
@@ -469,7 +469,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
469 | PAGE_SIZE; | 469 | PAGE_SIZE; |
470 | u64 *dma_list = NULL; | 470 | u64 *dma_list = NULL; |
471 | dma_addr_t t; | 471 | dma_addr_t t; |
472 | void *mailbox = NULL; | 472 | struct mthca_mailbox *mailbox; |
473 | struct mthca_eq_context *eq_context; | 473 | struct mthca_eq_context *eq_context; |
474 | int err = -ENOMEM; | 474 | int err = -ENOMEM; |
475 | int i; | 475 | int i; |
@@ -494,17 +494,16 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
494 | if (!dma_list) | 494 | if (!dma_list) |
495 | goto err_out_free; | 495 | goto err_out_free; |
496 | 496 | ||
497 | mailbox = kmalloc(sizeof *eq_context + MTHCA_CMD_MAILBOX_EXTRA, | 497 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
498 | GFP_KERNEL); | 498 | if (IS_ERR(mailbox)) |
499 | if (!mailbox) | ||
500 | goto err_out_free; | 499 | goto err_out_free; |
501 | eq_context = MAILBOX_ALIGN(mailbox); | 500 | eq_context = mailbox->buf; |
502 | 501 | ||
503 | for (i = 0; i < npages; ++i) { | 502 | for (i = 0; i < npages; ++i) { |
504 | eq->page_list[i].buf = pci_alloc_consistent(dev->pdev, | 503 | eq->page_list[i].buf = dma_alloc_coherent(&dev->pdev->dev, |
505 | PAGE_SIZE, &t); | 504 | PAGE_SIZE, &t, GFP_KERNEL); |
506 | if (!eq->page_list[i].buf) | 505 | if (!eq->page_list[i].buf) |
507 | goto err_out_free; | 506 | goto err_out_free_pages; |
508 | 507 | ||
509 | dma_list[i] = t; | 508 | dma_list[i] = t; |
510 | pci_unmap_addr_set(&eq->page_list[i], mapping, t); | 509 | pci_unmap_addr_set(&eq->page_list[i], mapping, t); |
@@ -517,7 +516,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
517 | 516 | ||
518 | eq->eqn = mthca_alloc(&dev->eq_table.alloc); | 517 | eq->eqn = mthca_alloc(&dev->eq_table.alloc); |
519 | if (eq->eqn == -1) | 518 | if (eq->eqn == -1) |
520 | goto err_out_free; | 519 | goto err_out_free_pages; |
521 | 520 | ||
522 | err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num, | 521 | err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num, |
523 | dma_list, PAGE_SHIFT, npages, | 522 | dma_list, PAGE_SHIFT, npages, |
@@ -548,7 +547,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
548 | eq_context->intr = intr; | 547 | eq_context->intr = intr; |
549 | eq_context->lkey = cpu_to_be32(eq->mr.ibmr.lkey); | 548 | eq_context->lkey = cpu_to_be32(eq->mr.ibmr.lkey); |
550 | 549 | ||
551 | err = mthca_SW2HW_EQ(dev, eq_context, eq->eqn, &status); | 550 | err = mthca_SW2HW_EQ(dev, mailbox, eq->eqn, &status); |
552 | if (err) { | 551 | if (err) { |
553 | mthca_warn(dev, "SW2HW_EQ failed (%d)\n", err); | 552 | mthca_warn(dev, "SW2HW_EQ failed (%d)\n", err); |
554 | goto err_out_free_mr; | 553 | goto err_out_free_mr; |
@@ -561,7 +560,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
561 | } | 560 | } |
562 | 561 | ||
563 | kfree(dma_list); | 562 | kfree(dma_list); |
564 | kfree(mailbox); | 563 | mthca_free_mailbox(dev, mailbox); |
565 | 564 | ||
566 | eq->eqn_mask = swab32(1 << eq->eqn); | 565 | eq->eqn_mask = swab32(1 << eq->eqn); |
567 | eq->cons_index = 0; | 566 | eq->cons_index = 0; |
@@ -579,17 +578,19 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
579 | err_out_free_eq: | 578 | err_out_free_eq: |
580 | mthca_free(&dev->eq_table.alloc, eq->eqn); | 579 | mthca_free(&dev->eq_table.alloc, eq->eqn); |
581 | 580 | ||
582 | err_out_free: | 581 | err_out_free_pages: |
583 | for (i = 0; i < npages; ++i) | 582 | for (i = 0; i < npages; ++i) |
584 | if (eq->page_list[i].buf) | 583 | if (eq->page_list[i].buf) |
585 | pci_free_consistent(dev->pdev, PAGE_SIZE, | 584 | dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, |
586 | eq->page_list[i].buf, | 585 | eq->page_list[i].buf, |
587 | pci_unmap_addr(&eq->page_list[i], | 586 | pci_unmap_addr(&eq->page_list[i], |
588 | mapping)); | 587 | mapping)); |
588 | |||
589 | mthca_free_mailbox(dev, mailbox); | ||
589 | 590 | ||
591 | err_out_free: | ||
590 | kfree(eq->page_list); | 592 | kfree(eq->page_list); |
591 | kfree(dma_list); | 593 | kfree(dma_list); |
592 | kfree(mailbox); | ||
593 | 594 | ||
594 | err_out: | 595 | err_out: |
595 | return err; | 596 | return err; |
@@ -598,25 +599,22 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
598 | static void mthca_free_eq(struct mthca_dev *dev, | 599 | static void mthca_free_eq(struct mthca_dev *dev, |
599 | struct mthca_eq *eq) | 600 | struct mthca_eq *eq) |
600 | { | 601 | { |
601 | void *mailbox = NULL; | 602 | struct mthca_mailbox *mailbox; |
602 | int err; | 603 | int err; |
603 | u8 status; | 604 | u8 status; |
604 | int npages = (eq->nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) / | 605 | int npages = (eq->nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) / |
605 | PAGE_SIZE; | 606 | PAGE_SIZE; |
606 | int i; | 607 | int i; |
607 | 608 | ||
608 | mailbox = kmalloc(sizeof (struct mthca_eq_context) + MTHCA_CMD_MAILBOX_EXTRA, | 609 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
609 | GFP_KERNEL); | 610 | if (IS_ERR(mailbox)) |
610 | if (!mailbox) | ||
611 | return; | 611 | return; |
612 | 612 | ||
613 | err = mthca_HW2SW_EQ(dev, MAILBOX_ALIGN(mailbox), | 613 | err = mthca_HW2SW_EQ(dev, mailbox, eq->eqn, &status); |
614 | eq->eqn, &status); | ||
615 | if (err) | 614 | if (err) |
616 | mthca_warn(dev, "HW2SW_EQ failed (%d)\n", err); | 615 | mthca_warn(dev, "HW2SW_EQ failed (%d)\n", err); |
617 | if (status) | 616 | if (status) |
618 | mthca_warn(dev, "HW2SW_EQ returned status 0x%02x\n", | 617 | mthca_warn(dev, "HW2SW_EQ returned status 0x%02x\n", status); |
619 | status); | ||
620 | 618 | ||
621 | dev->eq_table.arm_mask &= ~eq->eqn_mask; | 619 | dev->eq_table.arm_mask &= ~eq->eqn_mask; |
622 | 620 | ||
@@ -625,7 +623,7 @@ static void mthca_free_eq(struct mthca_dev *dev, | |||
625 | for (i = 0; i < sizeof (struct mthca_eq_context) / 4; ++i) { | 623 | for (i = 0; i < sizeof (struct mthca_eq_context) / 4; ++i) { |
626 | if (i % 4 == 0) | 624 | if (i % 4 == 0) |
627 | printk("[%02x] ", i * 4); | 625 | printk("[%02x] ", i * 4); |
628 | printk(" %08x", be32_to_cpup(MAILBOX_ALIGN(mailbox) + i * 4)); | 626 | printk(" %08x", be32_to_cpup(mailbox->buf + i * 4)); |
629 | if ((i + 1) % 4 == 0) | 627 | if ((i + 1) % 4 == 0) |
630 | printk("\n"); | 628 | printk("\n"); |
631 | } | 629 | } |
@@ -638,7 +636,7 @@ static void mthca_free_eq(struct mthca_dev *dev, | |||
638 | pci_unmap_addr(&eq->page_list[i], mapping)); | 636 | pci_unmap_addr(&eq->page_list[i], mapping)); |
639 | 637 | ||
640 | kfree(eq->page_list); | 638 | kfree(eq->page_list); |
641 | kfree(mailbox); | 639 | mthca_free_mailbox(dev, mailbox); |
642 | } | 640 | } |
643 | 641 | ||
644 | static void mthca_free_irqs(struct mthca_dev *dev) | 642 | static void mthca_free_irqs(struct mthca_dev *dev) |
@@ -709,8 +707,7 @@ static int __devinit mthca_map_eq_regs(struct mthca_dev *dev) | |||
709 | if (mthca_map_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) & | 707 | if (mthca_map_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) & |
710 | dev->fw.arbel.eq_arm_base) + 4, 4, | 708 | dev->fw.arbel.eq_arm_base) + 4, 4, |
711 | &dev->eq_regs.arbel.eq_arm)) { | 709 | &dev->eq_regs.arbel.eq_arm)) { |
712 | mthca_err(dev, "Couldn't map interrupt clear register, " | 710 | mthca_err(dev, "Couldn't map EQ arm register, aborting.\n"); |
713 | "aborting.\n"); | ||
714 | mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & | 711 | mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & |
715 | dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE, | 712 | dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE, |
716 | dev->clr_base); | 713 | dev->clr_base); |
@@ -721,8 +718,7 @@ static int __devinit mthca_map_eq_regs(struct mthca_dev *dev) | |||
721 | dev->fw.arbel.eq_set_ci_base, | 718 | dev->fw.arbel.eq_set_ci_base, |
722 | MTHCA_EQ_SET_CI_SIZE, | 719 | MTHCA_EQ_SET_CI_SIZE, |
723 | &dev->eq_regs.arbel.eq_set_ci_base)) { | 720 | &dev->eq_regs.arbel.eq_set_ci_base)) { |
724 | mthca_err(dev, "Couldn't map interrupt clear register, " | 721 | mthca_err(dev, "Couldn't map EQ CI register, aborting.\n"); |
725 | "aborting.\n"); | ||
726 | mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) & | 722 | mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) & |
727 | dev->fw.arbel.eq_arm_base) + 4, 4, | 723 | dev->fw.arbel.eq_arm_base) + 4, 4, |
728 | dev->eq_regs.arbel.eq_arm); | 724 | dev->eq_regs.arbel.eq_arm); |
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index d40590356df8..09519b604c08 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. | 2 | * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. |
3 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -69,7 +70,7 @@ MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero"); | |||
69 | #endif /* CONFIG_PCI_MSI */ | 70 | #endif /* CONFIG_PCI_MSI */ |
70 | 71 | ||
71 | static const char mthca_version[] __devinitdata = | 72 | static const char mthca_version[] __devinitdata = |
72 | "ib_mthca: Mellanox InfiniBand HCA driver v" | 73 | DRV_NAME ": Mellanox InfiniBand HCA driver v" |
73 | DRV_VERSION " (" DRV_RELDATE ")\n"; | 74 | DRV_VERSION " (" DRV_RELDATE ")\n"; |
74 | 75 | ||
75 | static struct mthca_profile default_profile = { | 76 | static struct mthca_profile default_profile = { |
@@ -927,13 +928,13 @@ static int __devinit mthca_init_one(struct pci_dev *pdev, | |||
927 | */ | 928 | */ |
928 | if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || | 929 | if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || |
929 | pci_resource_len(pdev, 0) != 1 << 20) { | 930 | pci_resource_len(pdev, 0) != 1 << 20) { |
930 | dev_err(&pdev->dev, "Missing DCS, aborting."); | 931 | dev_err(&pdev->dev, "Missing DCS, aborting.\n"); |
931 | err = -ENODEV; | 932 | err = -ENODEV; |
932 | goto err_disable_pdev; | 933 | goto err_disable_pdev; |
933 | } | 934 | } |
934 | if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM) || | 935 | if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM) || |
935 | pci_resource_len(pdev, 2) != 1 << 23) { | 936 | pci_resource_len(pdev, 2) != 1 << 23) { |
936 | dev_err(&pdev->dev, "Missing UAR, aborting."); | 937 | dev_err(&pdev->dev, "Missing UAR, aborting.\n"); |
937 | err = -ENODEV; | 938 | err = -ENODEV; |
938 | goto err_disable_pdev; | 939 | goto err_disable_pdev; |
939 | } | 940 | } |
@@ -1004,25 +1005,18 @@ static int __devinit mthca_init_one(struct pci_dev *pdev, | |||
1004 | !pci_enable_msi(pdev)) | 1005 | !pci_enable_msi(pdev)) |
1005 | mdev->mthca_flags |= MTHCA_FLAG_MSI; | 1006 | mdev->mthca_flags |= MTHCA_FLAG_MSI; |
1006 | 1007 | ||
1007 | sema_init(&mdev->cmd.hcr_sem, 1); | 1008 | if (mthca_cmd_init(mdev)) { |
1008 | sema_init(&mdev->cmd.poll_sem, 1); | 1009 | mthca_err(mdev, "Failed to init command interface, aborting.\n"); |
1009 | mdev->cmd.use_events = 0; | ||
1010 | |||
1011 | mdev->hcr = ioremap(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, MTHCA_HCR_SIZE); | ||
1012 | if (!mdev->hcr) { | ||
1013 | mthca_err(mdev, "Couldn't map command register, " | ||
1014 | "aborting.\n"); | ||
1015 | err = -ENOMEM; | ||
1016 | goto err_free_dev; | 1010 | goto err_free_dev; |
1017 | } | 1011 | } |
1018 | 1012 | ||
1019 | err = mthca_tune_pci(mdev); | 1013 | err = mthca_tune_pci(mdev); |
1020 | if (err) | 1014 | if (err) |
1021 | goto err_iounmap; | 1015 | goto err_cmd; |
1022 | 1016 | ||
1023 | err = mthca_init_hca(mdev); | 1017 | err = mthca_init_hca(mdev); |
1024 | if (err) | 1018 | if (err) |
1025 | goto err_iounmap; | 1019 | goto err_cmd; |
1026 | 1020 | ||
1027 | if (mdev->fw_ver < mthca_hca_table[id->driver_data].latest_fw) { | 1021 | if (mdev->fw_ver < mthca_hca_table[id->driver_data].latest_fw) { |
1028 | mthca_warn(mdev, "HCA FW version %x.%x.%x is old (%x.%x.%x is current).\n", | 1022 | mthca_warn(mdev, "HCA FW version %x.%x.%x is old (%x.%x.%x is current).\n", |
@@ -1070,8 +1064,8 @@ err_cleanup: | |||
1070 | err_close: | 1064 | err_close: |
1071 | mthca_close_hca(mdev); | 1065 | mthca_close_hca(mdev); |
1072 | 1066 | ||
1073 | err_iounmap: | 1067 | err_cmd: |
1074 | iounmap(mdev->hcr); | 1068 | mthca_cmd_cleanup(mdev); |
1075 | 1069 | ||
1076 | err_free_dev: | 1070 | err_free_dev: |
1077 | if (mdev->mthca_flags & MTHCA_FLAG_MSI_X) | 1071 | if (mdev->mthca_flags & MTHCA_FLAG_MSI_X) |
@@ -1118,10 +1112,8 @@ static void __devexit mthca_remove_one(struct pci_dev *pdev) | |||
1118 | iounmap(mdev->kar); | 1112 | iounmap(mdev->kar); |
1119 | mthca_uar_free(mdev, &mdev->driver_uar); | 1113 | mthca_uar_free(mdev, &mdev->driver_uar); |
1120 | mthca_cleanup_uar_table(mdev); | 1114 | mthca_cleanup_uar_table(mdev); |
1121 | |||
1122 | mthca_close_hca(mdev); | 1115 | mthca_close_hca(mdev); |
1123 | 1116 | mthca_cmd_cleanup(mdev); | |
1124 | iounmap(mdev->hcr); | ||
1125 | 1117 | ||
1126 | if (mdev->mthca_flags & MTHCA_FLAG_MSI_X) | 1118 | if (mdev->mthca_flags & MTHCA_FLAG_MSI_X) |
1127 | pci_disable_msix(pdev); | 1119 | pci_disable_msix(pdev); |
@@ -1163,7 +1155,7 @@ static struct pci_device_id mthca_pci_table[] = { | |||
1163 | MODULE_DEVICE_TABLE(pci, mthca_pci_table); | 1155 | MODULE_DEVICE_TABLE(pci, mthca_pci_table); |
1164 | 1156 | ||
1165 | static struct pci_driver mthca_driver = { | 1157 | static struct pci_driver mthca_driver = { |
1166 | .name = "ib_mthca", | 1158 | .name = DRV_NAME, |
1167 | .id_table = mthca_pci_table, | 1159 | .id_table = mthca_pci_table, |
1168 | .probe = mthca_init_one, | 1160 | .probe = mthca_init_one, |
1169 | .remove = __devexit_p(mthca_remove_one) | 1161 | .remove = __devexit_p(mthca_remove_one) |
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 70a6553a588e..5be7d949dbf6 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c | |||
@@ -66,22 +66,23 @@ static const u8 zero_gid[16]; /* automatically initialized to 0 */ | |||
66 | * entry in hash chain and *mgm holds end of hash chain. | 66 | * entry in hash chain and *mgm holds end of hash chain. |
67 | */ | 67 | */ |
68 | static int find_mgm(struct mthca_dev *dev, | 68 | static int find_mgm(struct mthca_dev *dev, |
69 | u8 *gid, struct mthca_mgm *mgm, | 69 | u8 *gid, struct mthca_mailbox *mgm_mailbox, |
70 | u16 *hash, int *prev, int *index) | 70 | u16 *hash, int *prev, int *index) |
71 | { | 71 | { |
72 | void *mailbox; | 72 | struct mthca_mailbox *mailbox; |
73 | struct mthca_mgm *mgm = mgm_mailbox->buf; | ||
73 | u8 *mgid; | 74 | u8 *mgid; |
74 | int err; | 75 | int err; |
75 | u8 status; | 76 | u8 status; |
76 | 77 | ||
77 | mailbox = kmalloc(16 + MTHCA_CMD_MAILBOX_EXTRA, GFP_KERNEL); | 78 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
78 | if (!mailbox) | 79 | if (IS_ERR(mailbox)) |
79 | return -ENOMEM; | 80 | return -ENOMEM; |
80 | mgid = MAILBOX_ALIGN(mailbox); | 81 | mgid = mailbox->buf; |
81 | 82 | ||
82 | memcpy(mgid, gid, 16); | 83 | memcpy(mgid, gid, 16); |
83 | 84 | ||
84 | err = mthca_MGID_HASH(dev, mgid, hash, &status); | 85 | err = mthca_MGID_HASH(dev, mailbox, hash, &status); |
85 | if (err) | 86 | if (err) |
86 | goto out; | 87 | goto out; |
87 | if (status) { | 88 | if (status) { |
@@ -103,7 +104,7 @@ static int find_mgm(struct mthca_dev *dev, | |||
103 | *prev = -1; | 104 | *prev = -1; |
104 | 105 | ||
105 | do { | 106 | do { |
106 | err = mthca_READ_MGM(dev, *index, mgm, &status); | 107 | err = mthca_READ_MGM(dev, *index, mgm_mailbox, &status); |
107 | if (err) | 108 | if (err) |
108 | goto out; | 109 | goto out; |
109 | if (status) { | 110 | if (status) { |
@@ -129,14 +130,14 @@ static int find_mgm(struct mthca_dev *dev, | |||
129 | *index = -1; | 130 | *index = -1; |
130 | 131 | ||
131 | out: | 132 | out: |
132 | kfree(mailbox); | 133 | mthca_free_mailbox(dev, mailbox); |
133 | return err; | 134 | return err; |
134 | } | 135 | } |
135 | 136 | ||
136 | int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | 137 | int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) |
137 | { | 138 | { |
138 | struct mthca_dev *dev = to_mdev(ibqp->device); | 139 | struct mthca_dev *dev = to_mdev(ibqp->device); |
139 | void *mailbox; | 140 | struct mthca_mailbox *mailbox; |
140 | struct mthca_mgm *mgm; | 141 | struct mthca_mgm *mgm; |
141 | u16 hash; | 142 | u16 hash; |
142 | int index, prev; | 143 | int index, prev; |
@@ -145,15 +146,15 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
145 | int err; | 146 | int err; |
146 | u8 status; | 147 | u8 status; |
147 | 148 | ||
148 | mailbox = kmalloc(sizeof *mgm + MTHCA_CMD_MAILBOX_EXTRA, GFP_KERNEL); | 149 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
149 | if (!mailbox) | 150 | if (IS_ERR(mailbox)) |
150 | return -ENOMEM; | 151 | return PTR_ERR(mailbox); |
151 | mgm = MAILBOX_ALIGN(mailbox); | 152 | mgm = mailbox->buf; |
152 | 153 | ||
153 | if (down_interruptible(&dev->mcg_table.sem)) | 154 | if (down_interruptible(&dev->mcg_table.sem)) |
154 | return -EINTR; | 155 | return -EINTR; |
155 | 156 | ||
156 | err = find_mgm(dev, gid->raw, mgm, &hash, &prev, &index); | 157 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); |
157 | if (err) | 158 | if (err) |
158 | goto out; | 159 | goto out; |
159 | 160 | ||
@@ -170,7 +171,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
170 | goto out; | 171 | goto out; |
171 | } | 172 | } |
172 | 173 | ||
173 | err = mthca_READ_MGM(dev, index, mgm, &status); | 174 | err = mthca_READ_MGM(dev, index, mailbox, &status); |
174 | if (err) | 175 | if (err) |
175 | goto out; | 176 | goto out; |
176 | if (status) { | 177 | if (status) { |
@@ -195,7 +196,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
195 | goto out; | 196 | goto out; |
196 | } | 197 | } |
197 | 198 | ||
198 | err = mthca_WRITE_MGM(dev, index, mgm, &status); | 199 | err = mthca_WRITE_MGM(dev, index, mailbox, &status); |
199 | if (err) | 200 | if (err) |
200 | goto out; | 201 | goto out; |
201 | if (status) { | 202 | if (status) { |
@@ -206,7 +207,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
206 | if (!link) | 207 | if (!link) |
207 | goto out; | 208 | goto out; |
208 | 209 | ||
209 | err = mthca_READ_MGM(dev, prev, mgm, &status); | 210 | err = mthca_READ_MGM(dev, prev, mailbox, &status); |
210 | if (err) | 211 | if (err) |
211 | goto out; | 212 | goto out; |
212 | if (status) { | 213 | if (status) { |
@@ -217,7 +218,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
217 | 218 | ||
218 | mgm->next_gid_index = cpu_to_be32(index << 5); | 219 | mgm->next_gid_index = cpu_to_be32(index << 5); |
219 | 220 | ||
220 | err = mthca_WRITE_MGM(dev, prev, mgm, &status); | 221 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); |
221 | if (err) | 222 | if (err) |
222 | goto out; | 223 | goto out; |
223 | if (status) { | 224 | if (status) { |
@@ -227,14 +228,14 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
227 | 228 | ||
228 | out: | 229 | out: |
229 | up(&dev->mcg_table.sem); | 230 | up(&dev->mcg_table.sem); |
230 | kfree(mailbox); | 231 | mthca_free_mailbox(dev, mailbox); |
231 | return err; | 232 | return err; |
232 | } | 233 | } |
233 | 234 | ||
234 | int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | 235 | int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) |
235 | { | 236 | { |
236 | struct mthca_dev *dev = to_mdev(ibqp->device); | 237 | struct mthca_dev *dev = to_mdev(ibqp->device); |
237 | void *mailbox; | 238 | struct mthca_mailbox *mailbox; |
238 | struct mthca_mgm *mgm; | 239 | struct mthca_mgm *mgm; |
239 | u16 hash; | 240 | u16 hash; |
240 | int prev, index; | 241 | int prev, index; |
@@ -242,15 +243,15 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
242 | int err; | 243 | int err; |
243 | u8 status; | 244 | u8 status; |
244 | 245 | ||
245 | mailbox = kmalloc(sizeof *mgm + MTHCA_CMD_MAILBOX_EXTRA, GFP_KERNEL); | 246 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
246 | if (!mailbox) | 247 | if (IS_ERR(mailbox)) |
247 | return -ENOMEM; | 248 | return PTR_ERR(mailbox); |
248 | mgm = MAILBOX_ALIGN(mailbox); | 249 | mgm = mailbox->buf; |
249 | 250 | ||
250 | if (down_interruptible(&dev->mcg_table.sem)) | 251 | if (down_interruptible(&dev->mcg_table.sem)) |
251 | return -EINTR; | 252 | return -EINTR; |
252 | 253 | ||
253 | err = find_mgm(dev, gid->raw, mgm, &hash, &prev, &index); | 254 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); |
254 | if (err) | 255 | if (err) |
255 | goto out; | 256 | goto out; |
256 | 257 | ||
@@ -285,7 +286,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
285 | mgm->qp[loc] = mgm->qp[i - 1]; | 286 | mgm->qp[loc] = mgm->qp[i - 1]; |
286 | mgm->qp[i - 1] = 0; | 287 | mgm->qp[i - 1] = 0; |
287 | 288 | ||
288 | err = mthca_WRITE_MGM(dev, index, mgm, &status); | 289 | err = mthca_WRITE_MGM(dev, index, mailbox, &status); |
289 | if (err) | 290 | if (err) |
290 | goto out; | 291 | goto out; |
291 | if (status) { | 292 | if (status) { |
@@ -304,7 +305,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
304 | if (be32_to_cpu(mgm->next_gid_index) >> 5) { | 305 | if (be32_to_cpu(mgm->next_gid_index) >> 5) { |
305 | err = mthca_READ_MGM(dev, | 306 | err = mthca_READ_MGM(dev, |
306 | be32_to_cpu(mgm->next_gid_index) >> 5, | 307 | be32_to_cpu(mgm->next_gid_index) >> 5, |
307 | mgm, &status); | 308 | mailbox, &status); |
308 | if (err) | 309 | if (err) |
309 | goto out; | 310 | goto out; |
310 | if (status) { | 311 | if (status) { |
@@ -316,7 +317,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
316 | } else | 317 | } else |
317 | memset(mgm->gid, 0, 16); | 318 | memset(mgm->gid, 0, 16); |
318 | 319 | ||
319 | err = mthca_WRITE_MGM(dev, index, mgm, &status); | 320 | err = mthca_WRITE_MGM(dev, index, mailbox, &status); |
320 | if (err) | 321 | if (err) |
321 | goto out; | 322 | goto out; |
322 | if (status) { | 323 | if (status) { |
@@ -327,7 +328,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
327 | } else { | 328 | } else { |
328 | /* Remove entry from AMGM */ | 329 | /* Remove entry from AMGM */ |
329 | index = be32_to_cpu(mgm->next_gid_index) >> 5; | 330 | index = be32_to_cpu(mgm->next_gid_index) >> 5; |
330 | err = mthca_READ_MGM(dev, prev, mgm, &status); | 331 | err = mthca_READ_MGM(dev, prev, mailbox, &status); |
331 | if (err) | 332 | if (err) |
332 | goto out; | 333 | goto out; |
333 | if (status) { | 334 | if (status) { |
@@ -338,7 +339,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
338 | 339 | ||
339 | mgm->next_gid_index = cpu_to_be32(index << 5); | 340 | mgm->next_gid_index = cpu_to_be32(index << 5); |
340 | 341 | ||
341 | err = mthca_WRITE_MGM(dev, prev, mgm, &status); | 342 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); |
342 | if (err) | 343 | if (err) |
343 | goto out; | 344 | goto out; |
344 | if (status) { | 345 | if (status) { |
@@ -350,7 +351,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
350 | 351 | ||
351 | out: | 352 | out: |
352 | up(&dev->mcg_table.sem); | 353 | up(&dev->mcg_table.sem); |
353 | kfree(mailbox); | 354 | mthca_free_mailbox(dev, mailbox); |
354 | return err; | 355 | return err; |
355 | } | 356 | } |
356 | 357 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index 637b30e35592..6d3b05dd9e3f 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c | |||
@@ -179,9 +179,14 @@ out: | |||
179 | 179 | ||
180 | void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj) | 180 | void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj) |
181 | { | 181 | { |
182 | int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE; | 182 | int i; |
183 | u8 status; | 183 | u8 status; |
184 | 184 | ||
185 | if (!mthca_is_memfree(dev)) | ||
186 | return; | ||
187 | |||
188 | i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE; | ||
189 | |||
185 | down(&table->mutex); | 190 | down(&table->mutex); |
186 | 191 | ||
187 | if (--table->icm[i]->refcount == 0) { | 192 | if (--table->icm[i]->refcount == 0) { |
@@ -256,6 +261,9 @@ void mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table, | |||
256 | { | 261 | { |
257 | int i; | 262 | int i; |
258 | 263 | ||
264 | if (!mthca_is_memfree(dev)) | ||
265 | return; | ||
266 | |||
259 | for (i = start; i <= end; i += MTHCA_TABLE_CHUNK_SIZE / table->obj_size) | 267 | for (i = start; i <= end; i += MTHCA_TABLE_CHUNK_SIZE / table->obj_size) |
260 | mthca_table_put(dev, table, i); | 268 | mthca_table_put(dev, table, i); |
261 | } | 269 | } |
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 8960fc2306be..cbe50feaf680 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c | |||
@@ -40,6 +40,12 @@ | |||
40 | #include "mthca_cmd.h" | 40 | #include "mthca_cmd.h" |
41 | #include "mthca_memfree.h" | 41 | #include "mthca_memfree.h" |
42 | 42 | ||
43 | struct mthca_mtt { | ||
44 | struct mthca_buddy *buddy; | ||
45 | int order; | ||
46 | u32 first_seg; | ||
47 | }; | ||
48 | |||
43 | /* | 49 | /* |
44 | * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. | 50 | * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. |
45 | */ | 51 | */ |
@@ -173,8 +179,8 @@ static void __devexit mthca_buddy_cleanup(struct mthca_buddy *buddy) | |||
173 | kfree(buddy->bits); | 179 | kfree(buddy->bits); |
174 | } | 180 | } |
175 | 181 | ||
176 | static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order, | 182 | static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order, |
177 | struct mthca_buddy *buddy) | 183 | struct mthca_buddy *buddy) |
178 | { | 184 | { |
179 | u32 seg = mthca_buddy_alloc(buddy, order); | 185 | u32 seg = mthca_buddy_alloc(buddy, order); |
180 | 186 | ||
@@ -191,14 +197,102 @@ static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order, | |||
191 | return seg; | 197 | return seg; |
192 | } | 198 | } |
193 | 199 | ||
194 | static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order, | 200 | static struct mthca_mtt *__mthca_alloc_mtt(struct mthca_dev *dev, int size, |
195 | struct mthca_buddy* buddy) | 201 | struct mthca_buddy *buddy) |
196 | { | 202 | { |
197 | mthca_buddy_free(buddy, seg, order); | 203 | struct mthca_mtt *mtt; |
204 | int i; | ||
198 | 205 | ||
199 | if (mthca_is_memfree(dev)) | 206 | if (size <= 0) |
200 | mthca_table_put_range(dev, dev->mr_table.mtt_table, seg, | 207 | return ERR_PTR(-EINVAL); |
201 | seg + (1 << order) - 1); | 208 | |
209 | mtt = kmalloc(sizeof *mtt, GFP_KERNEL); | ||
210 | if (!mtt) | ||
211 | return ERR_PTR(-ENOMEM); | ||
212 | |||
213 | mtt->buddy = buddy; | ||
214 | mtt->order = 0; | ||
215 | for (i = MTHCA_MTT_SEG_SIZE / 8; i < size; i <<= 1) | ||
216 | ++mtt->order; | ||
217 | |||
218 | mtt->first_seg = mthca_alloc_mtt_range(dev, mtt->order, buddy); | ||
219 | if (mtt->first_seg == -1) { | ||
220 | kfree(mtt); | ||
221 | return ERR_PTR(-ENOMEM); | ||
222 | } | ||
223 | |||
224 | return mtt; | ||
225 | } | ||
226 | |||
227 | struct mthca_mtt *mthca_alloc_mtt(struct mthca_dev *dev, int size) | ||
228 | { | ||
229 | return __mthca_alloc_mtt(dev, size, &dev->mr_table.mtt_buddy); | ||
230 | } | ||
231 | |||
232 | void mthca_free_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt) | ||
233 | { | ||
234 | if (!mtt) | ||
235 | return; | ||
236 | |||
237 | mthca_buddy_free(mtt->buddy, mtt->first_seg, mtt->order); | ||
238 | |||
239 | mthca_table_put_range(dev, dev->mr_table.mtt_table, | ||
240 | mtt->first_seg, | ||
241 | mtt->first_seg + (1 << mtt->order) - 1); | ||
242 | |||
243 | kfree(mtt); | ||
244 | } | ||
245 | |||
246 | int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt, | ||
247 | int start_index, u64 *buffer_list, int list_len) | ||
248 | { | ||
249 | struct mthca_mailbox *mailbox; | ||
250 | u64 *mtt_entry; | ||
251 | int err = 0; | ||
252 | u8 status; | ||
253 | int i; | ||
254 | |||
255 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); | ||
256 | if (IS_ERR(mailbox)) | ||
257 | return PTR_ERR(mailbox); | ||
258 | mtt_entry = mailbox->buf; | ||
259 | |||
260 | while (list_len > 0) { | ||
261 | mtt_entry[0] = cpu_to_be64(dev->mr_table.mtt_base + | ||
262 | mtt->first_seg * MTHCA_MTT_SEG_SIZE + | ||
263 | start_index * 8); | ||
264 | mtt_entry[1] = 0; | ||
265 | for (i = 0; i < list_len && i < MTHCA_MAILBOX_SIZE / 8 - 2; ++i) | ||
266 | mtt_entry[i + 2] = cpu_to_be64(buffer_list[i] | | ||
267 | MTHCA_MTT_FLAG_PRESENT); | ||
268 | |||
269 | /* | ||
270 | * If we have an odd number of entries to write, add | ||
271 | * one more dummy entry for firmware efficiency. | ||
272 | */ | ||
273 | if (i & 1) | ||
274 | mtt_entry[i + 2] = 0; | ||
275 | |||
276 | err = mthca_WRITE_MTT(dev, mailbox, (i + 1) & ~1, &status); | ||
277 | if (err) { | ||
278 | mthca_warn(dev, "WRITE_MTT failed (%d)\n", err); | ||
279 | goto out; | ||
280 | } | ||
281 | if (status) { | ||
282 | mthca_warn(dev, "WRITE_MTT returned status 0x%02x\n", | ||
283 | status); | ||
284 | err = -EINVAL; | ||
285 | goto out; | ||
286 | } | ||
287 | |||
288 | list_len -= i; | ||
289 | start_index += i; | ||
290 | buffer_list += i; | ||
291 | } | ||
292 | |||
293 | out: | ||
294 | mthca_free_mailbox(dev, mailbox); | ||
295 | return err; | ||
202 | } | 296 | } |
203 | 297 | ||
204 | static inline u32 tavor_hw_index_to_key(u32 ind) | 298 | static inline u32 tavor_hw_index_to_key(u32 ind) |
@@ -237,91 +331,18 @@ static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key) | |||
237 | return tavor_key_to_hw_index(key); | 331 | return tavor_key_to_hw_index(key); |
238 | } | 332 | } |
239 | 333 | ||
240 | int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd, | 334 | int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, |
241 | u32 access, struct mthca_mr *mr) | 335 | u64 iova, u64 total_size, u32 access, struct mthca_mr *mr) |
242 | { | 336 | { |
243 | void *mailbox = NULL; | 337 | struct mthca_mailbox *mailbox; |
244 | struct mthca_mpt_entry *mpt_entry; | 338 | struct mthca_mpt_entry *mpt_entry; |
245 | u32 key; | 339 | u32 key; |
340 | int i; | ||
246 | int err; | 341 | int err; |
247 | u8 status; | 342 | u8 status; |
248 | 343 | ||
249 | might_sleep(); | 344 | might_sleep(); |
250 | 345 | ||
251 | mr->order = -1; | ||
252 | key = mthca_alloc(&dev->mr_table.mpt_alloc); | ||
253 | if (key == -1) | ||
254 | return -ENOMEM; | ||
255 | mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); | ||
256 | |||
257 | if (mthca_is_memfree(dev)) { | ||
258 | err = mthca_table_get(dev, dev->mr_table.mpt_table, key); | ||
259 | if (err) | ||
260 | goto err_out_mpt_free; | ||
261 | } | ||
262 | |||
263 | mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA, | ||
264 | GFP_KERNEL); | ||
265 | if (!mailbox) { | ||
266 | err = -ENOMEM; | ||
267 | goto err_out_table; | ||
268 | } | ||
269 | mpt_entry = MAILBOX_ALIGN(mailbox); | ||
270 | |||
271 | mpt_entry->flags = cpu_to_be32(MTHCA_MPT_FLAG_SW_OWNS | | ||
272 | MTHCA_MPT_FLAG_MIO | | ||
273 | MTHCA_MPT_FLAG_PHYSICAL | | ||
274 | MTHCA_MPT_FLAG_REGION | | ||
275 | access); | ||
276 | mpt_entry->page_size = 0; | ||
277 | mpt_entry->key = cpu_to_be32(key); | ||
278 | mpt_entry->pd = cpu_to_be32(pd); | ||
279 | mpt_entry->start = 0; | ||
280 | mpt_entry->length = ~0ULL; | ||
281 | |||
282 | memset(&mpt_entry->lkey, 0, | ||
283 | sizeof *mpt_entry - offsetof(struct mthca_mpt_entry, lkey)); | ||
284 | |||
285 | err = mthca_SW2HW_MPT(dev, mpt_entry, | ||
286 | key & (dev->limits.num_mpts - 1), | ||
287 | &status); | ||
288 | if (err) { | ||
289 | mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err); | ||
290 | goto err_out_table; | ||
291 | } else if (status) { | ||
292 | mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n", | ||
293 | status); | ||
294 | err = -EINVAL; | ||
295 | goto err_out_table; | ||
296 | } | ||
297 | |||
298 | kfree(mailbox); | ||
299 | return err; | ||
300 | |||
301 | err_out_table: | ||
302 | if (mthca_is_memfree(dev)) | ||
303 | mthca_table_put(dev, dev->mr_table.mpt_table, key); | ||
304 | |||
305 | err_out_mpt_free: | ||
306 | mthca_free(&dev->mr_table.mpt_alloc, key); | ||
307 | kfree(mailbox); | ||
308 | return err; | ||
309 | } | ||
310 | |||
311 | int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd, | ||
312 | u64 *buffer_list, int buffer_size_shift, | ||
313 | int list_len, u64 iova, u64 total_size, | ||
314 | u32 access, struct mthca_mr *mr) | ||
315 | { | ||
316 | void *mailbox; | ||
317 | u64 *mtt_entry; | ||
318 | struct mthca_mpt_entry *mpt_entry; | ||
319 | u32 key; | ||
320 | int err = -ENOMEM; | ||
321 | u8 status; | ||
322 | int i; | ||
323 | |||
324 | might_sleep(); | ||
325 | WARN_ON(buffer_size_shift >= 32); | 346 | WARN_ON(buffer_size_shift >= 32); |
326 | 347 | ||
327 | key = mthca_alloc(&dev->mr_table.mpt_alloc); | 348 | key = mthca_alloc(&dev->mr_table.mpt_alloc); |
@@ -335,75 +356,33 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd, | |||
335 | goto err_out_mpt_free; | 356 | goto err_out_mpt_free; |
336 | } | 357 | } |
337 | 358 | ||
338 | for (i = MTHCA_MTT_SEG_SIZE / 8, mr->order = 0; | 359 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
339 | i < list_len; | 360 | if (IS_ERR(mailbox)) { |
340 | i <<= 1, ++mr->order) | 361 | err = PTR_ERR(mailbox); |
341 | ; /* nothing */ | ||
342 | |||
343 | mr->first_seg = mthca_alloc_mtt(dev, mr->order, | ||
344 | &dev->mr_table.mtt_buddy); | ||
345 | if (mr->first_seg == -1) | ||
346 | goto err_out_table; | 362 | goto err_out_table; |
347 | |||
348 | /* | ||
349 | * If list_len is odd, we add one more dummy entry for | ||
350 | * firmware efficiency. | ||
351 | */ | ||
352 | mailbox = kmalloc(max(sizeof *mpt_entry, | ||
353 | (size_t) 8 * (list_len + (list_len & 1) + 2)) + | ||
354 | MTHCA_CMD_MAILBOX_EXTRA, | ||
355 | GFP_KERNEL); | ||
356 | if (!mailbox) | ||
357 | goto err_out_free_mtt; | ||
358 | |||
359 | mtt_entry = MAILBOX_ALIGN(mailbox); | ||
360 | |||
361 | mtt_entry[0] = cpu_to_be64(dev->mr_table.mtt_base + | ||
362 | mr->first_seg * MTHCA_MTT_SEG_SIZE); | ||
363 | mtt_entry[1] = 0; | ||
364 | for (i = 0; i < list_len; ++i) | ||
365 | mtt_entry[i + 2] = cpu_to_be64(buffer_list[i] | | ||
366 | MTHCA_MTT_FLAG_PRESENT); | ||
367 | if (list_len & 1) { | ||
368 | mtt_entry[i + 2] = 0; | ||
369 | ++list_len; | ||
370 | } | ||
371 | |||
372 | if (0) { | ||
373 | mthca_dbg(dev, "Dumping MPT entry\n"); | ||
374 | for (i = 0; i < list_len + 2; ++i) | ||
375 | printk(KERN_ERR "[%2d] %016llx\n", | ||
376 | i, (unsigned long long) be64_to_cpu(mtt_entry[i])); | ||
377 | } | ||
378 | |||
379 | err = mthca_WRITE_MTT(dev, mtt_entry, list_len, &status); | ||
380 | if (err) { | ||
381 | mthca_warn(dev, "WRITE_MTT failed (%d)\n", err); | ||
382 | goto err_out_mailbox_free; | ||
383 | } | ||
384 | if (status) { | ||
385 | mthca_warn(dev, "WRITE_MTT returned status 0x%02x\n", | ||
386 | status); | ||
387 | err = -EINVAL; | ||
388 | goto err_out_mailbox_free; | ||
389 | } | 363 | } |
390 | 364 | mpt_entry = mailbox->buf; | |
391 | mpt_entry = MAILBOX_ALIGN(mailbox); | ||
392 | 365 | ||
393 | mpt_entry->flags = cpu_to_be32(MTHCA_MPT_FLAG_SW_OWNS | | 366 | mpt_entry->flags = cpu_to_be32(MTHCA_MPT_FLAG_SW_OWNS | |
394 | MTHCA_MPT_FLAG_MIO | | 367 | MTHCA_MPT_FLAG_MIO | |
395 | MTHCA_MPT_FLAG_REGION | | 368 | MTHCA_MPT_FLAG_REGION | |
396 | access); | 369 | access); |
370 | if (!mr->mtt) | ||
371 | mpt_entry->flags |= cpu_to_be32(MTHCA_MPT_FLAG_PHYSICAL); | ||
397 | 372 | ||
398 | mpt_entry->page_size = cpu_to_be32(buffer_size_shift - 12); | 373 | mpt_entry->page_size = cpu_to_be32(buffer_size_shift - 12); |
399 | mpt_entry->key = cpu_to_be32(key); | 374 | mpt_entry->key = cpu_to_be32(key); |
400 | mpt_entry->pd = cpu_to_be32(pd); | 375 | mpt_entry->pd = cpu_to_be32(pd); |
401 | mpt_entry->start = cpu_to_be64(iova); | 376 | mpt_entry->start = cpu_to_be64(iova); |
402 | mpt_entry->length = cpu_to_be64(total_size); | 377 | mpt_entry->length = cpu_to_be64(total_size); |
378 | |||
403 | memset(&mpt_entry->lkey, 0, | 379 | memset(&mpt_entry->lkey, 0, |
404 | sizeof *mpt_entry - offsetof(struct mthca_mpt_entry, lkey)); | 380 | sizeof *mpt_entry - offsetof(struct mthca_mpt_entry, lkey)); |
405 | mpt_entry->mtt_seg = cpu_to_be64(dev->mr_table.mtt_base + | 381 | |
406 | mr->first_seg * MTHCA_MTT_SEG_SIZE); | 382 | if (mr->mtt) |
383 | mpt_entry->mtt_seg = | ||
384 | cpu_to_be64(dev->mr_table.mtt_base + | ||
385 | mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE); | ||
407 | 386 | ||
408 | if (0) { | 387 | if (0) { |
409 | mthca_dbg(dev, "Dumping MPT entry %08x:\n", mr->ibmr.lkey); | 388 | mthca_dbg(dev, "Dumping MPT entry %08x:\n", mr->ibmr.lkey); |
@@ -416,45 +395,70 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd, | |||
416 | } | 395 | } |
417 | } | 396 | } |
418 | 397 | ||
419 | err = mthca_SW2HW_MPT(dev, mpt_entry, | 398 | err = mthca_SW2HW_MPT(dev, mailbox, |
420 | key & (dev->limits.num_mpts - 1), | 399 | key & (dev->limits.num_mpts - 1), |
421 | &status); | 400 | &status); |
422 | if (err) | 401 | if (err) { |
423 | mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err); | 402 | mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err); |
424 | else if (status) { | 403 | goto err_out_mailbox; |
404 | } else if (status) { | ||
425 | mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n", | 405 | mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n", |
426 | status); | 406 | status); |
427 | err = -EINVAL; | 407 | err = -EINVAL; |
408 | goto err_out_mailbox; | ||
428 | } | 409 | } |
429 | 410 | ||
430 | kfree(mailbox); | 411 | mthca_free_mailbox(dev, mailbox); |
431 | return err; | 412 | return err; |
432 | 413 | ||
433 | err_out_mailbox_free: | 414 | err_out_mailbox: |
434 | kfree(mailbox); | 415 | mthca_free_mailbox(dev, mailbox); |
435 | |||
436 | err_out_free_mtt: | ||
437 | mthca_free_mtt(dev, mr->first_seg, mr->order, &dev->mr_table.mtt_buddy); | ||
438 | 416 | ||
439 | err_out_table: | 417 | err_out_table: |
440 | if (mthca_is_memfree(dev)) | 418 | mthca_table_put(dev, dev->mr_table.mpt_table, key); |
441 | mthca_table_put(dev, dev->mr_table.mpt_table, key); | ||
442 | 419 | ||
443 | err_out_mpt_free: | 420 | err_out_mpt_free: |
444 | mthca_free(&dev->mr_table.mpt_alloc, key); | 421 | mthca_free(&dev->mr_table.mpt_alloc, key); |
445 | return err; | 422 | return err; |
446 | } | 423 | } |
447 | 424 | ||
448 | /* Free mr or fmr */ | 425 | int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd, |
449 | static void mthca_free_region(struct mthca_dev *dev, u32 lkey, int order, | 426 | u32 access, struct mthca_mr *mr) |
450 | u32 first_seg, struct mthca_buddy *buddy) | ||
451 | { | 427 | { |
452 | if (order >= 0) | 428 | mr->mtt = NULL; |
453 | mthca_free_mtt(dev, first_seg, order, buddy); | 429 | return mthca_mr_alloc(dev, pd, 12, 0, ~0ULL, access, mr); |
430 | } | ||
454 | 431 | ||
455 | if (mthca_is_memfree(dev)) | 432 | int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd, |
456 | mthca_table_put(dev, dev->mr_table.mpt_table, | 433 | u64 *buffer_list, int buffer_size_shift, |
457 | arbel_key_to_hw_index(lkey)); | 434 | int list_len, u64 iova, u64 total_size, |
435 | u32 access, struct mthca_mr *mr) | ||
436 | { | ||
437 | int err; | ||
438 | |||
439 | mr->mtt = mthca_alloc_mtt(dev, list_len); | ||
440 | if (IS_ERR(mr->mtt)) | ||
441 | return PTR_ERR(mr->mtt); | ||
442 | |||
443 | err = mthca_write_mtt(dev, mr->mtt, 0, buffer_list, list_len); | ||
444 | if (err) { | ||
445 | mthca_free_mtt(dev, mr->mtt); | ||
446 | return err; | ||
447 | } | ||
448 | |||
449 | err = mthca_mr_alloc(dev, pd, buffer_size_shift, iova, | ||
450 | total_size, access, mr); | ||
451 | if (err) | ||
452 | mthca_free_mtt(dev, mr->mtt); | ||
453 | |||
454 | return err; | ||
455 | } | ||
456 | |||
457 | /* Free mr or fmr */ | ||
458 | static void mthca_free_region(struct mthca_dev *dev, u32 lkey) | ||
459 | { | ||
460 | mthca_table_put(dev, dev->mr_table.mpt_table, | ||
461 | arbel_key_to_hw_index(lkey)); | ||
458 | 462 | ||
459 | mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, lkey)); | 463 | mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, lkey)); |
460 | } | 464 | } |
@@ -476,15 +480,15 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr) | |||
476 | mthca_warn(dev, "HW2SW_MPT returned status 0x%02x\n", | 480 | mthca_warn(dev, "HW2SW_MPT returned status 0x%02x\n", |
477 | status); | 481 | status); |
478 | 482 | ||
479 | mthca_free_region(dev, mr->ibmr.lkey, mr->order, mr->first_seg, | 483 | mthca_free_region(dev, mr->ibmr.lkey); |
480 | &dev->mr_table.mtt_buddy); | 484 | mthca_free_mtt(dev, mr->mtt); |
481 | } | 485 | } |
482 | 486 | ||
483 | int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, | 487 | int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, |
484 | u32 access, struct mthca_fmr *mr) | 488 | u32 access, struct mthca_fmr *mr) |
485 | { | 489 | { |
486 | struct mthca_mpt_entry *mpt_entry; | 490 | struct mthca_mpt_entry *mpt_entry; |
487 | void *mailbox; | 491 | struct mthca_mailbox *mailbox; |
488 | u64 mtt_seg; | 492 | u64 mtt_seg; |
489 | u32 key, idx; | 493 | u32 key, idx; |
490 | u8 status; | 494 | u8 status; |
@@ -522,31 +526,24 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, | |||
522 | mr->mem.tavor.mpt = dev->mr_table.tavor_fmr.mpt_base + | 526 | mr->mem.tavor.mpt = dev->mr_table.tavor_fmr.mpt_base + |
523 | sizeof *(mr->mem.tavor.mpt) * idx; | 527 | sizeof *(mr->mem.tavor.mpt) * idx; |
524 | 528 | ||
525 | for (i = MTHCA_MTT_SEG_SIZE / 8, mr->order = 0; | 529 | mr->mtt = __mthca_alloc_mtt(dev, list_len, dev->mr_table.fmr_mtt_buddy); |
526 | i < list_len; | 530 | if (IS_ERR(mr->mtt)) |
527 | i <<= 1, ++mr->order) | ||
528 | ; /* nothing */ | ||
529 | |||
530 | mr->first_seg = mthca_alloc_mtt(dev, mr->order, | ||
531 | dev->mr_table.fmr_mtt_buddy); | ||
532 | if (mr->first_seg == -1) | ||
533 | goto err_out_table; | 531 | goto err_out_table; |
534 | 532 | ||
535 | mtt_seg = mr->first_seg * MTHCA_MTT_SEG_SIZE; | 533 | mtt_seg = mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE; |
536 | 534 | ||
537 | if (mthca_is_memfree(dev)) { | 535 | if (mthca_is_memfree(dev)) { |
538 | mr->mem.arbel.mtts = mthca_table_find(dev->mr_table.mtt_table, | 536 | mr->mem.arbel.mtts = mthca_table_find(dev->mr_table.mtt_table, |
539 | mr->first_seg); | 537 | mr->mtt->first_seg); |
540 | BUG_ON(!mr->mem.arbel.mtts); | 538 | BUG_ON(!mr->mem.arbel.mtts); |
541 | } else | 539 | } else |
542 | mr->mem.tavor.mtts = dev->mr_table.tavor_fmr.mtt_base + mtt_seg; | 540 | mr->mem.tavor.mtts = dev->mr_table.tavor_fmr.mtt_base + mtt_seg; |
543 | 541 | ||
544 | mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA, | 542 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
545 | GFP_KERNEL); | 543 | if (IS_ERR(mailbox)) |
546 | if (!mailbox) | ||
547 | goto err_out_free_mtt; | 544 | goto err_out_free_mtt; |
548 | 545 | ||
549 | mpt_entry = MAILBOX_ALIGN(mailbox); | 546 | mpt_entry = mailbox->buf; |
550 | 547 | ||
551 | mpt_entry->flags = cpu_to_be32(MTHCA_MPT_FLAG_SW_OWNS | | 548 | mpt_entry->flags = cpu_to_be32(MTHCA_MPT_FLAG_SW_OWNS | |
552 | MTHCA_MPT_FLAG_MIO | | 549 | MTHCA_MPT_FLAG_MIO | |
@@ -571,7 +568,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, | |||
571 | } | 568 | } |
572 | } | 569 | } |
573 | 570 | ||
574 | err = mthca_SW2HW_MPT(dev, mpt_entry, | 571 | err = mthca_SW2HW_MPT(dev, mailbox, |
575 | key & (dev->limits.num_mpts - 1), | 572 | key & (dev->limits.num_mpts - 1), |
576 | &status); | 573 | &status); |
577 | if (err) { | 574 | if (err) { |
@@ -585,19 +582,17 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, | |||
585 | goto err_out_mailbox_free; | 582 | goto err_out_mailbox_free; |
586 | } | 583 | } |
587 | 584 | ||
588 | kfree(mailbox); | 585 | mthca_free_mailbox(dev, mailbox); |
589 | return 0; | 586 | return 0; |
590 | 587 | ||
591 | err_out_mailbox_free: | 588 | err_out_mailbox_free: |
592 | kfree(mailbox); | 589 | mthca_free_mailbox(dev, mailbox); |
593 | 590 | ||
594 | err_out_free_mtt: | 591 | err_out_free_mtt: |
595 | mthca_free_mtt(dev, mr->first_seg, mr->order, | 592 | mthca_free_mtt(dev, mr->mtt); |
596 | dev->mr_table.fmr_mtt_buddy); | ||
597 | 593 | ||
598 | err_out_table: | 594 | err_out_table: |
599 | if (mthca_is_memfree(dev)) | 595 | mthca_table_put(dev, dev->mr_table.mpt_table, key); |
600 | mthca_table_put(dev, dev->mr_table.mpt_table, key); | ||
601 | 596 | ||
602 | err_out_mpt_free: | 597 | err_out_mpt_free: |
603 | mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey); | 598 | mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey); |
@@ -609,8 +604,9 @@ int mthca_free_fmr(struct mthca_dev *dev, struct mthca_fmr *fmr) | |||
609 | if (fmr->maps) | 604 | if (fmr->maps) |
610 | return -EBUSY; | 605 | return -EBUSY; |
611 | 606 | ||
612 | mthca_free_region(dev, fmr->ibmr.lkey, fmr->order, fmr->first_seg, | 607 | mthca_free_region(dev, fmr->ibmr.lkey); |
613 | dev->mr_table.fmr_mtt_buddy); | 608 | mthca_free_mtt(dev, fmr->mtt); |
609 | |||
614 | return 0; | 610 | return 0; |
615 | } | 611 | } |
616 | 612 | ||
@@ -826,7 +822,8 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev) | |||
826 | if (dev->limits.reserved_mtts) { | 822 | if (dev->limits.reserved_mtts) { |
827 | i = fls(dev->limits.reserved_mtts - 1); | 823 | i = fls(dev->limits.reserved_mtts - 1); |
828 | 824 | ||
829 | if (mthca_alloc_mtt(dev, i, dev->mr_table.fmr_mtt_buddy) == -1) { | 825 | if (mthca_alloc_mtt_range(dev, i, |
826 | dev->mr_table.fmr_mtt_buddy) == -1) { | ||
830 | mthca_warn(dev, "MTT table of order %d is too small.\n", | 827 | mthca_warn(dev, "MTT table of order %d is too small.\n", |
831 | dev->mr_table.fmr_mtt_buddy->max_order); | 828 | dev->mr_table.fmr_mtt_buddy->max_order); |
832 | err = -ENOMEM; | 829 | err = -ENOMEM; |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 159f4e6c312d..0b5adfd91597 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. | 2 | * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. |
3 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -52,7 +53,7 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
52 | if (!in_mad || !out_mad) | 53 | if (!in_mad || !out_mad) |
53 | goto out; | 54 | goto out; |
54 | 55 | ||
55 | memset(props, 0, sizeof props); | 56 | memset(props, 0, sizeof *props); |
56 | 57 | ||
57 | props->fw_ver = mdev->fw_ver; | 58 | props->fw_ver = mdev->fw_ver; |
58 | 59 | ||
@@ -558,6 +559,7 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd, | |||
558 | convert_access(acc), mr); | 559 | convert_access(acc), mr); |
559 | 560 | ||
560 | if (err) { | 561 | if (err) { |
562 | kfree(page_list); | ||
561 | kfree(mr); | 563 | kfree(mr); |
562 | return ERR_PTR(err); | 564 | return ERR_PTR(err); |
563 | } | 565 | } |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h index 619710f95a87..4d976cccb1a8 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.h +++ b/drivers/infiniband/hw/mthca/mthca_provider.h | |||
@@ -54,18 +54,18 @@ struct mthca_uar { | |||
54 | int index; | 54 | int index; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | struct mthca_mtt; | ||
58 | |||
57 | struct mthca_mr { | 59 | struct mthca_mr { |
58 | struct ib_mr ibmr; | 60 | struct ib_mr ibmr; |
59 | int order; | 61 | struct mthca_mtt *mtt; |
60 | u32 first_seg; | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | struct mthca_fmr { | 64 | struct mthca_fmr { |
64 | struct ib_fmr ibmr; | 65 | struct ib_fmr ibmr; |
65 | struct ib_fmr_attr attr; | 66 | struct ib_fmr_attr attr; |
66 | int order; | 67 | struct mthca_mtt *mtt; |
67 | u32 first_seg; | 68 | int maps; |
68 | int maps; | ||
69 | union { | 69 | union { |
70 | struct { | 70 | struct { |
71 | struct mthca_mpt_entry __iomem *mpt; | 71 | struct mthca_mpt_entry __iomem *mpt; |
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index ca73bab11a02..163a8ef4186f 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -357,6 +357,9 @@ static const struct { | |||
357 | [UD] = (IB_QP_PKEY_INDEX | | 357 | [UD] = (IB_QP_PKEY_INDEX | |
358 | IB_QP_PORT | | 358 | IB_QP_PORT | |
359 | IB_QP_QKEY), | 359 | IB_QP_QKEY), |
360 | [UC] = (IB_QP_PKEY_INDEX | | ||
361 | IB_QP_PORT | | ||
362 | IB_QP_ACCESS_FLAGS), | ||
360 | [RC] = (IB_QP_PKEY_INDEX | | 363 | [RC] = (IB_QP_PKEY_INDEX | |
361 | IB_QP_PORT | | 364 | IB_QP_PORT | |
362 | IB_QP_ACCESS_FLAGS), | 365 | IB_QP_ACCESS_FLAGS), |
@@ -378,6 +381,9 @@ static const struct { | |||
378 | [UD] = (IB_QP_PKEY_INDEX | | 381 | [UD] = (IB_QP_PKEY_INDEX | |
379 | IB_QP_PORT | | 382 | IB_QP_PORT | |
380 | IB_QP_QKEY), | 383 | IB_QP_QKEY), |
384 | [UC] = (IB_QP_PKEY_INDEX | | ||
385 | IB_QP_PORT | | ||
386 | IB_QP_ACCESS_FLAGS), | ||
381 | [RC] = (IB_QP_PKEY_INDEX | | 387 | [RC] = (IB_QP_PKEY_INDEX | |
382 | IB_QP_PORT | | 388 | IB_QP_PORT | |
383 | IB_QP_ACCESS_FLAGS), | 389 | IB_QP_ACCESS_FLAGS), |
@@ -388,6 +394,11 @@ static const struct { | |||
388 | [IB_QPS_RTR] = { | 394 | [IB_QPS_RTR] = { |
389 | .trans = MTHCA_TRANS_INIT2RTR, | 395 | .trans = MTHCA_TRANS_INIT2RTR, |
390 | .req_param = { | 396 | .req_param = { |
397 | [UC] = (IB_QP_AV | | ||
398 | IB_QP_PATH_MTU | | ||
399 | IB_QP_DEST_QPN | | ||
400 | IB_QP_RQ_PSN | | ||
401 | IB_QP_MAX_DEST_RD_ATOMIC), | ||
391 | [RC] = (IB_QP_AV | | 402 | [RC] = (IB_QP_AV | |
392 | IB_QP_PATH_MTU | | 403 | IB_QP_PATH_MTU | |
393 | IB_QP_DEST_QPN | | 404 | IB_QP_DEST_QPN | |
@@ -398,6 +409,9 @@ static const struct { | |||
398 | .opt_param = { | 409 | .opt_param = { |
399 | [UD] = (IB_QP_PKEY_INDEX | | 410 | [UD] = (IB_QP_PKEY_INDEX | |
400 | IB_QP_QKEY), | 411 | IB_QP_QKEY), |
412 | [UC] = (IB_QP_ALT_PATH | | ||
413 | IB_QP_ACCESS_FLAGS | | ||
414 | IB_QP_PKEY_INDEX), | ||
401 | [RC] = (IB_QP_ALT_PATH | | 415 | [RC] = (IB_QP_ALT_PATH | |
402 | IB_QP_ACCESS_FLAGS | | 416 | IB_QP_ACCESS_FLAGS | |
403 | IB_QP_PKEY_INDEX), | 417 | IB_QP_PKEY_INDEX), |
@@ -413,6 +427,8 @@ static const struct { | |||
413 | .trans = MTHCA_TRANS_RTR2RTS, | 427 | .trans = MTHCA_TRANS_RTR2RTS, |
414 | .req_param = { | 428 | .req_param = { |
415 | [UD] = IB_QP_SQ_PSN, | 429 | [UD] = IB_QP_SQ_PSN, |
430 | [UC] = (IB_QP_SQ_PSN | | ||
431 | IB_QP_MAX_QP_RD_ATOMIC), | ||
416 | [RC] = (IB_QP_TIMEOUT | | 432 | [RC] = (IB_QP_TIMEOUT | |
417 | IB_QP_RETRY_CNT | | 433 | IB_QP_RETRY_CNT | |
418 | IB_QP_RNR_RETRY | | 434 | IB_QP_RNR_RETRY | |
@@ -423,6 +439,11 @@ static const struct { | |||
423 | .opt_param = { | 439 | .opt_param = { |
424 | [UD] = (IB_QP_CUR_STATE | | 440 | [UD] = (IB_QP_CUR_STATE | |
425 | IB_QP_QKEY), | 441 | IB_QP_QKEY), |
442 | [UC] = (IB_QP_CUR_STATE | | ||
443 | IB_QP_ALT_PATH | | ||
444 | IB_QP_ACCESS_FLAGS | | ||
445 | IB_QP_PKEY_INDEX | | ||
446 | IB_QP_PATH_MIG_STATE), | ||
426 | [RC] = (IB_QP_CUR_STATE | | 447 | [RC] = (IB_QP_CUR_STATE | |
427 | IB_QP_ALT_PATH | | 448 | IB_QP_ALT_PATH | |
428 | IB_QP_ACCESS_FLAGS | | 449 | IB_QP_ACCESS_FLAGS | |
@@ -442,6 +463,9 @@ static const struct { | |||
442 | .opt_param = { | 463 | .opt_param = { |
443 | [UD] = (IB_QP_CUR_STATE | | 464 | [UD] = (IB_QP_CUR_STATE | |
444 | IB_QP_QKEY), | 465 | IB_QP_QKEY), |
466 | [UC] = (IB_QP_ACCESS_FLAGS | | ||
467 | IB_QP_ALT_PATH | | ||
468 | IB_QP_PATH_MIG_STATE), | ||
445 | [RC] = (IB_QP_ACCESS_FLAGS | | 469 | [RC] = (IB_QP_ACCESS_FLAGS | |
446 | IB_QP_ALT_PATH | | 470 | IB_QP_ALT_PATH | |
447 | IB_QP_PATH_MIG_STATE | | 471 | IB_QP_PATH_MIG_STATE | |
@@ -462,6 +486,10 @@ static const struct { | |||
462 | .opt_param = { | 486 | .opt_param = { |
463 | [UD] = (IB_QP_CUR_STATE | | 487 | [UD] = (IB_QP_CUR_STATE | |
464 | IB_QP_QKEY), | 488 | IB_QP_QKEY), |
489 | [UC] = (IB_QP_CUR_STATE | | ||
490 | IB_QP_ALT_PATH | | ||
491 | IB_QP_ACCESS_FLAGS | | ||
492 | IB_QP_PATH_MIG_STATE), | ||
465 | [RC] = (IB_QP_CUR_STATE | | 493 | [RC] = (IB_QP_CUR_STATE | |
466 | IB_QP_ALT_PATH | | 494 | IB_QP_ALT_PATH | |
467 | IB_QP_ACCESS_FLAGS | | 495 | IB_QP_ACCESS_FLAGS | |
@@ -476,6 +504,14 @@ static const struct { | |||
476 | .opt_param = { | 504 | .opt_param = { |
477 | [UD] = (IB_QP_PKEY_INDEX | | 505 | [UD] = (IB_QP_PKEY_INDEX | |
478 | IB_QP_QKEY), | 506 | IB_QP_QKEY), |
507 | [UC] = (IB_QP_AV | | ||
508 | IB_QP_MAX_QP_RD_ATOMIC | | ||
509 | IB_QP_MAX_DEST_RD_ATOMIC | | ||
510 | IB_QP_CUR_STATE | | ||
511 | IB_QP_ALT_PATH | | ||
512 | IB_QP_ACCESS_FLAGS | | ||
513 | IB_QP_PKEY_INDEX | | ||
514 | IB_QP_PATH_MIG_STATE), | ||
479 | [RC] = (IB_QP_AV | | 515 | [RC] = (IB_QP_AV | |
480 | IB_QP_TIMEOUT | | 516 | IB_QP_TIMEOUT | |
481 | IB_QP_RETRY_CNT | | 517 | IB_QP_RETRY_CNT | |
@@ -501,6 +537,7 @@ static const struct { | |||
501 | .opt_param = { | 537 | .opt_param = { |
502 | [UD] = (IB_QP_CUR_STATE | | 538 | [UD] = (IB_QP_CUR_STATE | |
503 | IB_QP_QKEY), | 539 | IB_QP_QKEY), |
540 | [UC] = (IB_QP_CUR_STATE), | ||
504 | [RC] = (IB_QP_CUR_STATE | | 541 | [RC] = (IB_QP_CUR_STATE | |
505 | IB_QP_MIN_RNR_TIMER), | 542 | IB_QP_MIN_RNR_TIMER), |
506 | [MLX] = (IB_QP_CUR_STATE | | 543 | [MLX] = (IB_QP_CUR_STATE | |
@@ -552,7 +589,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
552 | struct mthca_dev *dev = to_mdev(ibqp->device); | 589 | struct mthca_dev *dev = to_mdev(ibqp->device); |
553 | struct mthca_qp *qp = to_mqp(ibqp); | 590 | struct mthca_qp *qp = to_mqp(ibqp); |
554 | enum ib_qp_state cur_state, new_state; | 591 | enum ib_qp_state cur_state, new_state; |
555 | void *mailbox = NULL; | 592 | struct mthca_mailbox *mailbox; |
556 | struct mthca_qp_param *qp_param; | 593 | struct mthca_qp_param *qp_param; |
557 | struct mthca_qp_context *qp_context; | 594 | struct mthca_qp_context *qp_context; |
558 | u32 req_param, opt_param; | 595 | u32 req_param, opt_param; |
@@ -609,10 +646,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
609 | return -EINVAL; | 646 | return -EINVAL; |
610 | } | 647 | } |
611 | 648 | ||
612 | mailbox = kmalloc(sizeof (*qp_param) + MTHCA_CMD_MAILBOX_EXTRA, GFP_KERNEL); | 649 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
613 | if (!mailbox) | 650 | if (IS_ERR(mailbox)) |
614 | return -ENOMEM; | 651 | return PTR_ERR(mailbox); |
615 | qp_param = MAILBOX_ALIGN(mailbox); | 652 | qp_param = mailbox->buf; |
616 | qp_context = &qp_param->context; | 653 | qp_context = &qp_param->context; |
617 | memset(qp_param, 0, sizeof *qp_param); | 654 | memset(qp_param, 0, sizeof *qp_param); |
618 | 655 | ||
@@ -683,7 +720,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
683 | if (attr_mask & IB_QP_AV) { | 720 | if (attr_mask & IB_QP_AV) { |
684 | qp_context->pri_path.g_mylmc = attr->ah_attr.src_path_bits & 0x7f; | 721 | qp_context->pri_path.g_mylmc = attr->ah_attr.src_path_bits & 0x7f; |
685 | qp_context->pri_path.rlid = cpu_to_be16(attr->ah_attr.dlid); | 722 | qp_context->pri_path.rlid = cpu_to_be16(attr->ah_attr.dlid); |
686 | qp_context->pri_path.static_rate = (!!attr->ah_attr.static_rate) << 3; | 723 | qp_context->pri_path.static_rate = !!attr->ah_attr.static_rate; |
687 | if (attr->ah_attr.ah_flags & IB_AH_GRH) { | 724 | if (attr->ah_attr.ah_flags & IB_AH_GRH) { |
688 | qp_context->pri_path.g_mylmc |= 1 << 7; | 725 | qp_context->pri_path.g_mylmc |= 1 << 7; |
689 | qp_context->pri_path.mgid_index = attr->ah_attr.grh.sgid_index; | 726 | qp_context->pri_path.mgid_index = attr->ah_attr.grh.sgid_index; |
@@ -724,9 +761,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
724 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RETRY_COUNT); | 761 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RETRY_COUNT); |
725 | } | 762 | } |
726 | 763 | ||
727 | if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { | 764 | if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { |
728 | qp_context->params1 |= cpu_to_be32(min(attr->max_dest_rd_atomic ? | 765 | qp_context->params1 |= cpu_to_be32(min(attr->max_rd_atomic ? |
729 | ffs(attr->max_dest_rd_atomic) - 1 : 0, | 766 | ffs(attr->max_rd_atomic) - 1 : 0, |
730 | 7) << 21); | 767 | 7) << 21); |
731 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_SRA_MAX); | 768 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_SRA_MAX); |
732 | } | 769 | } |
@@ -764,10 +801,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
764 | qp->atomic_rd_en = attr->qp_access_flags; | 801 | qp->atomic_rd_en = attr->qp_access_flags; |
765 | } | 802 | } |
766 | 803 | ||
767 | if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { | 804 | if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { |
768 | u8 rra_max; | 805 | u8 rra_max; |
769 | 806 | ||
770 | if (qp->resp_depth && !attr->max_rd_atomic) { | 807 | if (qp->resp_depth && !attr->max_dest_rd_atomic) { |
771 | /* | 808 | /* |
772 | * Lowering our responder resources to zero. | 809 | * Lowering our responder resources to zero. |
773 | * Turn off RDMA/atomics as responder. | 810 | * Turn off RDMA/atomics as responder. |
@@ -778,7 +815,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
778 | MTHCA_QP_OPTPAR_RAE); | 815 | MTHCA_QP_OPTPAR_RAE); |
779 | } | 816 | } |
780 | 817 | ||
781 | if (!qp->resp_depth && attr->max_rd_atomic) { | 818 | if (!qp->resp_depth && attr->max_dest_rd_atomic) { |
782 | /* | 819 | /* |
783 | * Increasing our responder resources from | 820 | * Increasing our responder resources from |
784 | * zero. Turn on RDMA/atomics as appropriate. | 821 | * zero. Turn on RDMA/atomics as appropriate. |
@@ -799,7 +836,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
799 | } | 836 | } |
800 | 837 | ||
801 | for (rra_max = 0; | 838 | for (rra_max = 0; |
802 | 1 << rra_max < attr->max_rd_atomic && | 839 | 1 << rra_max < attr->max_dest_rd_atomic && |
803 | rra_max < dev->qp_table.rdb_shift; | 840 | rra_max < dev->qp_table.rdb_shift; |
804 | ++rra_max) | 841 | ++rra_max) |
805 | ; /* nothing */ | 842 | ; /* nothing */ |
@@ -807,7 +844,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
807 | qp_context->params2 |= cpu_to_be32(rra_max << 21); | 844 | qp_context->params2 |= cpu_to_be32(rra_max << 21); |
808 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX); | 845 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX); |
809 | 846 | ||
810 | qp->resp_depth = attr->max_rd_atomic; | 847 | qp->resp_depth = attr->max_dest_rd_atomic; |
811 | } | 848 | } |
812 | 849 | ||
813 | qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC); | 850 | qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC); |
@@ -835,7 +872,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
835 | } | 872 | } |
836 | 873 | ||
837 | err = mthca_MODIFY_QP(dev, state_table[cur_state][new_state].trans, | 874 | err = mthca_MODIFY_QP(dev, state_table[cur_state][new_state].trans, |
838 | qp->qpn, 0, qp_param, 0, &status); | 875 | qp->qpn, 0, mailbox, 0, &status); |
839 | if (status) { | 876 | if (status) { |
840 | mthca_warn(dev, "modify QP %d returned status %02x.\n", | 877 | mthca_warn(dev, "modify QP %d returned status %02x.\n", |
841 | state_table[cur_state][new_state].trans, status); | 878 | state_table[cur_state][new_state].trans, status); |
@@ -845,7 +882,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
845 | if (!err) | 882 | if (!err) |
846 | qp->state = new_state; | 883 | qp->state = new_state; |
847 | 884 | ||
848 | kfree(mailbox); | 885 | mthca_free_mailbox(dev, mailbox); |
849 | 886 | ||
850 | if (is_sqp(dev, qp)) | 887 | if (is_sqp(dev, qp)) |
851 | store_attrs(to_msqp(qp), attr, attr_mask); | 888 | store_attrs(to_msqp(qp), attr, attr_mask); |
@@ -934,7 +971,8 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev, | |||
934 | mthca_dbg(dev, "Creating direct QP of size %d (shift %d)\n", | 971 | mthca_dbg(dev, "Creating direct QP of size %d (shift %d)\n", |
935 | size, shift); | 972 | size, shift); |
936 | 973 | ||
937 | qp->queue.direct.buf = pci_alloc_consistent(dev->pdev, size, &t); | 974 | qp->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev, size, |
975 | &t, GFP_KERNEL); | ||
938 | if (!qp->queue.direct.buf) | 976 | if (!qp->queue.direct.buf) |
939 | goto err_out; | 977 | goto err_out; |
940 | 978 | ||
@@ -973,7 +1011,8 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev, | |||
973 | 1011 | ||
974 | for (i = 0; i < npages; ++i) { | 1012 | for (i = 0; i < npages; ++i) { |
975 | qp->queue.page_list[i].buf = | 1013 | qp->queue.page_list[i].buf = |
976 | pci_alloc_consistent(dev->pdev, PAGE_SIZE, &t); | 1014 | dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE, |
1015 | &t, GFP_KERNEL); | ||
977 | if (!qp->queue.page_list[i].buf) | 1016 | if (!qp->queue.page_list[i].buf) |
978 | goto err_out_free; | 1017 | goto err_out_free; |
979 | 1018 | ||
@@ -996,16 +1035,15 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev, | |||
996 | 1035 | ||
997 | err_out_free: | 1036 | err_out_free: |
998 | if (qp->is_direct) { | 1037 | if (qp->is_direct) { |
999 | pci_free_consistent(dev->pdev, size, | 1038 | dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf, |
1000 | qp->queue.direct.buf, | 1039 | pci_unmap_addr(&qp->queue.direct, mapping)); |
1001 | pci_unmap_addr(&qp->queue.direct, mapping)); | ||
1002 | } else | 1040 | } else |
1003 | for (i = 0; i < npages; ++i) { | 1041 | for (i = 0; i < npages; ++i) { |
1004 | if (qp->queue.page_list[i].buf) | 1042 | if (qp->queue.page_list[i].buf) |
1005 | pci_free_consistent(dev->pdev, PAGE_SIZE, | 1043 | dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, |
1006 | qp->queue.page_list[i].buf, | 1044 | qp->queue.page_list[i].buf, |
1007 | pci_unmap_addr(&qp->queue.page_list[i], | 1045 | pci_unmap_addr(&qp->queue.page_list[i], |
1008 | mapping)); | 1046 | mapping)); |
1009 | 1047 | ||
1010 | } | 1048 | } |
1011 | 1049 | ||
@@ -1073,11 +1111,12 @@ static void mthca_free_memfree(struct mthca_dev *dev, | |||
1073 | if (mthca_is_memfree(dev)) { | 1111 | if (mthca_is_memfree(dev)) { |
1074 | mthca_free_db(dev, MTHCA_DB_TYPE_SQ, qp->sq.db_index); | 1112 | mthca_free_db(dev, MTHCA_DB_TYPE_SQ, qp->sq.db_index); |
1075 | mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index); | 1113 | mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index); |
1076 | mthca_table_put(dev, dev->qp_table.rdb_table, | ||
1077 | qp->qpn << dev->qp_table.rdb_shift); | ||
1078 | mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn); | ||
1079 | mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn); | ||
1080 | } | 1114 | } |
1115 | |||
1116 | mthca_table_put(dev, dev->qp_table.rdb_table, | ||
1117 | qp->qpn << dev->qp_table.rdb_shift); | ||
1118 | mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn); | ||
1119 | mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn); | ||
1081 | } | 1120 | } |
1082 | 1121 | ||
1083 | static void mthca_wq_init(struct mthca_wq* wq) | 1122 | static void mthca_wq_init(struct mthca_wq* wq) |
@@ -1529,6 +1568,26 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1529 | 1568 | ||
1530 | break; | 1569 | break; |
1531 | 1570 | ||
1571 | case UC: | ||
1572 | switch (wr->opcode) { | ||
1573 | case IB_WR_RDMA_WRITE: | ||
1574 | case IB_WR_RDMA_WRITE_WITH_IMM: | ||
1575 | ((struct mthca_raddr_seg *) wqe)->raddr = | ||
1576 | cpu_to_be64(wr->wr.rdma.remote_addr); | ||
1577 | ((struct mthca_raddr_seg *) wqe)->rkey = | ||
1578 | cpu_to_be32(wr->wr.rdma.rkey); | ||
1579 | ((struct mthca_raddr_seg *) wqe)->reserved = 0; | ||
1580 | wqe += sizeof (struct mthca_raddr_seg); | ||
1581 | size += sizeof (struct mthca_raddr_seg) / 16; | ||
1582 | break; | ||
1583 | |||
1584 | default: | ||
1585 | /* No extra segments required for sends */ | ||
1586 | break; | ||
1587 | } | ||
1588 | |||
1589 | break; | ||
1590 | |||
1532 | case UD: | 1591 | case UD: |
1533 | ((struct mthca_tavor_ud_seg *) wqe)->lkey = | 1592 | ((struct mthca_tavor_ud_seg *) wqe)->lkey = |
1534 | cpu_to_be32(to_mah(wr->wr.ud.ah)->key); | 1593 | cpu_to_be32(to_mah(wr->wr.ud.ah)->key); |
@@ -1814,9 +1873,29 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1814 | sizeof (struct mthca_atomic_seg); | 1873 | sizeof (struct mthca_atomic_seg); |
1815 | break; | 1874 | break; |
1816 | 1875 | ||
1876 | case IB_WR_RDMA_READ: | ||
1877 | case IB_WR_RDMA_WRITE: | ||
1878 | case IB_WR_RDMA_WRITE_WITH_IMM: | ||
1879 | ((struct mthca_raddr_seg *) wqe)->raddr = | ||
1880 | cpu_to_be64(wr->wr.rdma.remote_addr); | ||
1881 | ((struct mthca_raddr_seg *) wqe)->rkey = | ||
1882 | cpu_to_be32(wr->wr.rdma.rkey); | ||
1883 | ((struct mthca_raddr_seg *) wqe)->reserved = 0; | ||
1884 | wqe += sizeof (struct mthca_raddr_seg); | ||
1885 | size += sizeof (struct mthca_raddr_seg) / 16; | ||
1886 | break; | ||
1887 | |||
1888 | default: | ||
1889 | /* No extra segments required for sends */ | ||
1890 | break; | ||
1891 | } | ||
1892 | |||
1893 | break; | ||
1894 | |||
1895 | case UC: | ||
1896 | switch (wr->opcode) { | ||
1817 | case IB_WR_RDMA_WRITE: | 1897 | case IB_WR_RDMA_WRITE: |
1818 | case IB_WR_RDMA_WRITE_WITH_IMM: | 1898 | case IB_WR_RDMA_WRITE_WITH_IMM: |
1819 | case IB_WR_RDMA_READ: | ||
1820 | ((struct mthca_raddr_seg *) wqe)->raddr = | 1899 | ((struct mthca_raddr_seg *) wqe)->raddr = |
1821 | cpu_to_be64(wr->wr.rdma.remote_addr); | 1900 | cpu_to_be64(wr->wr.rdma.remote_addr); |
1822 | ((struct mthca_raddr_seg *) wqe)->rkey = | 1901 | ((struct mthca_raddr_seg *) wqe)->rkey = |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 556264b43425..374f404e81da 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/smp_lock.h> | 21 | #include <linux/smp_lock.h> |
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/devfs_fs_kernel.h> | 23 | #include <linux/devfs_fs_kernel.h> |
24 | #include <linux/compat.h> | ||
24 | 25 | ||
25 | struct evdev { | 26 | struct evdev { |
26 | int exist; | 27 | int exist; |
@@ -145,6 +146,41 @@ static int evdev_open(struct inode * inode, struct file * file) | |||
145 | return 0; | 146 | return 0; |
146 | } | 147 | } |
147 | 148 | ||
149 | #ifdef CONFIG_COMPAT | ||
150 | struct input_event_compat { | ||
151 | struct compat_timeval time; | ||
152 | __u16 type; | ||
153 | __u16 code; | ||
154 | __s32 value; | ||
155 | }; | ||
156 | |||
157 | #ifdef CONFIG_X86_64 | ||
158 | # define COMPAT_TEST test_thread_flag(TIF_IA32) | ||
159 | #elif defined(CONFIG_IA64) | ||
160 | # define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) | ||
161 | #elif defined(CONFIG_ARCH_S390) | ||
162 | # define COMPAT_TEST test_thread_flag(TIF_31BIT) | ||
163 | #else | ||
164 | # define COMPAT_TEST test_thread_flag(TIF_32BIT) | ||
165 | #endif | ||
166 | |||
167 | static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | ||
168 | { | ||
169 | struct evdev_list *list = file->private_data; | ||
170 | struct input_event_compat event; | ||
171 | int retval = 0; | ||
172 | |||
173 | while (retval < count) { | ||
174 | if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat))) | ||
175 | return -EFAULT; | ||
176 | input_event(list->evdev->handle.dev, event.type, event.code, event.value); | ||
177 | retval += sizeof(struct input_event_compat); | ||
178 | } | ||
179 | |||
180 | return retval; | ||
181 | } | ||
182 | #endif | ||
183 | |||
148 | static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | 184 | static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) |
149 | { | 185 | { |
150 | struct evdev_list *list = file->private_data; | 186 | struct evdev_list *list = file->private_data; |
@@ -153,6 +189,11 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ | |||
153 | 189 | ||
154 | if (!list->evdev->exist) return -ENODEV; | 190 | if (!list->evdev->exist) return -ENODEV; |
155 | 191 | ||
192 | #ifdef CONFIG_COMPAT | ||
193 | if (COMPAT_TEST) | ||
194 | return evdev_write_compat(file, buffer, count, ppos); | ||
195 | #endif | ||
196 | |||
156 | while (retval < count) { | 197 | while (retval < count) { |
157 | 198 | ||
158 | if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) | 199 | if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) |
@@ -164,11 +205,56 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ | |||
164 | return retval; | 205 | return retval; |
165 | } | 206 | } |
166 | 207 | ||
208 | #ifdef CONFIG_COMPAT | ||
209 | static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | ||
210 | { | ||
211 | struct evdev_list *list = file->private_data; | ||
212 | int retval; | ||
213 | |||
214 | if (count < sizeof(struct input_event_compat)) | ||
215 | return -EINVAL; | ||
216 | |||
217 | if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) | ||
218 | return -EAGAIN; | ||
219 | |||
220 | retval = wait_event_interruptible(list->evdev->wait, | ||
221 | list->head != list->tail || (!list->evdev->exist)); | ||
222 | |||
223 | if (retval) | ||
224 | return retval; | ||
225 | |||
226 | if (!list->evdev->exist) | ||
227 | return -ENODEV; | ||
228 | |||
229 | while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) { | ||
230 | struct input_event *event = (struct input_event *) list->buffer + list->tail; | ||
231 | struct input_event_compat event_compat; | ||
232 | event_compat.time.tv_sec = event->time.tv_sec; | ||
233 | event_compat.time.tv_usec = event->time.tv_usec; | ||
234 | event_compat.type = event->type; | ||
235 | event_compat.code = event->code; | ||
236 | event_compat.value = event->value; | ||
237 | |||
238 | if (copy_to_user(buffer + retval, &event_compat, | ||
239 | sizeof(struct input_event_compat))) return -EFAULT; | ||
240 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
241 | retval += sizeof(struct input_event_compat); | ||
242 | } | ||
243 | |||
244 | return retval; | ||
245 | } | ||
246 | #endif | ||
247 | |||
167 | static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | 248 | static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) |
168 | { | 249 | { |
169 | struct evdev_list *list = file->private_data; | 250 | struct evdev_list *list = file->private_data; |
170 | int retval; | 251 | int retval; |
171 | 252 | ||
253 | #ifdef CONFIG_COMPAT | ||
254 | if (COMPAT_TEST) | ||
255 | return evdev_read_compat(file, buffer, count, ppos); | ||
256 | #endif | ||
257 | |||
172 | if (count < sizeof(struct input_event)) | 258 | if (count < sizeof(struct input_event)) |
173 | return -EINVAL; | 259 | return -EINVAL; |
174 | 260 | ||
@@ -186,7 +272,7 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count | |||
186 | 272 | ||
187 | while (list->head != list->tail && retval + sizeof(struct input_event) <= count) { | 273 | while (list->head != list->tail && retval + sizeof(struct input_event) <= count) { |
188 | if (copy_to_user(buffer + retval, list->buffer + list->tail, | 274 | if (copy_to_user(buffer + retval, list->buffer + list->tail, |
189 | sizeof(struct input_event))) return -EFAULT; | 275 | sizeof(struct input_event))) return -EFAULT; |
190 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | 276 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); |
191 | retval += sizeof(struct input_event); | 277 | retval += sizeof(struct input_event); |
192 | } | 278 | } |
@@ -203,7 +289,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait) | |||
203 | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); | 289 | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); |
204 | } | 290 | } |
205 | 291 | ||
206 | static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 292 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
207 | { | 293 | { |
208 | struct evdev_list *list = file->private_data; | 294 | struct evdev_list *list = file->private_data; |
209 | struct evdev *evdev = list->evdev; | 295 | struct evdev *evdev = list->evdev; |
@@ -285,109 +371,267 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
285 | 371 | ||
286 | default: | 372 | default: |
287 | 373 | ||
288 | if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) | 374 | if (_IOC_TYPE(cmd) != 'E') |
289 | return -EINVAL; | 375 | return -EINVAL; |
290 | 376 | ||
291 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | 377 | if (_IOC_DIR(cmd) == _IOC_READ) { |
292 | 378 | ||
293 | long *bits; | 379 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { |
294 | int len; | 380 | |
295 | 381 | long *bits; | |
296 | switch (_IOC_NR(cmd) & EV_MAX) { | 382 | int len; |
297 | case 0: bits = dev->evbit; len = EV_MAX; break; | 383 | |
298 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | 384 | switch (_IOC_NR(cmd) & EV_MAX) { |
299 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | 385 | case 0: bits = dev->evbit; len = EV_MAX; break; |
300 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | 386 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; |
301 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | 387 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; |
302 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | 388 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; |
303 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | 389 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; |
304 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | 390 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; |
305 | default: return -EINVAL; | 391 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; |
392 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
393 | default: return -EINVAL; | ||
394 | } | ||
395 | len = NBITS(len) * sizeof(long); | ||
396 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
397 | return copy_to_user(p, bits, len) ? -EFAULT : len; | ||
306 | } | 398 | } |
307 | len = NBITS(len) * sizeof(long); | ||
308 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
309 | return copy_to_user(p, bits, len) ? -EFAULT : len; | ||
310 | } | ||
311 | 399 | ||
312 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { | 400 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { |
313 | int len; | 401 | int len; |
314 | len = NBITS(KEY_MAX) * sizeof(long); | 402 | len = NBITS(KEY_MAX) * sizeof(long); |
315 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 403 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
316 | return copy_to_user(p, dev->key, len) ? -EFAULT : len; | 404 | return copy_to_user(p, dev->key, len) ? -EFAULT : len; |
317 | } | 405 | } |
318 | 406 | ||
319 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { | 407 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { |
320 | int len; | 408 | int len; |
321 | len = NBITS(LED_MAX) * sizeof(long); | 409 | len = NBITS(LED_MAX) * sizeof(long); |
322 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 410 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
323 | return copy_to_user(p, dev->led, len) ? -EFAULT : len; | 411 | return copy_to_user(p, dev->led, len) ? -EFAULT : len; |
324 | } | 412 | } |
325 | 413 | ||
326 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { | 414 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { |
327 | int len; | 415 | int len; |
328 | len = NBITS(SND_MAX) * sizeof(long); | 416 | len = NBITS(SND_MAX) * sizeof(long); |
329 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 417 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
330 | return copy_to_user(p, dev->snd, len) ? -EFAULT : len; | 418 | return copy_to_user(p, dev->snd, len) ? -EFAULT : len; |
331 | } | 419 | } |
332 | 420 | ||
333 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | 421 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { |
334 | int len; | 422 | int len; |
335 | if (!dev->name) return -ENOENT; | 423 | if (!dev->name) return -ENOENT; |
336 | len = strlen(dev->name) + 1; | 424 | len = strlen(dev->name) + 1; |
337 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 425 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
338 | return copy_to_user(p, dev->name, len) ? -EFAULT : len; | 426 | return copy_to_user(p, dev->name, len) ? -EFAULT : len; |
339 | } | 427 | } |
428 | |||
429 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | ||
430 | int len; | ||
431 | if (!dev->phys) return -ENOENT; | ||
432 | len = strlen(dev->phys) + 1; | ||
433 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
434 | return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | ||
435 | } | ||
436 | |||
437 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | ||
438 | int len; | ||
439 | if (!dev->uniq) return -ENOENT; | ||
440 | len = strlen(dev->uniq) + 1; | ||
441 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
442 | return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | ||
443 | } | ||
444 | |||
445 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | ||
446 | |||
447 | int t = _IOC_NR(cmd) & ABS_MAX; | ||
448 | |||
449 | abs.value = dev->abs[t]; | ||
450 | abs.minimum = dev->absmin[t]; | ||
451 | abs.maximum = dev->absmax[t]; | ||
452 | abs.fuzz = dev->absfuzz[t]; | ||
453 | abs.flat = dev->absflat[t]; | ||
454 | |||
455 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | ||
456 | return -EFAULT; | ||
457 | |||
458 | return 0; | ||
459 | } | ||
340 | 460 | ||
341 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | ||
342 | int len; | ||
343 | if (!dev->phys) return -ENOENT; | ||
344 | len = strlen(dev->phys) + 1; | ||
345 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
346 | return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | ||
347 | } | 461 | } |
348 | 462 | ||
349 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | 463 | if (_IOC_DIR(cmd) == _IOC_WRITE) { |
350 | int len; | 464 | |
351 | if (!dev->uniq) return -ENOENT; | 465 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
352 | len = strlen(dev->uniq) + 1; | 466 | |
353 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 467 | int t = _IOC_NR(cmd) & ABS_MAX; |
354 | return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | 468 | |
469 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | ||
470 | return -EFAULT; | ||
471 | |||
472 | dev->abs[t] = abs.value; | ||
473 | dev->absmin[t] = abs.minimum; | ||
474 | dev->absmax[t] = abs.maximum; | ||
475 | dev->absfuzz[t] = abs.fuzz; | ||
476 | dev->absflat[t] = abs.flat; | ||
477 | |||
478 | return 0; | ||
479 | } | ||
355 | } | 480 | } |
481 | } | ||
482 | return -EINVAL; | ||
483 | } | ||
356 | 484 | ||
357 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 485 | #ifdef CONFIG_COMPAT |
486 | |||
487 | #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) | ||
488 | #define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1) | ||
489 | #define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT) | ||
490 | #define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x)) | ||
491 | #define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT) | ||
492 | #define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1) | ||
493 | |||
494 | #ifdef __BIG_ENDIAN | ||
495 | #define bit_to_user(bit, max) \ | ||
496 | do { \ | ||
497 | int i; \ | ||
498 | int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ | ||
499 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ | ||
500 | for (i = 0; i < len / sizeof(compat_long_t); i++) \ | ||
501 | if (copy_to_user((compat_long_t*) p + i, \ | ||
502 | (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ | ||
503 | sizeof(compat_long_t))) \ | ||
504 | return -EFAULT; \ | ||
505 | return len; \ | ||
506 | } while (0) | ||
507 | #else | ||
508 | #define bit_to_user(bit, max) \ | ||
509 | do { \ | ||
510 | int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ | ||
511 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ | ||
512 | return copy_to_user(p, (bit), len) ? -EFAULT : len; \ | ||
513 | } while (0) | ||
514 | #endif | ||
515 | |||
516 | static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | ||
517 | { | ||
518 | struct evdev_list *list = file->private_data; | ||
519 | struct evdev *evdev = list->evdev; | ||
520 | struct input_dev *dev = evdev->handle.dev; | ||
521 | struct input_absinfo abs; | ||
522 | void __user *p = compat_ptr(arg); | ||
358 | 523 | ||
359 | int t = _IOC_NR(cmd) & ABS_MAX; | 524 | if (!evdev->exist) return -ENODEV; |
360 | 525 | ||
361 | abs.value = dev->abs[t]; | 526 | switch (cmd) { |
362 | abs.minimum = dev->absmin[t]; | ||
363 | abs.maximum = dev->absmax[t]; | ||
364 | abs.fuzz = dev->absfuzz[t]; | ||
365 | abs.flat = dev->absflat[t]; | ||
366 | 527 | ||
367 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | 528 | case EVIOCGVERSION: |
368 | return -EFAULT; | 529 | case EVIOCGID: |
530 | case EVIOCGKEYCODE: | ||
531 | case EVIOCSKEYCODE: | ||
532 | case EVIOCSFF: | ||
533 | case EVIOCRMFF: | ||
534 | case EVIOCGEFFECTS: | ||
535 | case EVIOCGRAB: | ||
536 | return evdev_ioctl(file, cmd, (unsigned long) p); | ||
369 | 537 | ||
370 | return 0; | 538 | default: |
539 | |||
540 | if (_IOC_TYPE(cmd) != 'E') | ||
541 | return -EINVAL; | ||
542 | |||
543 | if (_IOC_DIR(cmd) == _IOC_READ) { | ||
544 | |||
545 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | ||
546 | long *bits; | ||
547 | int max; | ||
548 | |||
549 | switch (_IOC_NR(cmd) & EV_MAX) { | ||
550 | case 0: bits = dev->evbit; max = EV_MAX; break; | ||
551 | case EV_KEY: bits = dev->keybit; max = KEY_MAX; break; | ||
552 | case EV_REL: bits = dev->relbit; max = REL_MAX; break; | ||
553 | case EV_ABS: bits = dev->absbit; max = ABS_MAX; break; | ||
554 | case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break; | ||
555 | case EV_LED: bits = dev->ledbit; max = LED_MAX; break; | ||
556 | case EV_SND: bits = dev->sndbit; max = SND_MAX; break; | ||
557 | case EV_FF: bits = dev->ffbit; max = FF_MAX; break; | ||
558 | default: return -EINVAL; | ||
559 | } | ||
560 | bit_to_user(bits, max); | ||
561 | } | ||
562 | |||
563 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | ||
564 | bit_to_user(dev->key, KEY_MAX); | ||
565 | |||
566 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) | ||
567 | bit_to_user(dev->led, LED_MAX); | ||
568 | |||
569 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | ||
570 | bit_to_user(dev->snd, SND_MAX); | ||
571 | |||
572 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | ||
573 | int len; | ||
574 | if (!dev->name) return -ENOENT; | ||
575 | len = strlen(dev->name) + 1; | ||
576 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
577 | return copy_to_user(p, dev->name, len) ? -EFAULT : len; | ||
578 | } | ||
579 | |||
580 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | ||
581 | int len; | ||
582 | if (!dev->phys) return -ENOENT; | ||
583 | len = strlen(dev->phys) + 1; | ||
584 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
585 | return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | ||
586 | } | ||
587 | |||
588 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | ||
589 | int len; | ||
590 | if (!dev->uniq) return -ENOENT; | ||
591 | len = strlen(dev->uniq) + 1; | ||
592 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
593 | return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | ||
594 | } | ||
595 | |||
596 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | ||
597 | |||
598 | int t = _IOC_NR(cmd) & ABS_MAX; | ||
599 | |||
600 | abs.value = dev->abs[t]; | ||
601 | abs.minimum = dev->absmin[t]; | ||
602 | abs.maximum = dev->absmax[t]; | ||
603 | abs.fuzz = dev->absfuzz[t]; | ||
604 | abs.flat = dev->absflat[t]; | ||
605 | |||
606 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | ||
607 | return -EFAULT; | ||
608 | |||
609 | return 0; | ||
610 | } | ||
371 | } | 611 | } |
372 | 612 | ||
373 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 613 | if (_IOC_DIR(cmd) == _IOC_WRITE) { |
374 | 614 | ||
375 | int t = _IOC_NR(cmd) & ABS_MAX; | 615 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
376 | 616 | ||
377 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | 617 | int t = _IOC_NR(cmd) & ABS_MAX; |
378 | return -EFAULT; | ||
379 | 618 | ||
380 | dev->abs[t] = abs.value; | 619 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) |
381 | dev->absmin[t] = abs.minimum; | 620 | return -EFAULT; |
382 | dev->absmax[t] = abs.maximum; | ||
383 | dev->absfuzz[t] = abs.fuzz; | ||
384 | dev->absflat[t] = abs.flat; | ||
385 | 621 | ||
386 | return 0; | 622 | dev->abs[t] = abs.value; |
623 | dev->absmin[t] = abs.minimum; | ||
624 | dev->absmax[t] = abs.maximum; | ||
625 | dev->absfuzz[t] = abs.fuzz; | ||
626 | dev->absflat[t] = abs.flat; | ||
627 | |||
628 | return 0; | ||
629 | } | ||
387 | } | 630 | } |
388 | } | 631 | } |
389 | return -EINVAL; | 632 | return -EINVAL; |
390 | } | 633 | } |
634 | #endif | ||
391 | 635 | ||
392 | static struct file_operations evdev_fops = { | 636 | static struct file_operations evdev_fops = { |
393 | .owner = THIS_MODULE, | 637 | .owner = THIS_MODULE, |
@@ -396,7 +640,10 @@ static struct file_operations evdev_fops = { | |||
396 | .poll = evdev_poll, | 640 | .poll = evdev_poll, |
397 | .open = evdev_open, | 641 | .open = evdev_open, |
398 | .release = evdev_release, | 642 | .release = evdev_release, |
399 | .ioctl = evdev_ioctl, | 643 | .unlocked_ioctl = evdev_ioctl, |
644 | #ifdef CONFIG_COMPAT | ||
645 | .compat_ioctl = evdev_ioctl_compat, | ||
646 | #endif | ||
400 | .fasync = evdev_fasync, | 647 | .fasync = evdev_fasync, |
401 | .flush = evdev_flush | 648 | .flush = evdev_flush |
402 | }; | 649 | }; |
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig index 1d93f5092904..7524bd7d8b8f 100644 --- a/drivers/input/gameport/Kconfig +++ b/drivers/input/gameport/Kconfig | |||
@@ -49,22 +49,8 @@ config GAMEPORT_EMU10K1 | |||
49 | To compile this driver as a module, choose M here: the | 49 | To compile this driver as a module, choose M here: the |
50 | module will be called emu10k1-gp. | 50 | module will be called emu10k1-gp. |
51 | 51 | ||
52 | config GAMEPORT_VORTEX | ||
53 | tristate "Aureal Vortex, Vortex 2 gameport support" | ||
54 | depends on PCI | ||
55 | help | ||
56 | Say Y here if you have an Aureal Vortex 1 or 2 card and want | ||
57 | to use its gameport. | ||
58 | |||
59 | To compile this driver as a module, choose M here: the | ||
60 | module will be called vortex. | ||
61 | |||
62 | config GAMEPORT_FM801 | 52 | config GAMEPORT_FM801 |
63 | tristate "ForteMedia FM801 gameport support" | 53 | tristate "ForteMedia FM801 gameport support" |
64 | depends on PCI | 54 | depends on PCI |
65 | 55 | ||
66 | config GAMEPORT_CS461X | ||
67 | tristate "Crystal SoundFusion gameport support" | ||
68 | depends on PCI | ||
69 | |||
70 | endif | 56 | endif |
diff --git a/drivers/input/gameport/Makefile b/drivers/input/gameport/Makefile index 5367b4267adf..b6f6097bd8c4 100644 --- a/drivers/input/gameport/Makefile +++ b/drivers/input/gameport/Makefile | |||
@@ -5,9 +5,7 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_GAMEPORT) += gameport.o | 7 | obj-$(CONFIG_GAMEPORT) += gameport.o |
8 | obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o | ||
9 | obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o | 8 | obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o |
10 | obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o | 9 | obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o |
11 | obj-$(CONFIG_GAMEPORT_L4) += lightning.o | 10 | obj-$(CONFIG_GAMEPORT_L4) += lightning.o |
12 | obj-$(CONFIG_GAMEPORT_NS558) += ns558.o | 11 | obj-$(CONFIG_GAMEPORT_NS558) += ns558.o |
13 | obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o | ||
diff --git a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c deleted file mode 100644 index d4013ff98623..000000000000 --- a/drivers/input/gameport/cs461x.c +++ /dev/null | |||
@@ -1,322 +0,0 @@ | |||
1 | /* | ||
2 | The all defines and part of code (such as cs461x_*) are | ||
3 | contributed from ALSA 0.5.8 sources. | ||
4 | See http://www.alsa-project.org/ for sources | ||
5 | |||
6 | Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610 | ||
7 | */ | ||
8 | |||
9 | #include <asm/io.h> | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/ioport.h> | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/gameport.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/pci.h> | ||
18 | |||
19 | MODULE_AUTHOR("Victor Krapivin"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | /* | ||
23 | These options are experimental | ||
24 | |||
25 | #define CS461X_FULL_MAP | ||
26 | */ | ||
27 | |||
28 | |||
29 | #ifndef PCI_VENDOR_ID_CIRRUS | ||
30 | #define PCI_VENDOR_ID_CIRRUS 0x1013 | ||
31 | #endif | ||
32 | #ifndef PCI_DEVICE_ID_CIRRUS_4610 | ||
33 | #define PCI_DEVICE_ID_CIRRUS_4610 0x6001 | ||
34 | #endif | ||
35 | #ifndef PCI_DEVICE_ID_CIRRUS_4612 | ||
36 | #define PCI_DEVICE_ID_CIRRUS_4612 0x6003 | ||
37 | #endif | ||
38 | #ifndef PCI_DEVICE_ID_CIRRUS_4615 | ||
39 | #define PCI_DEVICE_ID_CIRRUS_4615 0x6004 | ||
40 | #endif | ||
41 | |||
42 | /* Registers */ | ||
43 | |||
44 | #define BA0_JSPT 0x00000480 | ||
45 | #define BA0_JSCTL 0x00000484 | ||
46 | #define BA0_JSC1 0x00000488 | ||
47 | #define BA0_JSC2 0x0000048C | ||
48 | #define BA0_JSIO 0x000004A0 | ||
49 | |||
50 | /* Bits for JSPT */ | ||
51 | |||
52 | #define JSPT_CAX 0x00000001 | ||
53 | #define JSPT_CAY 0x00000002 | ||
54 | #define JSPT_CBX 0x00000004 | ||
55 | #define JSPT_CBY 0x00000008 | ||
56 | #define JSPT_BA1 0x00000010 | ||
57 | #define JSPT_BA2 0x00000020 | ||
58 | #define JSPT_BB1 0x00000040 | ||
59 | #define JSPT_BB2 0x00000080 | ||
60 | |||
61 | /* Bits for JSCTL */ | ||
62 | |||
63 | #define JSCTL_SP_MASK 0x00000003 | ||
64 | #define JSCTL_SP_SLOW 0x00000000 | ||
65 | #define JSCTL_SP_MEDIUM_SLOW 0x00000001 | ||
66 | #define JSCTL_SP_MEDIUM_FAST 0x00000002 | ||
67 | #define JSCTL_SP_FAST 0x00000003 | ||
68 | #define JSCTL_ARE 0x00000004 | ||
69 | |||
70 | /* Data register pairs masks */ | ||
71 | |||
72 | #define JSC1_Y1V_MASK 0x0000FFFF | ||
73 | #define JSC1_X1V_MASK 0xFFFF0000 | ||
74 | #define JSC1_Y1V_SHIFT 0 | ||
75 | #define JSC1_X1V_SHIFT 16 | ||
76 | #define JSC2_Y2V_MASK 0x0000FFFF | ||
77 | #define JSC2_X2V_MASK 0xFFFF0000 | ||
78 | #define JSC2_Y2V_SHIFT 0 | ||
79 | #define JSC2_X2V_SHIFT 16 | ||
80 | |||
81 | /* JS GPIO */ | ||
82 | |||
83 | #define JSIO_DAX 0x00000001 | ||
84 | #define JSIO_DAY 0x00000002 | ||
85 | #define JSIO_DBX 0x00000004 | ||
86 | #define JSIO_DBY 0x00000008 | ||
87 | #define JSIO_AXOE 0x00000010 | ||
88 | #define JSIO_AYOE 0x00000020 | ||
89 | #define JSIO_BXOE 0x00000040 | ||
90 | #define JSIO_BYOE 0x00000080 | ||
91 | |||
92 | /* | ||
93 | The card initialization code is obfuscated; the module cs461x | ||
94 | need to be loaded after ALSA modules initialized and something | ||
95 | played on the CS 4610 chip (see sources for details of CS4610 | ||
96 | initialization code from ALSA) | ||
97 | */ | ||
98 | |||
99 | /* Card specific definitions */ | ||
100 | |||
101 | #define CS461X_BA0_SIZE 0x2000 | ||
102 | #define CS461X_BA1_DATA0_SIZE 0x3000 | ||
103 | #define CS461X_BA1_DATA1_SIZE 0x3800 | ||
104 | #define CS461X_BA1_PRG_SIZE 0x7000 | ||
105 | #define CS461X_BA1_REG_SIZE 0x0100 | ||
106 | |||
107 | #define BA1_SP_DMEM0 0x00000000 | ||
108 | #define BA1_SP_DMEM1 0x00010000 | ||
109 | #define BA1_SP_PMEM 0x00020000 | ||
110 | #define BA1_SP_REG 0x00030000 | ||
111 | |||
112 | #define BA1_DWORD_SIZE (13 * 1024 + 512) | ||
113 | #define BA1_MEMORY_COUNT 3 | ||
114 | |||
115 | /* | ||
116 | Only one CS461x card is still suppoted; the code requires | ||
117 | redesign to avoid this limitatuion. | ||
118 | */ | ||
119 | |||
120 | static unsigned long ba0_addr; | ||
121 | static unsigned int __iomem *ba0; | ||
122 | |||
123 | #ifdef CS461X_FULL_MAP | ||
124 | static unsigned long ba1_addr; | ||
125 | static union ba1_t { | ||
126 | struct { | ||
127 | unsigned int __iomem *data0; | ||
128 | unsigned int __iomem *data1; | ||
129 | unsigned int __iomem *pmem; | ||
130 | unsigned int __iomem *reg; | ||
131 | } name; | ||
132 | unsigned int __iomem *idx[4]; | ||
133 | } ba1; | ||
134 | |||
135 | static void cs461x_poke(unsigned long reg, unsigned int val) | ||
136 | { | ||
137 | writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); | ||
138 | } | ||
139 | |||
140 | static unsigned int cs461x_peek(unsigned long reg) | ||
141 | { | ||
142 | return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); | ||
143 | } | ||
144 | |||
145 | #endif | ||
146 | |||
147 | static void cs461x_pokeBA0(unsigned long reg, unsigned int val) | ||
148 | { | ||
149 | writel(val, &ba0[reg >> 2]); | ||
150 | } | ||
151 | |||
152 | static unsigned int cs461x_peekBA0(unsigned long reg) | ||
153 | { | ||
154 | return readl(&ba0[reg >> 2]); | ||
155 | } | ||
156 | |||
157 | static int cs461x_free(struct pci_dev *pdev) | ||
158 | { | ||
159 | struct gameport *port = pci_get_drvdata(pdev); | ||
160 | |||
161 | if (port) | ||
162 | gameport_unregister_port(port); | ||
163 | |||
164 | if (ba0) iounmap(ba0); | ||
165 | #ifdef CS461X_FULL_MAP | ||
166 | if (ba1.name.data0) iounmap(ba1.name.data0); | ||
167 | if (ba1.name.data1) iounmap(ba1.name.data1); | ||
168 | if (ba1.name.pmem) iounmap(ba1.name.pmem); | ||
169 | if (ba1.name.reg) iounmap(ba1.name.reg); | ||
170 | #endif | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void cs461x_gameport_trigger(struct gameport *gameport) | ||
175 | { | ||
176 | cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); | ||
177 | } | ||
178 | |||
179 | static unsigned char cs461x_gameport_read(struct gameport *gameport) | ||
180 | { | ||
181 | return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io); | ||
182 | } | ||
183 | |||
184 | static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) | ||
185 | { | ||
186 | unsigned js1, js2, jst; | ||
187 | |||
188 | js1 = cs461x_peekBA0(BA0_JSC1); | ||
189 | js2 = cs461x_peekBA0(BA0_JSC2); | ||
190 | jst = cs461x_peekBA0(BA0_JSPT); | ||
191 | |||
192 | *buttons = (~jst >> 4) & 0x0F; | ||
193 | |||
194 | axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; | ||
195 | axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; | ||
196 | axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; | ||
197 | axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; | ||
198 | |||
199 | for(jst=0;jst<4;++jst) | ||
200 | if(axes[jst]==0xFFFF) axes[jst] = -1; | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int cs461x_gameport_open(struct gameport *gameport, int mode) | ||
205 | { | ||
206 | switch (mode) { | ||
207 | case GAMEPORT_MODE_COOKED: | ||
208 | case GAMEPORT_MODE_RAW: | ||
209 | return 0; | ||
210 | default: | ||
211 | return -1; | ||
212 | } | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static struct pci_device_id cs461x_pci_tbl[] = { | ||
217 | { PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */ | ||
218 | { PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */ | ||
219 | { PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */ | ||
220 | { 0, } | ||
221 | }; | ||
222 | MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl); | ||
223 | |||
224 | static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
225 | { | ||
226 | int rc; | ||
227 | struct gameport* port; | ||
228 | |||
229 | rc = pci_enable_device(pdev); | ||
230 | if (rc) { | ||
231 | printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n", | ||
232 | pdev->bus->number, pdev->devfn, rc); | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | ba0_addr = pci_resource_start(pdev, 0); | ||
237 | #ifdef CS461X_FULL_MAP | ||
238 | ba1_addr = pci_resource_start(pdev, 1); | ||
239 | #endif | ||
240 | if (ba0_addr == 0 || ba0_addr == ~0 | ||
241 | #ifdef CS461X_FULL_MAP | ||
242 | || ba1_addr == 0 || ba1_addr == ~0 | ||
243 | #endif | ||
244 | ) { | ||
245 | printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr); | ||
246 | #ifdef CS461X_FULL_MAP | ||
247 | printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr); | ||
248 | #endif | ||
249 | cs461x_free(pdev); | ||
250 | return -ENOMEM; | ||
251 | } | ||
252 | |||
253 | ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE); | ||
254 | #ifdef CS461X_FULL_MAP | ||
255 | ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE); | ||
256 | ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE); | ||
257 | ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); | ||
258 | ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); | ||
259 | |||
260 | if (ba0 == NULL || ba1.name.data0 == NULL || | ||
261 | ba1.name.data1 == NULL || ba1.name.pmem == NULL || | ||
262 | ba1.name.reg == NULL) { | ||
263 | cs461x_free(pdev); | ||
264 | return -ENOMEM; | ||
265 | } | ||
266 | #else | ||
267 | if (ba0 == NULL) { | ||
268 | cs461x_free(pdev); | ||
269 | return -ENOMEM; | ||
270 | } | ||
271 | #endif | ||
272 | |||
273 | if (!(port = gameport_allocate_port())) { | ||
274 | printk(KERN_ERR "cs461x: Memory allocation failed\n"); | ||
275 | cs461x_free(pdev); | ||
276 | return -ENOMEM; | ||
277 | } | ||
278 | |||
279 | pci_set_drvdata(pdev, port); | ||
280 | |||
281 | port->open = cs461x_gameport_open; | ||
282 | port->trigger = cs461x_gameport_trigger; | ||
283 | port->read = cs461x_gameport_read; | ||
284 | port->cooked_read = cs461x_gameport_cooked_read; | ||
285 | |||
286 | gameport_set_name(port, "CS416x"); | ||
287 | gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); | ||
288 | port->dev.parent = &pdev->dev; | ||
289 | |||
290 | cs461x_pokeBA0(BA0_JSIO, 0xFF); // ? | ||
291 | cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); | ||
292 | |||
293 | gameport_register_port(port); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static void __devexit cs461x_pci_remove(struct pci_dev *pdev) | ||
299 | { | ||
300 | cs461x_free(pdev); | ||
301 | } | ||
302 | |||
303 | static struct pci_driver cs461x_pci_driver = { | ||
304 | .name = "CS461x_gameport", | ||
305 | .id_table = cs461x_pci_tbl, | ||
306 | .probe = cs461x_pci_probe, | ||
307 | .remove = __devexit_p(cs461x_pci_remove), | ||
308 | }; | ||
309 | |||
310 | static int __init cs461x_init(void) | ||
311 | { | ||
312 | return pci_register_driver(&cs461x_pci_driver); | ||
313 | } | ||
314 | |||
315 | static void __exit cs461x_exit(void) | ||
316 | { | ||
317 | pci_unregister_driver(&cs461x_pci_driver); | ||
318 | } | ||
319 | |||
320 | module_init(cs461x_init); | ||
321 | module_exit(cs461x_exit); | ||
322 | |||
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index 7c5c6318eeb9..1ab5f2dc8a2a 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c | |||
@@ -258,18 +258,18 @@ static int __init ns558_init(void) | |||
258 | { | 258 | { |
259 | int i = 0; | 259 | int i = 0; |
260 | 260 | ||
261 | if (pnp_register_driver(&ns558_pnp_driver) >= 0) | ||
262 | pnp_registered = 1; | ||
263 | |||
261 | /* | 264 | /* |
262 | * Probe ISA ports first so that PnP gets to choose free port addresses | 265 | * Probe ISA ports after PnP, so that PnP ports that are already |
263 | * not occupied by the ISA ports. | 266 | * enabled get detected as PnP. This may be suboptimal in multi-device |
267 | * configurations, but saves hassle with simple setups. | ||
264 | */ | 268 | */ |
265 | 269 | ||
266 | while (ns558_isa_portlist[i]) | 270 | while (ns558_isa_portlist[i]) |
267 | ns558_isa_probe(ns558_isa_portlist[i++]); | 271 | ns558_isa_probe(ns558_isa_portlist[i++]); |
268 | 272 | ||
269 | if (pnp_register_driver(&ns558_pnp_driver) >= 0) | ||
270 | pnp_registered = 1; | ||
271 | |||
272 | |||
273 | return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; | 273 | return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; |
274 | } | 274 | } |
275 | 275 | ||
diff --git a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c deleted file mode 100644 index 36b0309c8bf6..000000000000 --- a/drivers/input/gameport/vortex.c +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | /* | ||
2 | * $Id: vortex.c,v 1.5 2002/07/01 15:39:30 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
5 | * | ||
6 | * Based on the work of: | ||
7 | * Raymond Ingles | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Trident 4DWave and Aureal Vortex gameport driver for Linux | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | * | ||
29 | * Should you need to contact me, the author, you can do so either by | ||
30 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
31 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
32 | */ | ||
33 | |||
34 | #include <asm/io.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/ioport.h> | ||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/pci.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <linux/delay.h> | ||
44 | #include <linux/gameport.h> | ||
45 | |||
46 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | ||
47 | MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver"); | ||
48 | MODULE_LICENSE("GPL"); | ||
49 | |||
50 | #define VORTEX_GCR 0x0c /* Gameport control register */ | ||
51 | #define VORTEX_LEG 0x08 /* Legacy port location */ | ||
52 | #define VORTEX_AXD 0x10 /* Axes start */ | ||
53 | #define VORTEX_DATA_WAIT 20 /* 20 ms */ | ||
54 | |||
55 | struct vortex { | ||
56 | struct gameport *gameport; | ||
57 | struct pci_dev *dev; | ||
58 | unsigned char __iomem *base; | ||
59 | unsigned char __iomem *io; | ||
60 | }; | ||
61 | |||
62 | static unsigned char vortex_read(struct gameport *gameport) | ||
63 | { | ||
64 | struct vortex *vortex = gameport->port_data; | ||
65 | return readb(vortex->io + VORTEX_LEG); | ||
66 | } | ||
67 | |||
68 | static void vortex_trigger(struct gameport *gameport) | ||
69 | { | ||
70 | struct vortex *vortex = gameport->port_data; | ||
71 | writeb(0xff, vortex->io + VORTEX_LEG); | ||
72 | } | ||
73 | |||
74 | static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons) | ||
75 | { | ||
76 | struct vortex *vortex = gameport->port_data; | ||
77 | int i; | ||
78 | |||
79 | *buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf; | ||
80 | |||
81 | for (i = 0; i < 4; i++) { | ||
82 | axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32)); | ||
83 | if (axes[i] == 0x1fff) axes[i] = -1; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int vortex_open(struct gameport *gameport, int mode) | ||
90 | { | ||
91 | struct vortex *vortex = gameport->port_data; | ||
92 | |||
93 | switch (mode) { | ||
94 | case GAMEPORT_MODE_COOKED: | ||
95 | writeb(0x40, vortex->io + VORTEX_GCR); | ||
96 | msleep(VORTEX_DATA_WAIT); | ||
97 | return 0; | ||
98 | case GAMEPORT_MODE_RAW: | ||
99 | writeb(0x00, vortex->io + VORTEX_GCR); | ||
100 | return 0; | ||
101 | default: | ||
102 | return -1; | ||
103 | } | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
109 | { | ||
110 | struct vortex *vortex; | ||
111 | struct gameport *port; | ||
112 | int i; | ||
113 | |||
114 | vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL); | ||
115 | port = gameport_allocate_port(); | ||
116 | if (!vortex || !port) { | ||
117 | printk(KERN_ERR "vortex: Memory allocation failed.\n"); | ||
118 | kfree(vortex); | ||
119 | gameport_free_port(port); | ||
120 | return -ENOMEM; | ||
121 | } | ||
122 | |||
123 | for (i = 0; i < 6; i++) | ||
124 | if (~pci_resource_flags(dev, i) & IORESOURCE_IO) | ||
125 | break; | ||
126 | |||
127 | pci_enable_device(dev); | ||
128 | |||
129 | vortex->dev = dev; | ||
130 | vortex->gameport = port; | ||
131 | vortex->base = ioremap(pci_resource_start(vortex->dev, i), | ||
132 | pci_resource_len(vortex->dev, i)); | ||
133 | vortex->io = vortex->base + id->driver_data; | ||
134 | |||
135 | pci_set_drvdata(dev, vortex); | ||
136 | |||
137 | port->port_data = vortex; | ||
138 | port->fuzz = 64; | ||
139 | |||
140 | gameport_set_name(port, "AU88x0"); | ||
141 | gameport_set_phys(port, "pci%s/gameport0", pci_name(dev)); | ||
142 | port->dev.parent = &dev->dev; | ||
143 | port->read = vortex_read; | ||
144 | port->trigger = vortex_trigger; | ||
145 | port->cooked_read = vortex_cooked_read; | ||
146 | port->open = vortex_open; | ||
147 | |||
148 | gameport_register_port(port); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static void __devexit vortex_remove(struct pci_dev *dev) | ||
154 | { | ||
155 | struct vortex *vortex = pci_get_drvdata(dev); | ||
156 | |||
157 | gameport_unregister_port(vortex->gameport); | ||
158 | iounmap(vortex->base); | ||
159 | kfree(vortex); | ||
160 | } | ||
161 | |||
162 | static struct pci_device_id vortex_id_table[] = { | ||
163 | { 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 }, | ||
164 | { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 }, | ||
165 | { 0 } | ||
166 | }; | ||
167 | |||
168 | static struct pci_driver vortex_driver = { | ||
169 | .name = "vortex_gameport", | ||
170 | .id_table = vortex_id_table, | ||
171 | .probe = vortex_probe, | ||
172 | .remove = __devexit_p(vortex_remove), | ||
173 | }; | ||
174 | |||
175 | static int __init vortex_init(void) | ||
176 | { | ||
177 | return pci_register_driver(&vortex_driver); | ||
178 | } | ||
179 | |||
180 | static void __exit vortex_exit(void) | ||
181 | { | ||
182 | pci_unregister_driver(&vortex_driver); | ||
183 | } | ||
184 | |||
185 | module_init(vortex_init); | ||
186 | module_exit(vortex_exit); | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index 83c77c990dda..7c4b4d37b3e6 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -219,10 +219,24 @@ void input_release_device(struct input_handle *handle) | |||
219 | 219 | ||
220 | int input_open_device(struct input_handle *handle) | 220 | int input_open_device(struct input_handle *handle) |
221 | { | 221 | { |
222 | struct input_dev *dev = handle->dev; | ||
223 | int err; | ||
224 | |||
225 | err = down_interruptible(&dev->sem); | ||
226 | if (err) | ||
227 | return err; | ||
228 | |||
222 | handle->open++; | 229 | handle->open++; |
223 | if (handle->dev->open) | 230 | |
224 | return handle->dev->open(handle->dev); | 231 | if (!dev->users++ && dev->open) |
225 | return 0; | 232 | err = dev->open(dev); |
233 | |||
234 | if (err) | ||
235 | handle->open--; | ||
236 | |||
237 | up(&dev->sem); | ||
238 | |||
239 | return err; | ||
226 | } | 240 | } |
227 | 241 | ||
228 | int input_flush_device(struct input_handle* handle, struct file* file) | 242 | int input_flush_device(struct input_handle* handle, struct file* file) |
@@ -235,10 +249,17 @@ int input_flush_device(struct input_handle* handle, struct file* file) | |||
235 | 249 | ||
236 | void input_close_device(struct input_handle *handle) | 250 | void input_close_device(struct input_handle *handle) |
237 | { | 251 | { |
252 | struct input_dev *dev = handle->dev; | ||
253 | |||
238 | input_release_device(handle); | 254 | input_release_device(handle); |
239 | if (handle->dev->close) | 255 | |
240 | handle->dev->close(handle->dev); | 256 | down(&dev->sem); |
257 | |||
258 | if (!--dev->users && dev->close) | ||
259 | dev->close(dev); | ||
241 | handle->open--; | 260 | handle->open--; |
261 | |||
262 | up(&dev->sem); | ||
242 | } | 263 | } |
243 | 264 | ||
244 | static void input_link_handle(struct input_handle *handle) | 265 | static void input_link_handle(struct input_handle *handle) |
@@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev) | |||
415 | 436 | ||
416 | set_bit(EV_SYN, dev->evbit); | 437 | set_bit(EV_SYN, dev->evbit); |
417 | 438 | ||
439 | init_MUTEX(&dev->sem); | ||
440 | |||
418 | /* | 441 | /* |
419 | * If delay and period are pre-set by the driver, then autorepeating | 442 | * If delay and period are pre-set by the driver, then autorepeating |
420 | * is handled by the driver itself and we don't do it in input.c. | 443 | * is handled by the driver itself and we don't do it in input.c. |
@@ -674,6 +697,8 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in | |||
674 | return (count > cnt) ? cnt : count; | 697 | return (count > cnt) ? cnt : count; |
675 | } | 698 | } |
676 | 699 | ||
700 | static struct file_operations input_fileops; | ||
701 | |||
677 | static int __init input_proc_init(void) | 702 | static int __init input_proc_init(void) |
678 | { | 703 | { |
679 | struct proc_dir_entry *entry; | 704 | struct proc_dir_entry *entry; |
@@ -688,6 +713,8 @@ static int __init input_proc_init(void) | |||
688 | return -ENOMEM; | 713 | return -ENOMEM; |
689 | } | 714 | } |
690 | entry->owner = THIS_MODULE; | 715 | entry->owner = THIS_MODULE; |
716 | input_fileops = *entry->proc_fops; | ||
717 | entry->proc_fops = &input_fileops; | ||
691 | entry->proc_fops->poll = input_devices_poll; | 718 | entry->proc_fops->poll = input_devices_poll; |
692 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); | 719 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); |
693 | if (entry == NULL) { | 720 | if (entry == NULL) { |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 39775fc380c7..ff8e1bbd0e13 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
285 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); | 285 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); |
286 | } | 286 | } |
287 | 287 | ||
288 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 288 | static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) |
289 | { | 289 | { |
290 | struct joydev_list *list = file->private_data; | ||
291 | struct joydev *joydev = list->joydev; | ||
292 | struct input_dev *dev = joydev->handle.dev; | 290 | struct input_dev *dev = joydev->handle.dev; |
293 | void __user *argp = (void __user *)arg; | ||
294 | int i, j; | 291 | int i, j; |
295 | 292 | ||
296 | if (!joydev->exist) return -ENODEV; | ||
297 | |||
298 | switch (cmd) { | 293 | switch (cmd) { |
299 | 294 | ||
300 | case JS_SET_CAL: | 295 | case JS_SET_CAL: |
301 | return copy_from_user(&joydev->glue.JS_CORR, argp, | 296 | return copy_from_user(&joydev->glue.JS_CORR, argp, |
302 | sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; | 297 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
303 | case JS_GET_CAL: | 298 | case JS_GET_CAL: |
304 | return copy_to_user(argp, &joydev->glue.JS_CORR, | 299 | return copy_to_user(argp, &joydev->glue.JS_CORR, |
305 | sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; | 300 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
306 | case JS_SET_TIMEOUT: | 301 | case JS_SET_TIMEOUT: |
307 | return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); | 302 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
308 | case JS_GET_TIMEOUT: | 303 | case JS_GET_TIMEOUT: |
309 | return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); | 304 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
310 | case JS_SET_TIMELIMIT: | ||
311 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
312 | case JS_GET_TIMELIMIT: | ||
313 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
314 | case JS_SET_ALL: | ||
315 | return copy_from_user(&joydev->glue, argp, | ||
316 | sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; | ||
317 | case JS_GET_ALL: | ||
318 | return copy_to_user(argp, &joydev->glue, | ||
319 | sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; | ||
320 | 305 | ||
321 | case JSIOCGVERSION: | 306 | case JSIOCGVERSION: |
322 | return put_user(JS_VERSION, (__u32 __user *) arg); | 307 | return put_user(JS_VERSION, (__u32 __user *) argp); |
323 | case JSIOCGAXES: | 308 | case JSIOCGAXES: |
324 | return put_user(joydev->nabs, (__u8 __user *) arg); | 309 | return put_user(joydev->nabs, (__u8 __user *) argp); |
325 | case JSIOCGBUTTONS: | 310 | case JSIOCGBUTTONS: |
326 | return put_user(joydev->nkey, (__u8 __user *) arg); | 311 | return put_user(joydev->nkey, (__u8 __user *) argp); |
327 | case JSIOCSCORR: | 312 | case JSIOCSCORR: |
328 | if (copy_from_user(joydev->corr, argp, | 313 | if (copy_from_user(joydev->corr, argp, |
329 | sizeof(struct js_corr) * joydev->nabs)) | 314 | sizeof(joydev->corr[0]) * joydev->nabs)) |
330 | return -EFAULT; | 315 | return -EFAULT; |
331 | for (i = 0; i < joydev->nabs; i++) { | 316 | for (i = 0; i < joydev->nabs; i++) { |
332 | j = joydev->abspam[i]; | 317 | j = joydev->abspam[i]; |
@@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
335 | return 0; | 320 | return 0; |
336 | case JSIOCGCORR: | 321 | case JSIOCGCORR: |
337 | return copy_to_user(argp, joydev->corr, | 322 | return copy_to_user(argp, joydev->corr, |
338 | sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0; | 323 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; |
339 | case JSIOCSAXMAP: | 324 | case JSIOCSAXMAP: |
340 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) | 325 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) |
341 | return -EFAULT; | 326 | return -EFAULT; |
@@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
371 | return -EINVAL; | 356 | return -EINVAL; |
372 | } | 357 | } |
373 | 358 | ||
359 | #ifdef CONFIG_COMPAT | ||
360 | static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
361 | { | ||
362 | struct joydev_list *list = file->private_data; | ||
363 | struct joydev *joydev = list->joydev; | ||
364 | void __user *argp = (void __user *)arg; | ||
365 | s32 tmp32; | ||
366 | struct JS_DATA_SAVE_TYPE_32 ds32; | ||
367 | int err; | ||
368 | |||
369 | if (!joydev->exist) return -ENODEV; | ||
370 | switch(cmd) { | ||
371 | case JS_SET_TIMELIMIT: | ||
372 | err = get_user(tmp32, (s32 __user *) arg); | ||
373 | if (err == 0) | ||
374 | joydev->glue.JS_TIMELIMIT = tmp32; | ||
375 | break; | ||
376 | case JS_GET_TIMELIMIT: | ||
377 | tmp32 = joydev->glue.JS_TIMELIMIT; | ||
378 | err = put_user(tmp32, (s32 __user *) arg); | ||
379 | break; | ||
380 | |||
381 | case JS_SET_ALL: | ||
382 | err = copy_from_user(&ds32, argp, | ||
383 | sizeof(ds32)) ? -EFAULT : 0; | ||
384 | if (err == 0) { | ||
385 | joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; | ||
386 | joydev->glue.BUSY = ds32.BUSY; | ||
387 | joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; | ||
388 | joydev->glue.JS_TIMELIMIT = ds32.JS_TIMELIMIT; | ||
389 | joydev->glue.JS_SAVE = ds32.JS_SAVE; | ||
390 | joydev->glue.JS_CORR = ds32.JS_CORR; | ||
391 | } | ||
392 | break; | ||
393 | |||
394 | case JS_GET_ALL: | ||
395 | ds32.JS_TIMEOUT = joydev->glue.JS_TIMEOUT; | ||
396 | ds32.BUSY = joydev->glue.BUSY; | ||
397 | ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME; | ||
398 | ds32.JS_TIMELIMIT = joydev->glue.JS_TIMELIMIT; | ||
399 | ds32.JS_SAVE = joydev->glue.JS_SAVE; | ||
400 | ds32.JS_CORR = joydev->glue.JS_CORR; | ||
401 | |||
402 | err = copy_to_user(argp, &ds32, | ||
403 | sizeof(ds32)) ? -EFAULT : 0; | ||
404 | break; | ||
405 | |||
406 | default: | ||
407 | err = joydev_ioctl_common(joydev, cmd, argp); | ||
408 | } | ||
409 | return err; | ||
410 | } | ||
411 | #endif /* CONFIG_COMPAT */ | ||
412 | |||
413 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
414 | { | ||
415 | struct joydev_list *list = file->private_data; | ||
416 | struct joydev *joydev = list->joydev; | ||
417 | void __user *argp = (void __user *)arg; | ||
418 | |||
419 | if (!joydev->exist) return -ENODEV; | ||
420 | |||
421 | switch(cmd) { | ||
422 | case JS_SET_TIMELIMIT: | ||
423 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
424 | case JS_GET_TIMELIMIT: | ||
425 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
426 | case JS_SET_ALL: | ||
427 | return copy_from_user(&joydev->glue, argp, | ||
428 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
429 | case JS_GET_ALL: | ||
430 | return copy_to_user(argp, &joydev->glue, | ||
431 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
432 | default: | ||
433 | return joydev_ioctl_common(joydev, cmd, argp); | ||
434 | } | ||
435 | } | ||
436 | |||
374 | static struct file_operations joydev_fops = { | 437 | static struct file_operations joydev_fops = { |
375 | .owner = THIS_MODULE, | 438 | .owner = THIS_MODULE, |
376 | .read = joydev_read, | 439 | .read = joydev_read, |
@@ -379,6 +442,9 @@ static struct file_operations joydev_fops = { | |||
379 | .open = joydev_open, | 442 | .open = joydev_open, |
380 | .release = joydev_release, | 443 | .release = joydev_release, |
381 | .ioctl = joydev_ioctl, | 444 | .ioctl = joydev_ioctl, |
445 | #ifdef CONFIG_COMPAT | ||
446 | .compat_ioctl = joydev_compat_ioctl, | ||
447 | #endif | ||
382 | .fasync = joydev_fasync, | 448 | .fasync = joydev_fasync, |
383 | }; | 449 | }; |
384 | 450 | ||
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index ad39fe4bf35f..bf34f75b9467 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
@@ -185,7 +185,7 @@ static void a3d_poll(struct gameport *gameport) | |||
185 | a3d->reads++; | 185 | a3d->reads++; |
186 | if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length || | 186 | if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length || |
187 | data[0] != a3d->mode || a3d_csum(data, a3d->length)) | 187 | data[0] != a3d->mode || a3d_csum(data, a3d->length)) |
188 | a3d->bads++; | 188 | a3d->bads++; |
189 | else | 189 | else |
190 | a3d_read(a3d, data); | 190 | a3d_read(a3d, data); |
191 | } | 191 | } |
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 83f6dafc1716..265962956c63 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c | |||
@@ -82,7 +82,7 @@ static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ }; | |||
82 | static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; | 82 | static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; |
83 | 83 | ||
84 | static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }; | 84 | static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }; |
85 | static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; | 85 | static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; |
86 | static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; | 86 | static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; |
87 | static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; | 87 | static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; |
88 | 88 | ||
@@ -183,7 +183,7 @@ static void adi_move_bits(struct adi_port *port, int length) | |||
183 | int i; | 183 | int i; |
184 | struct adi *adi = port->adi; | 184 | struct adi *adi = port->adi; |
185 | 185 | ||
186 | adi[0].idx = adi[1].idx = 0; | 186 | adi[0].idx = adi[1].idx = 0; |
187 | 187 | ||
188 | if (adi[0].ret <= 0 || adi[1].ret <= 0) return; | 188 | if (adi[0].ret <= 0 || adi[1].ret <= 0) return; |
189 | if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return; | 189 | if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return; |
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index cf36ca9b92f3..033456bb9fe0 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c | |||
@@ -51,7 +51,8 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is | |||
51 | 51 | ||
52 | __obsolete_setup("amijoy="); | 52 | __obsolete_setup("amijoy="); |
53 | 53 | ||
54 | static int amijoy_used[2] = { 0, 0 }; | 54 | static int amijoy_used; |
55 | static DECLARE_MUTEX(amijoy_sem); | ||
55 | static struct input_dev amijoy_dev[2]; | 56 | static struct input_dev amijoy_dev[2]; |
56 | static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; | 57 | static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; |
57 | 58 | ||
@@ -84,26 +85,30 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp) | |||
84 | 85 | ||
85 | static int amijoy_open(struct input_dev *dev) | 86 | static int amijoy_open(struct input_dev *dev) |
86 | { | 87 | { |
87 | int *used = dev->private; | 88 | int err; |
88 | 89 | ||
89 | if ((*used)++) | 90 | err = down_interruptible(&amijoy_sem); |
90 | return 0; | 91 | if (err) |
92 | return err; | ||
91 | 93 | ||
92 | if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { | 94 | if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { |
93 | (*used)--; | ||
94 | printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); | 95 | printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); |
95 | return -EBUSY; | 96 | err = -EBUSY; |
97 | goto out; | ||
96 | } | 98 | } |
97 | 99 | ||
98 | return 0; | 100 | amijoy_used++; |
101 | out: | ||
102 | up(&amijoy_sem); | ||
103 | return err; | ||
99 | } | 104 | } |
100 | 105 | ||
101 | static void amijoy_close(struct input_dev *dev) | 106 | static void amijoy_close(struct input_dev *dev) |
102 | { | 107 | { |
103 | int *used = dev->private; | 108 | down(&amijoysem); |
104 | 109 | if (!--amijoy_used) | |
105 | if (!--(*used)) | ||
106 | free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); | 110 | free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); |
111 | up(&amijoy_sem); | ||
107 | } | 112 | } |
108 | 113 | ||
109 | static int __init amijoy_init(void) | 114 | static int __init amijoy_init(void) |
@@ -138,8 +143,6 @@ static int __init amijoy_init(void) | |||
138 | amijoy_dev[i].id.product = 0x0003; | 143 | amijoy_dev[i].id.product = 0x0003; |
139 | amijoy_dev[i].id.version = 0x0100; | 144 | amijoy_dev[i].id.version = 0x0100; |
140 | 145 | ||
141 | amijoy_dev[i].private = amijoy_used + i; | ||
142 | |||
143 | input_register_device(amijoy_dev + i); | 146 | input_register_device(amijoy_dev + i); |
144 | printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); | 147 | printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); |
145 | } | 148 | } |
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index cfdd3acf06a1..fbd3eed07f90 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c | |||
@@ -87,7 +87,7 @@ __obsolete_setup("db9_3="); | |||
87 | #define DB9_NORMAL 0x0a | 87 | #define DB9_NORMAL 0x0a |
88 | #define DB9_NOSELECT 0x08 | 88 | #define DB9_NOSELECT 0x08 |
89 | 89 | ||
90 | #define DB9_MAX_DEVICES 2 | 90 | #define DB9_MAX_DEVICES 2 |
91 | 91 | ||
92 | #define DB9_GENESIS6_DELAY 14 | 92 | #define DB9_GENESIS6_DELAY 14 |
93 | #define DB9_REFRESH_TIME HZ/100 | 93 | #define DB9_REFRESH_TIME HZ/100 |
@@ -98,6 +98,7 @@ struct db9 { | |||
98 | struct pardevice *pd; | 98 | struct pardevice *pd; |
99 | int mode; | 99 | int mode; |
100 | int used; | 100 | int used; |
101 | struct semaphore sem; | ||
101 | char phys[2][32]; | 102 | char phys[2][32]; |
102 | }; | 103 | }; |
103 | 104 | ||
@@ -503,6 +504,11 @@ static int db9_open(struct input_dev *dev) | |||
503 | { | 504 | { |
504 | struct db9 *db9 = dev->private; | 505 | struct db9 *db9 = dev->private; |
505 | struct parport *port = db9->pd->port; | 506 | struct parport *port = db9->pd->port; |
507 | int err; | ||
508 | |||
509 | err = down_interruptible(&db9->sem); | ||
510 | if (err) | ||
511 | return err; | ||
506 | 512 | ||
507 | if (!db9->used++) { | 513 | if (!db9->used++) { |
508 | parport_claim(db9->pd); | 514 | parport_claim(db9->pd); |
@@ -514,6 +520,7 @@ static int db9_open(struct input_dev *dev) | |||
514 | mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); | 520 | mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); |
515 | } | 521 | } |
516 | 522 | ||
523 | up(&db9->sem); | ||
517 | return 0; | 524 | return 0; |
518 | } | 525 | } |
519 | 526 | ||
@@ -522,12 +529,14 @@ static void db9_close(struct input_dev *dev) | |||
522 | struct db9 *db9 = dev->private; | 529 | struct db9 *db9 = dev->private; |
523 | struct parport *port = db9->pd->port; | 530 | struct parport *port = db9->pd->port; |
524 | 531 | ||
532 | down(&db9->sem); | ||
525 | if (!--db9->used) { | 533 | if (!--db9->used) { |
526 | del_timer(&db9->timer); | 534 | del_timer_sync(&db9->timer); |
527 | parport_write_control(port, 0x00); | 535 | parport_write_control(port, 0x00); |
528 | parport_data_forward(port); | 536 | parport_data_forward(port); |
529 | parport_release(db9->pd); | 537 | parport_release(db9->pd); |
530 | } | 538 | } |
539 | up(&db9->sem); | ||
531 | } | 540 | } |
532 | 541 | ||
533 | static struct db9 __init *db9_probe(int *config, int nargs) | 542 | static struct db9 __init *db9_probe(int *config, int nargs) |
@@ -563,12 +572,12 @@ static struct db9 __init *db9_probe(int *config, int nargs) | |||
563 | } | 572 | } |
564 | } | 573 | } |
565 | 574 | ||
566 | if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) { | 575 | if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) { |
567 | parport_put_port(pp); | 576 | parport_put_port(pp); |
568 | return NULL; | 577 | return NULL; |
569 | } | 578 | } |
570 | memset(db9, 0, sizeof(struct db9)); | ||
571 | 579 | ||
580 | init_MUTEX(&db9->sem); | ||
572 | db9->mode = config[1]; | 581 | db9->mode = config[1]; |
573 | init_timer(&db9->timer); | 582 | init_timer(&db9->timer); |
574 | db9->timer.data = (long) db9; | 583 | db9->timer.data = (long) db9; |
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 8732f52bdd08..95bbdd302aad 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
@@ -1,12 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux | 2 | * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux |
3 | * | 3 | * |
4 | * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> | 4 | * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> |
5 | * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> | 5 | * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> |
6 | * | 6 | * |
7 | * Based on the work of: | 7 | * Based on the work of: |
8 | * Andree Borrmann John Dahlstrom | 8 | * Andree Borrmann John Dahlstrom |
9 | * David Kuder Nathan Hand | 9 | * David Kuder Nathan Hand |
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* | 12 | /* |
@@ -81,6 +81,7 @@ struct gc { | |||
81 | struct timer_list timer; | 81 | struct timer_list timer; |
82 | unsigned char pads[GC_MAX + 1]; | 82 | unsigned char pads[GC_MAX + 1]; |
83 | int used; | 83 | int used; |
84 | struct semaphore sem; | ||
84 | char phys[5][32]; | 85 | char phys[5][32]; |
85 | }; | 86 | }; |
86 | 87 | ||
@@ -433,7 +434,7 @@ static void gc_timer(unsigned long private) | |||
433 | gc_psx_read_packet(gc, data_psx, data); | 434 | gc_psx_read_packet(gc, data_psx, data); |
434 | 435 | ||
435 | for (i = 0; i < 5; i++) { | 436 | for (i = 0; i < 5; i++) { |
436 | switch (data[i]) { | 437 | switch (data[i]) { |
437 | 438 | ||
438 | case GC_PSX_RUMBLE: | 439 | case GC_PSX_RUMBLE: |
439 | 440 | ||
@@ -503,22 +504,33 @@ static void gc_timer(unsigned long private) | |||
503 | static int gc_open(struct input_dev *dev) | 504 | static int gc_open(struct input_dev *dev) |
504 | { | 505 | { |
505 | struct gc *gc = dev->private; | 506 | struct gc *gc = dev->private; |
507 | int err; | ||
508 | |||
509 | err = down_interruptible(&gc->sem); | ||
510 | if (err) | ||
511 | return err; | ||
512 | |||
506 | if (!gc->used++) { | 513 | if (!gc->used++) { |
507 | parport_claim(gc->pd); | 514 | parport_claim(gc->pd); |
508 | parport_write_control(gc->pd->port, 0x04); | 515 | parport_write_control(gc->pd->port, 0x04); |
509 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); | 516 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); |
510 | } | 517 | } |
518 | |||
519 | up(&gc->sem); | ||
511 | return 0; | 520 | return 0; |
512 | } | 521 | } |
513 | 522 | ||
514 | static void gc_close(struct input_dev *dev) | 523 | static void gc_close(struct input_dev *dev) |
515 | { | 524 | { |
516 | struct gc *gc = dev->private; | 525 | struct gc *gc = dev->private; |
526 | |||
527 | down(&gc->sem); | ||
517 | if (!--gc->used) { | 528 | if (!--gc->used) { |
518 | del_timer(&gc->timer); | 529 | del_timer_sync(&gc->timer); |
519 | parport_write_control(gc->pd->port, 0x00); | 530 | parport_write_control(gc->pd->port, 0x00); |
520 | parport_release(gc->pd); | 531 | parport_release(gc->pd); |
521 | } | 532 | } |
533 | up(&gc->sem); | ||
522 | } | 534 | } |
523 | 535 | ||
524 | static struct gc __init *gc_probe(int *config, int nargs) | 536 | static struct gc __init *gc_probe(int *config, int nargs) |
@@ -542,11 +554,12 @@ static struct gc __init *gc_probe(int *config, int nargs) | |||
542 | return NULL; | 554 | return NULL; |
543 | } | 555 | } |
544 | 556 | ||
545 | if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) { | 557 | if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) { |
546 | parport_put_port(pp); | 558 | parport_put_port(pp); |
547 | return NULL; | 559 | return NULL; |
548 | } | 560 | } |
549 | memset(gc, 0, sizeof(struct gc)); | 561 | |
562 | init_MUTEX(&gc->sem); | ||
550 | 563 | ||
551 | gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 564 | gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
552 | 565 | ||
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index ad13f09a4e71..7d969420066c 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c | |||
@@ -329,7 +329,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
329 | 329 | ||
330 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) { | 330 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) { |
331 | gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : | 331 | gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : |
332 | gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; | 332 | gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; |
333 | gf2k->dev.absmin[gf2k_abs[i]] = 32; | 333 | gf2k->dev.absmin[gf2k_abs[i]] = 32; |
334 | gf2k->dev.absfuzz[gf2k_abs[i]] = 8; | 334 | gf2k->dev.absfuzz[gf2k_abs[i]] = 8; |
335 | gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; | 335 | gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; |
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 42e5005d621f..0da7bd133ccf 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c | |||
@@ -171,7 +171,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa | |||
171 | *packet = 0; | 171 | *packet = 0; |
172 | raw_data = gameport_read(gameport); | 172 | raw_data = gameport_read(gameport); |
173 | if (raw_data & 1) | 173 | if (raw_data & 1) |
174 | return IO_RETRY; | 174 | return IO_RETRY; |
175 | 175 | ||
176 | for (i = 0; i < 64; i++) { | 176 | for (i = 0; i < 64; i++) { |
177 | raw_data = gameport_read(gameport); | 177 | raw_data = gameport_read(gameport); |
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 028f3513629a..e31b7b93fde2 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c | |||
@@ -78,6 +78,7 @@ static struct iforce_device iforce_device[] = { | |||
78 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? | 78 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? |
79 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? | 79 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? |
80 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? | 80 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? |
81 | { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? | ||
81 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } | 82 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } |
82 | }; | 83 | }; |
83 | 84 | ||
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 617c0b0e5a39..6369a24684fe 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c | |||
@@ -229,6 +229,7 @@ static struct usb_device_id iforce_usb_ids [] = { | |||
229 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ | 229 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ |
230 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ | 230 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ |
231 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ | 231 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ |
232 | { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ | ||
232 | { } /* Terminating entry */ | 233 | { } /* Terminating entry */ |
233 | }; | 234 | }; |
234 | 235 | ||
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index ec0a2a64d49c..a436f2220856 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c | |||
@@ -4,8 +4,8 @@ | |||
4 | * Copyright (c) 1999-2001 Vojtech Pavlik | 4 | * Copyright (c) 1999-2001 Vojtech Pavlik |
5 | * | 5 | * |
6 | * Based on the work of: | 6 | * Based on the work of: |
7 | * David Thompson | 7 | * David Thompson |
8 | * Joseph Krahn | 8 | * Joseph Krahn |
9 | */ | 9 | */ |
10 | 10 | ||
11 | /* | 11 | /* |
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index 874367bfab08..01fd2e4791ae 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (c) 1999-2001 Vojtech Pavlik | 4 | * Copyright (c) 1999-2001 Vojtech Pavlik |
5 | * | 5 | * |
6 | * Based on the work of: | 6 | * Based on the work of: |
7 | * David Thompson | 7 | * David Thompson |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* | 10 | /* |
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index aaee52ceb920..9eb9954cac6e 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c | |||
@@ -79,7 +79,7 @@ static short tmdc_btn_pad[TMDC_BTN] = | |||
79 | { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR }; | 79 | { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR }; |
80 | static short tmdc_btn_joy[TMDC_BTN] = | 80 | static short tmdc_btn_joy[TMDC_BTN] = |
81 | { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE, | 81 | { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE, |
82 | BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; | 82 | BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; |
83 | static short tmdc_btn_fm[TMDC_BTN] = | 83 | static short tmdc_btn_fm[TMDC_BTN] = |
84 | { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 }; | 84 | { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 }; |
85 | static short tmdc_btn_at[TMDC_BTN] = | 85 | static short tmdc_btn_at[TMDC_BTN] = |
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index dd88b9cb49fa..28100d461cb7 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c | |||
@@ -84,6 +84,7 @@ static struct tgfx { | |||
84 | char phys[7][32]; | 84 | char phys[7][32]; |
85 | int sticks; | 85 | int sticks; |
86 | int used; | 86 | int used; |
87 | struct semaphore sem; | ||
87 | } *tgfx_base[3]; | 88 | } *tgfx_base[3]; |
88 | 89 | ||
89 | /* | 90 | /* |
@@ -99,7 +100,7 @@ static void tgfx_timer(unsigned long private) | |||
99 | for (i = 0; i < 7; i++) | 100 | for (i = 0; i < 7; i++) |
100 | if (tgfx->sticks & (1 << i)) { | 101 | if (tgfx->sticks & (1 << i)) { |
101 | 102 | ||
102 | dev = tgfx->dev + i; | 103 | dev = tgfx->dev + i; |
103 | 104 | ||
104 | parport_write_data(tgfx->pd->port, ~(1 << i)); | 105 | parport_write_data(tgfx->pd->port, ~(1 << i)); |
105 | data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; | 106 | data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; |
@@ -122,23 +123,34 @@ static void tgfx_timer(unsigned long private) | |||
122 | 123 | ||
123 | static int tgfx_open(struct input_dev *dev) | 124 | static int tgfx_open(struct input_dev *dev) |
124 | { | 125 | { |
125 | struct tgfx *tgfx = dev->private; | 126 | struct tgfx *tgfx = dev->private; |
126 | if (!tgfx->used++) { | 127 | int err; |
128 | |||
129 | err = down_interruptible(&tgfx->sem); | ||
130 | if (err) | ||
131 | return err; | ||
132 | |||
133 | if (!tgfx->used++) { | ||
127 | parport_claim(tgfx->pd); | 134 | parport_claim(tgfx->pd); |
128 | parport_write_control(tgfx->pd->port, 0x04); | 135 | parport_write_control(tgfx->pd->port, 0x04); |
129 | mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); | 136 | mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); |
130 | } | 137 | } |
131 | return 0; | 138 | |
139 | up(&tgfx->sem); | ||
140 | return 0; | ||
132 | } | 141 | } |
133 | 142 | ||
134 | static void tgfx_close(struct input_dev *dev) | 143 | static void tgfx_close(struct input_dev *dev) |
135 | { | 144 | { |
136 | struct tgfx *tgfx = dev->private; | 145 | struct tgfx *tgfx = dev->private; |
137 | if (!--tgfx->used) { | 146 | |
138 | del_timer(&tgfx->timer); | 147 | down(&tgfx->sem); |
148 | if (!--tgfx->used) { | ||
149 | del_timer_sync(&tgfx->timer); | ||
139 | parport_write_control(tgfx->pd->port, 0x00); | 150 | parport_write_control(tgfx->pd->port, 0x00); |
140 | parport_release(tgfx->pd); | 151 | parport_release(tgfx->pd); |
141 | } | 152 | } |
153 | up(&tgfx->sem); | ||
142 | } | 154 | } |
143 | 155 | ||
144 | /* | 156 | /* |
@@ -166,11 +178,12 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs) | |||
166 | return NULL; | 178 | return NULL; |
167 | } | 179 | } |
168 | 180 | ||
169 | if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) { | 181 | if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) { |
170 | parport_put_port(pp); | 182 | parport_put_port(pp); |
171 | return NULL; | 183 | return NULL; |
172 | } | 184 | } |
173 | memset(tgfx, 0, sizeof(struct tgfx)); | 185 | |
186 | init_MUTEX(&tgfx->sem); | ||
174 | 187 | ||
175 | tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 188 | tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
176 | 189 | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 82fad9a23ace..4d4985b59abf 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -227,7 +227,7 @@ static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *a | |||
227 | { \ | 227 | { \ |
228 | return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ | 228 | return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ |
229 | } \ | 229 | } \ |
230 | static struct device_attribute atkbd_attr_##_name = \ | 230 | static struct device_attribute atkbd_attr_##_name = \ |
231 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); | 231 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); |
232 | 232 | ||
233 | ATKBD_DEFINE_ATTR(extra); | 233 | ATKBD_DEFINE_ATTR(extra); |
@@ -388,7 +388,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
388 | value = atkbd->release ? 0 : | 388 | value = atkbd->release ? 0 : |
389 | (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); | 389 | (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); |
390 | 390 | ||
391 | switch (value) { /* Workaround Toshiba laptop multiple keypress */ | 391 | switch (value) { /* Workaround Toshiba laptop multiple keypress */ |
392 | case 0: | 392 | case 0: |
393 | atkbd->last = 0; | 393 | atkbd->last = 0; |
394 | break; | 394 | break; |
@@ -894,7 +894,7 @@ static int atkbd_reconnect(struct serio *serio) | |||
894 | if (atkbd->write) { | 894 | if (atkbd->write) { |
895 | param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) | 895 | param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) |
896 | | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) | 896 | | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) |
897 | | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); | 897 | | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); |
898 | 898 | ||
899 | if (atkbd_probe(atkbd)) | 899 | if (atkbd_probe(atkbd)) |
900 | return -1; | 900 | return -1; |
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index 0f1220a0ceb5..a8551711e8d6 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #define CORGI_KEY_CALENDER KEY_F1 | 39 | #define CORGI_KEY_CALENDER KEY_F1 |
40 | #define CORGI_KEY_ADDRESS KEY_F2 | 40 | #define CORGI_KEY_ADDRESS KEY_F2 |
41 | #define CORGI_KEY_FN KEY_F3 | 41 | #define CORGI_KEY_FN KEY_F3 |
42 | #define CORGI_KEY_CANCEL KEY_F4 | ||
42 | #define CORGI_KEY_OFF KEY_SUSPEND | 43 | #define CORGI_KEY_OFF KEY_SUSPEND |
43 | #define CORGI_KEY_EXOK KEY_F5 | 44 | #define CORGI_KEY_EXOK KEY_F5 |
44 | #define CORGI_KEY_EXCANCEL KEY_F6 | 45 | #define CORGI_KEY_EXCANCEL KEY_F6 |
@@ -46,6 +47,7 @@ | |||
46 | #define CORGI_KEY_EXJOGUP KEY_F8 | 47 | #define CORGI_KEY_EXJOGUP KEY_F8 |
47 | #define CORGI_KEY_JAP1 KEY_LEFTCTRL | 48 | #define CORGI_KEY_JAP1 KEY_LEFTCTRL |
48 | #define CORGI_KEY_JAP2 KEY_LEFTALT | 49 | #define CORGI_KEY_JAP2 KEY_LEFTALT |
50 | #define CORGI_KEY_MAIL KEY_F10 | ||
49 | #define CORGI_KEY_OK KEY_F11 | 51 | #define CORGI_KEY_OK KEY_F11 |
50 | #define CORGI_KEY_MENU KEY_F12 | 52 | #define CORGI_KEY_MENU KEY_F12 |
51 | #define CORGI_HINGE_0 KEY_KP0 | 53 | #define CORGI_HINGE_0 KEY_KP0 |
@@ -59,8 +61,8 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = { | |||
59 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | 61 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ |
60 | CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | 62 | CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ |
61 | CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ | 63 | CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ |
62 | KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ | 64 | CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ |
63 | KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ | 65 | KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ |
64 | CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ | 66 | CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ |
65 | CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ | 67 | CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ |
66 | }; | 68 | }; |
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 2694ff2b5beb..098963c7cdd6 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
@@ -15,10 +15,10 @@ | |||
15 | * information given below, I will _not_ be liable! | 15 | * information given below, I will _not_ be liable! |
16 | * | 16 | * |
17 | * RJ10 pinout: To DE9: Or DB25: | 17 | * RJ10 pinout: To DE9: Or DB25: |
18 | * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD) | 18 | * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD) |
19 | * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND) | 19 | * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND) |
20 | * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD) | 20 | * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD) |
21 | * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!! | 21 | * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!! |
22 | * | 22 | * |
23 | * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For | 23 | * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For |
24 | * RJ10, it's like this: | 24 | * RJ10, it's like this: |
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index d3e9dd6a13cd..8935290256b3 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c | |||
@@ -42,7 +42,7 @@ MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>"); | |||
42 | MODULE_DESCRIPTION("LoCoMo keyboard driver"); | 42 | MODULE_DESCRIPTION("LoCoMo keyboard driver"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | 44 | ||
45 | #define LOCOMOKBD_NUMKEYS 128 | 45 | #define LOCOMOKBD_NUMKEYS 128 |
46 | 46 | ||
47 | #define KEY_ACTIVITY KEY_F16 | 47 | #define KEY_ACTIVITY KEY_F16 |
48 | #define KEY_CONTACT KEY_F18 | 48 | #define KEY_CONTACT KEY_F18 |
@@ -61,7 +61,7 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = { | |||
61 | KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */ | 61 | KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */ |
62 | 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */ | 62 | 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */ |
63 | KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */ | 63 | KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */ |
64 | KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */ | 64 | KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */ |
65 | }; | 65 | }; |
66 | 66 | ||
67 | #define KB_ROWS 16 | 67 | #define KB_ROWS 16 |
@@ -82,7 +82,7 @@ struct locomokbd { | |||
82 | struct locomo_dev *ldev; | 82 | struct locomo_dev *ldev; |
83 | unsigned long base; | 83 | unsigned long base; |
84 | spinlock_t lock; | 84 | spinlock_t lock; |
85 | 85 | ||
86 | struct timer_list timer; | 86 | struct timer_list timer; |
87 | }; | 87 | }; |
88 | 88 | ||
@@ -95,7 +95,7 @@ static inline void locomokbd_charge_all(unsigned long membase) | |||
95 | static inline void locomokbd_activate_all(unsigned long membase) | 95 | static inline void locomokbd_activate_all(unsigned long membase) |
96 | { | 96 | { |
97 | unsigned long r; | 97 | unsigned long r; |
98 | 98 | ||
99 | locomo_writel(0, membase + LOCOMO_KSC); | 99 | locomo_writel(0, membase + LOCOMO_KSC); |
100 | r = locomo_readl(membase + LOCOMO_KIC); | 100 | r = locomo_readl(membase + LOCOMO_KIC); |
101 | r &= 0xFEFF; | 101 | r &= 0xFEFF; |
@@ -127,7 +127,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col) | |||
127 | */ | 127 | */ |
128 | 128 | ||
129 | /* Scan the hardware keyboard and push any changes up through the input layer */ | 129 | /* Scan the hardware keyboard and push any changes up through the input layer */ |
130 | static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) | 130 | static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) |
131 | { | 131 | { |
132 | unsigned int row, col, rowd, scancode; | 132 | unsigned int row, col, rowd, scancode; |
133 | unsigned long flags; | 133 | unsigned long flags; |
@@ -138,7 +138,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * | |||
138 | 138 | ||
139 | if (regs) | 139 | if (regs) |
140 | input_regs(&locomokbd->input, regs); | 140 | input_regs(&locomokbd->input, regs); |
141 | 141 | ||
142 | locomokbd_charge_all(membase); | 142 | locomokbd_charge_all(membase); |
143 | 143 | ||
144 | num_pressed = 0; | 144 | num_pressed = 0; |
@@ -146,9 +146,9 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * | |||
146 | 146 | ||
147 | locomokbd_activate_col(membase, col); | 147 | locomokbd_activate_col(membase, col); |
148 | udelay(KB_DELAY); | 148 | udelay(KB_DELAY); |
149 | 149 | ||
150 | rowd = ~locomo_readl(membase + LOCOMO_KIB); | 150 | rowd = ~locomo_readl(membase + LOCOMO_KIB); |
151 | for (row = 0; row < KB_ROWS; row++ ) { | 151 | for (row = 0; row < KB_ROWS; row++) { |
152 | scancode = SCANCODE(col, row); | 152 | scancode = SCANCODE(col, row); |
153 | if (rowd & KB_ROWMASK(row)) { | 153 | if (rowd & KB_ROWMASK(row)) { |
154 | num_pressed += 1; | 154 | num_pressed += 1; |
@@ -170,7 +170,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * | |||
170 | spin_unlock_irqrestore(&locomokbd->lock, flags); | 170 | spin_unlock_irqrestore(&locomokbd->lock, flags); |
171 | } | 171 | } |
172 | 172 | ||
173 | /* | 173 | /* |
174 | * LoCoMo keyboard interrupt handler. | 174 | * LoCoMo keyboard interrupt handler. |
175 | */ | 175 | */ |
176 | static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 176 | static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
@@ -205,8 +205,8 @@ static int locomokbd_probe(struct locomo_dev *dev) | |||
205 | memset(locomokbd, 0, sizeof(struct locomokbd)); | 205 | memset(locomokbd, 0, sizeof(struct locomokbd)); |
206 | 206 | ||
207 | /* try and claim memory region */ | 207 | /* try and claim memory region */ |
208 | if (!request_mem_region((unsigned long) dev->mapbase, | 208 | if (!request_mem_region((unsigned long) dev->mapbase, |
209 | dev->length, | 209 | dev->length, |
210 | LOCOMO_DRIVER_NAME(dev))) { | 210 | LOCOMO_DRIVER_NAME(dev))) { |
211 | ret = -EBUSY; | 211 | ret = -EBUSY; |
212 | printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n"); | 212 | printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n"); |
@@ -225,7 +225,7 @@ static int locomokbd_probe(struct locomo_dev *dev) | |||
225 | locomokbd->timer.data = (unsigned long) locomokbd; | 225 | locomokbd->timer.data = (unsigned long) locomokbd; |
226 | 226 | ||
227 | locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 227 | locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
228 | 228 | ||
229 | init_input_dev(&locomokbd->input); | 229 | init_input_dev(&locomokbd->input); |
230 | locomokbd->input.keycode = locomokbd->keycode; | 230 | locomokbd->input.keycode = locomokbd->keycode; |
231 | locomokbd->input.keycodesize = sizeof(unsigned char); | 231 | locomokbd->input.keycodesize = sizeof(unsigned char); |
@@ -271,11 +271,11 @@ free: | |||
271 | static int locomokbd_remove(struct locomo_dev *dev) | 271 | static int locomokbd_remove(struct locomo_dev *dev) |
272 | { | 272 | { |
273 | struct locomokbd *locomokbd = locomo_get_drvdata(dev); | 273 | struct locomokbd *locomokbd = locomo_get_drvdata(dev); |
274 | 274 | ||
275 | free_irq(dev->irq[0], locomokbd); | 275 | free_irq(dev->irq[0], locomokbd); |
276 | 276 | ||
277 | del_timer_sync(&locomokbd->timer); | 277 | del_timer_sync(&locomokbd->timer); |
278 | 278 | ||
279 | input_unregister_device(&locomokbd->input); | 279 | input_unregister_device(&locomokbd->input); |
280 | locomo_set_drvdata(dev, NULL); | 280 | locomo_set_drvdata(dev, NULL); |
281 | 281 | ||
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c index 859ed771ee0a..eecbde294f1f 100644 --- a/drivers/input/keyboard/maple_keyb.c +++ b/drivers/input/keyboard/maple_keyb.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ | 2 | * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ |
3 | * SEGA Dreamcast keyboard driver | 3 | * SEGA Dreamcast keyboard driver |
4 | * Based on drivers/usb/usbkbd.c | 4 | * Based on drivers/usb/usbkbd.c |
5 | */ | 5 | */ |
6 | 6 | ||
@@ -40,7 +40,6 @@ struct dc_kbd { | |||
40 | struct input_dev dev; | 40 | struct input_dev dev; |
41 | unsigned char new[8]; | 41 | unsigned char new[8]; |
42 | unsigned char old[8]; | 42 | unsigned char old[8]; |
43 | int open; | ||
44 | }; | 43 | }; |
45 | 44 | ||
46 | 45 | ||
@@ -95,22 +94,6 @@ static void dc_kbd_callback(struct mapleq *mq) | |||
95 | } | 94 | } |
96 | } | 95 | } |
97 | 96 | ||
98 | |||
99 | static int dc_kbd_open(struct input_dev *dev) | ||
100 | { | ||
101 | struct dc_kbd *kbd = dev->private; | ||
102 | kbd->open++; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | |||
107 | static void dc_kbd_close(struct input_dev *dev) | ||
108 | { | ||
109 | struct dc_kbd *kbd = dev->private; | ||
110 | kbd->open--; | ||
111 | } | ||
112 | |||
113 | |||
114 | static int dc_kbd_connect(struct maple_device *dev) | 97 | static int dc_kbd_connect(struct maple_device *dev) |
115 | { | 98 | { |
116 | int i; | 99 | int i; |
@@ -133,9 +116,6 @@ static int dc_kbd_connect(struct maple_device *dev) | |||
133 | clear_bit(0, kbd->dev.keybit); | 116 | clear_bit(0, kbd->dev.keybit); |
134 | 117 | ||
135 | kbd->dev.private = kbd; | 118 | kbd->dev.private = kbd; |
136 | kbd->dev.open = dc_kbd_open; | ||
137 | kbd->dev.close = dc_kbd_close; | ||
138 | kbd->dev.event = NULL; | ||
139 | 119 | ||
140 | kbd->dev.name = dev->product_name; | 120 | kbd->dev.name = dev->product_name; |
141 | kbd->dev.id.bustype = BUS_MAPLE; | 121 | kbd->dev.id.bustype = BUS_MAPLE; |
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 158c8e845ff9..98710997aaaa 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -298,9 +298,11 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz | |||
298 | /* check if absmin/absmax/absfuzz/absflat are filled as | 298 | /* check if absmin/absmax/absfuzz/absflat are filled as |
299 | * told in Documentation/input/input-programming.txt */ | 299 | * told in Documentation/input/input-programming.txt */ |
300 | if (test_bit(EV_ABS, dev->evbit)) { | 300 | if (test_bit(EV_ABS, dev->evbit)) { |
301 | retval = uinput_validate_absbits(dev); | 301 | int err = uinput_validate_absbits(dev); |
302 | if (retval < 0) | 302 | if (err < 0) { |
303 | retval = err; | ||
303 | kfree(dev->name); | 304 | kfree(dev->name); |
305 | } | ||
304 | } | 306 | } |
305 | 307 | ||
306 | exit: | 308 | exit: |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index a7864195806a..c4909b49337d 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o | |||
15 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | 15 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o |
16 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o | 16 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o |
17 | 17 | ||
18 | psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o | 18 | psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 7bf4be733e9a..a12e98158a75 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -30,10 +30,11 @@ | |||
30 | 30 | ||
31 | #define ALPS_DUALPOINT 0x01 | 31 | #define ALPS_DUALPOINT 0x01 |
32 | #define ALPS_WHEEL 0x02 | 32 | #define ALPS_WHEEL 0x02 |
33 | #define ALPS_FW_BK 0x04 | 33 | #define ALPS_FW_BK_1 0x04 |
34 | #define ALPS_4BTN 0x08 | 34 | #define ALPS_4BTN 0x08 |
35 | #define ALPS_OLDPROTO 0x10 | 35 | #define ALPS_OLDPROTO 0x10 |
36 | #define ALPS_PASS 0x20 | 36 | #define ALPS_PASS 0x20 |
37 | #define ALPS_FW_BK_2 0x40 | ||
37 | 38 | ||
38 | static struct alps_model_info alps_model_data[] = { | 39 | static struct alps_model_info alps_model_data[] = { |
39 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ | 40 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ |
@@ -43,11 +44,11 @@ static struct alps_model_info alps_model_data[] = { | |||
43 | { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 44 | { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, |
44 | { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 }, | 45 | { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 }, |
45 | { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ | 46 | { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ |
46 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK }, /* NEC Versa L320 */ | 47 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ |
47 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, | 48 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, |
48 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ | 49 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ |
49 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 50 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
50 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 51 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ |
51 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 52 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
52 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 53 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
53 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 54 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
@@ -61,11 +62,11 @@ static struct alps_model_info alps_model_data[] = { | |||
61 | 62 | ||
62 | /* | 63 | /* |
63 | * ALPS abolute Mode - new format | 64 | * ALPS abolute Mode - new format |
64 | * | 65 | * |
65 | * byte 0: 1 ? ? ? 1 ? ? ? | 66 | * byte 0: 1 ? ? ? 1 ? ? ? |
66 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | 67 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 |
67 | * byte 2: 0 x10 x9 x8 x7 ? fin ges | 68 | * byte 2: 0 x10 x9 x8 x7 ? fin ges |
68 | * byte 3: 0 y9 y8 y7 1 M R L | 69 | * byte 3: 0 y9 y8 y7 1 M R L |
69 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 | 70 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 |
70 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 | 71 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 |
71 | * | 72 | * |
@@ -81,11 +82,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |||
81 | struct input_dev *dev = &psmouse->dev; | 82 | struct input_dev *dev = &psmouse->dev; |
82 | struct input_dev *dev2 = &priv->dev2; | 83 | struct input_dev *dev2 = &priv->dev2; |
83 | int x, y, z, ges, fin, left, right, middle; | 84 | int x, y, z, ges, fin, left, right, middle; |
85 | int back = 0, forward = 0; | ||
84 | 86 | ||
85 | input_regs(dev, regs); | 87 | input_regs(dev, regs); |
86 | 88 | ||
87 | if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ | 89 | if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ |
88 | input_report_key(dev2, BTN_LEFT, packet[0] & 1); | 90 | input_report_key(dev2, BTN_LEFT, packet[0] & 1); |
89 | input_report_key(dev2, BTN_RIGHT, packet[0] & 2); | 91 | input_report_key(dev2, BTN_RIGHT, packet[0] & 2); |
90 | input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); | 92 | input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); |
91 | input_report_rel(dev2, REL_X, | 93 | input_report_rel(dev2, REL_X, |
@@ -112,6 +114,18 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |||
112 | z = packet[5]; | 114 | z = packet[5]; |
113 | } | 115 | } |
114 | 116 | ||
117 | if (priv->i->flags & ALPS_FW_BK_1) { | ||
118 | back = packet[2] & 4; | ||
119 | forward = packet[0] & 0x10; | ||
120 | } | ||
121 | |||
122 | if (priv->i->flags & ALPS_FW_BK_2) { | ||
123 | back = packet[3] & 4; | ||
124 | forward = packet[2] & 4; | ||
125 | if ((middle = forward && back)) | ||
126 | forward = back = 0; | ||
127 | } | ||
128 | |||
115 | ges = packet[2] & 1; | 129 | ges = packet[2] & 1; |
116 | fin = packet[2] & 2; | 130 | fin = packet[2] & 2; |
117 | 131 | ||
@@ -155,13 +169,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |||
155 | input_report_abs(dev, ABS_PRESSURE, z); | 169 | input_report_abs(dev, ABS_PRESSURE, z); |
156 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); | 170 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); |
157 | 171 | ||
158 | |||
159 | if (priv->i->flags & ALPS_WHEEL) | 172 | if (priv->i->flags & ALPS_WHEEL) |
160 | input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); | 173 | input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); |
161 | 174 | ||
162 | if (priv->i->flags & ALPS_FW_BK) { | 175 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
163 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x10); | 176 | input_report_key(dev, BTN_FORWARD, forward); |
164 | input_report_key(dev, BTN_BACK, packet[2] & 0x04); | 177 | input_report_key(dev, BTN_BACK, back); |
165 | } | 178 | } |
166 | 179 | ||
167 | input_sync(dev); | 180 | input_sync(dev); |
@@ -257,7 +270,6 @@ static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *vers | |||
257 | static int alps_passthrough_mode(struct psmouse *psmouse, int enable) | 270 | static int alps_passthrough_mode(struct psmouse *psmouse, int enable) |
258 | { | 271 | { |
259 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 272 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
260 | unsigned char param[3]; | ||
261 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; | 273 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; |
262 | 274 | ||
263 | if (ps2_command(ps2dev, NULL, cmd) || | 275 | if (ps2_command(ps2dev, NULL, cmd) || |
@@ -267,7 +279,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, int enable) | |||
267 | return -1; | 279 | return -1; |
268 | 280 | ||
269 | /* we may get 3 more bytes, just ignore them */ | 281 | /* we may get 3 more bytes, just ignore them */ |
270 | ps2_command(ps2dev, param, 0x0300); | 282 | ps2_drain(ps2dev, 3, 100); |
271 | 283 | ||
272 | return 0; | 284 | return 0; |
273 | } | 285 | } |
@@ -425,7 +437,7 @@ int alps_init(struct psmouse *psmouse) | |||
425 | psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL); | 437 | psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL); |
426 | } | 438 | } |
427 | 439 | ||
428 | if (priv->i->flags & ALPS_FW_BK) { | 440 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
429 | psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); | 441 | psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); |
430 | psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); | 442 | psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); |
431 | } | 443 | } |
@@ -436,8 +448,8 @@ int alps_init(struct psmouse *psmouse) | |||
436 | priv->dev2.id.bustype = BUS_I8042; | 448 | priv->dev2.id.bustype = BUS_I8042; |
437 | priv->dev2.id.vendor = 0x0002; | 449 | priv->dev2.id.vendor = 0x0002; |
438 | priv->dev2.id.product = PSMOUSE_ALPS; | 450 | priv->dev2.id.product = PSMOUSE_ALPS; |
439 | priv->dev2.id.version = 0x0000; | 451 | priv->dev2.id.version = 0x0000; |
440 | 452 | ||
441 | priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 453 | priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); |
442 | priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); | 454 | priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); |
443 | priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | 455 | priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); |
@@ -461,17 +473,15 @@ init_fail: | |||
461 | int alps_detect(struct psmouse *psmouse, int set_properties) | 473 | int alps_detect(struct psmouse *psmouse, int set_properties) |
462 | { | 474 | { |
463 | int version; | 475 | int version; |
464 | struct alps_model_info *model; | 476 | struct alps_model_info *model; |
465 | 477 | ||
466 | if (!(model = alps_get_model(psmouse, &version))) | 478 | if (!(model = alps_get_model(psmouse, &version))) |
467 | return -1; | 479 | return -1; |
468 | 480 | ||
469 | if (set_properties) { | 481 | if (set_properties) { |
470 | psmouse->vendor = "ALPS"; | 482 | psmouse->vendor = "ALPS"; |
471 | if (model->flags & ALPS_DUALPOINT) | 483 | psmouse->name = model->flags & ALPS_DUALPOINT ? |
472 | psmouse->name = "DualPoint TouchPad"; | 484 | "DualPoint TouchPad" : "GlidePoint"; |
473 | else | ||
474 | psmouse->name = "GlidePoint"; | ||
475 | psmouse->model = version; | 485 | psmouse->model = version; |
476 | } | 486 | } |
477 | return 0; | 487 | return 0; |
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index 7baa09cca7c5..e994849efb8f 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c | |||
@@ -33,7 +33,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
33 | MODULE_DESCRIPTION("Amiga mouse driver"); | 33 | MODULE_DESCRIPTION("Amiga mouse driver"); |
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | ||
36 | static int amimouse_used = 0; | ||
37 | static int amimouse_lastx, amimouse_lasty; | 36 | static int amimouse_lastx, amimouse_lasty; |
38 | static struct input_dev amimouse_dev; | 37 | static struct input_dev amimouse_dev; |
39 | 38 | ||
@@ -81,16 +80,12 @@ static int amimouse_open(struct input_dev *dev) | |||
81 | { | 80 | { |
82 | unsigned short joy0dat; | 81 | unsigned short joy0dat; |
83 | 82 | ||
84 | if (amimouse_used++) | ||
85 | return 0; | ||
86 | |||
87 | joy0dat = custom.joy0dat; | 83 | joy0dat = custom.joy0dat; |
88 | 84 | ||
89 | amimouse_lastx = joy0dat & 0xff; | 85 | amimouse_lastx = joy0dat & 0xff; |
90 | amimouse_lasty = joy0dat >> 8; | 86 | amimouse_lasty = joy0dat >> 8; |
91 | 87 | ||
92 | if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { | 88 | if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { |
93 | amimouse_used--; | ||
94 | printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); | 89 | printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); |
95 | return -EBUSY; | 90 | return -EBUSY; |
96 | } | 91 | } |
@@ -100,8 +95,7 @@ static int amimouse_open(struct input_dev *dev) | |||
100 | 95 | ||
101 | static void amimouse_close(struct input_dev *dev) | 96 | static void amimouse_close(struct input_dev *dev) |
102 | { | 97 | { |
103 | if (!--amimouse_used) | 98 | free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); |
104 | free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); | ||
105 | } | 99 | } |
106 | 100 | ||
107 | static int __init amimouse_init(void) | 101 | static int __init amimouse_init(void) |
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c index ca4e96886627..1f62c0134010 100644 --- a/drivers/input/mouse/inport.c +++ b/drivers/input/mouse/inport.c | |||
@@ -17,18 +17,18 @@ | |||
17 | /* | 17 | /* |
18 | * This program is free software; you can redistribute it and/or modify | 18 | * This program is free software; you can redistribute it and/or modify |
19 | * it under the terms of the GNU General Public License as published by | 19 | * it under the terms of the GNU General Public License as published by |
20 | * the Free Software Foundation; either version 2 of the License, or | 20 | * the Free Software Foundation; either version 2 of the License, or |
21 | * (at your option) any later version. | 21 | * (at your option) any later version. |
22 | * | 22 | * |
23 | * This program is distributed in the hope that it will be useful, | 23 | * This program is distributed in the hope that it will be useful, |
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
26 | * GNU General Public License for more details. | 26 | * GNU General Public License for more details. |
27 | * | 27 | * |
28 | * You should have received a copy of the GNU General Public License | 28 | * You should have received a copy of the GNU General Public License |
29 | * along with this program; if not, write to the Free Software | 29 | * along with this program; if not, write to the Free Software |
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
31 | * | 31 | * |
32 | * Should you need to contact me, the author, you can do so either by | 32 | * Should you need to contact me, the author, you can do so either by |
33 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 33 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
34 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 34 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
@@ -87,29 +87,23 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); | |||
87 | 87 | ||
88 | __obsolete_setup("inport_irq="); | 88 | __obsolete_setup("inport_irq="); |
89 | 89 | ||
90 | static int inport_used; | ||
91 | |||
92 | static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 90 | static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
93 | 91 | ||
94 | static int inport_open(struct input_dev *dev) | 92 | static int inport_open(struct input_dev *dev) |
95 | { | 93 | { |
96 | if (!inport_used++) { | 94 | if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) |
97 | if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) | 95 | return -EBUSY; |
98 | return -EBUSY; | 96 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); |
99 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); | 97 | outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); |
100 | outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); | ||
101 | } | ||
102 | 98 | ||
103 | return 0; | 99 | return 0; |
104 | } | 100 | } |
105 | 101 | ||
106 | static void inport_close(struct input_dev *dev) | 102 | static void inport_close(struct input_dev *dev) |
107 | { | 103 | { |
108 | if (!--inport_used) { | 104 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); |
109 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); | 105 | outb(INPORT_MODE_BASE, INPORT_DATA_PORT); |
110 | outb(INPORT_MODE_BASE, INPORT_DATA_PORT); | 106 | free_irq(inport_irq, NULL); |
111 | free_irq(inport_irq, NULL); | ||
112 | } | ||
113 | } | 107 | } |
114 | 108 | ||
115 | static struct input_dev inport_dev = { | 109 | static struct input_dev inport_dev = { |
@@ -120,11 +114,11 @@ static struct input_dev inport_dev = { | |||
120 | .close = inport_close, | 114 | .close = inport_close, |
121 | .name = INPORT_NAME, | 115 | .name = INPORT_NAME, |
122 | .phys = "isa023c/input0", | 116 | .phys = "isa023c/input0", |
123 | .id = { | 117 | .id = { |
124 | .bustype = BUS_ISA, | 118 | .bustype = BUS_ISA, |
125 | .vendor = INPORT_VENDOR, | 119 | .vendor = INPORT_VENDOR, |
126 | .product = 0x0001, | 120 | .product = 0x0001, |
127 | .version = 0x0100, | 121 | .version = 0x0100, |
128 | }, | 122 | }, |
129 | }; | 123 | }; |
130 | 124 | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c new file mode 100644 index 000000000000..bd9df9b28325 --- /dev/null +++ b/drivers/input/mouse/lifebook.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Fujitsu B-series Lifebook PS/2 TouchScreen driver | ||
3 | * | ||
4 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> | ||
5 | * Copyright (c) 2005 Kenan Esau <kenan.esau@conan.de> | ||
6 | * | ||
7 | * TouchScreen detection, absolute mode setting and packet layout is taken from | ||
8 | * Harald Hoyer's description of the device. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published by | ||
12 | * the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/input.h> | ||
16 | #include <linux/serio.h> | ||
17 | #include <linux/libps2.h> | ||
18 | #include <linux/dmi.h> | ||
19 | |||
20 | #include "psmouse.h" | ||
21 | #include "lifebook.h" | ||
22 | |||
23 | static struct dmi_system_id lifebook_dmi_table[] = { | ||
24 | { | ||
25 | .ident = "Lifebook B", | ||
26 | .matches = { | ||
27 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), | ||
28 | }, | ||
29 | }, | ||
30 | { } | ||
31 | }; | ||
32 | |||
33 | |||
34 | static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs) | ||
35 | { | ||
36 | unsigned char *packet = psmouse->packet; | ||
37 | struct input_dev *dev = &psmouse->dev; | ||
38 | |||
39 | if (psmouse->pktcnt != 3) | ||
40 | return PSMOUSE_GOOD_DATA; | ||
41 | |||
42 | input_regs(dev, regs); | ||
43 | |||
44 | /* calculate X and Y */ | ||
45 | if ((packet[0] & 0x08) == 0x00) { | ||
46 | input_report_abs(dev, ABS_X, | ||
47 | (packet[1] | ((packet[0] & 0x30) << 4))); | ||
48 | input_report_abs(dev, ABS_Y, | ||
49 | 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); | ||
50 | } else { | ||
51 | input_report_rel(dev, REL_X, | ||
52 | ((packet[0] & 0x10) ? packet[1] - 256 : packet[1])); | ||
53 | input_report_rel(dev, REL_Y, | ||
54 | -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2])); | ||
55 | } | ||
56 | |||
57 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | ||
58 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | ||
59 | input_report_key(dev, BTN_TOUCH, packet[0] & 0x04); | ||
60 | |||
61 | input_sync(dev); | ||
62 | |||
63 | return PSMOUSE_FULL_PACKET; | ||
64 | } | ||
65 | |||
66 | static int lifebook_absolute_mode(struct psmouse *psmouse) | ||
67 | { | ||
68 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
69 | unsigned char param; | ||
70 | |||
71 | if (psmouse_reset(psmouse)) | ||
72 | return -1; | ||
73 | |||
74 | /* | ||
75 | Enable absolute output -- ps2_command fails always but if | ||
76 | you leave this call out the touchsreen will never send | ||
77 | absolute coordinates | ||
78 | */ | ||
79 | param = 0x07; | ||
80 | ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution) | ||
86 | { | ||
87 | unsigned char params[] = { 0, 1, 2, 2, 3 }; | ||
88 | |||
89 | if (resolution == 0 || resolution > 400) | ||
90 | resolution = 400; | ||
91 | |||
92 | ps2_command(&psmouse->ps2dev, ¶ms[resolution / 100], PSMOUSE_CMD_SETRES); | ||
93 | psmouse->resolution = 50 << params[resolution / 100]; | ||
94 | } | ||
95 | |||
96 | static void lifebook_disconnect(struct psmouse *psmouse) | ||
97 | { | ||
98 | psmouse_reset(psmouse); | ||
99 | } | ||
100 | |||
101 | int lifebook_detect(struct psmouse *psmouse, int set_properties) | ||
102 | { | ||
103 | if (!dmi_check_system(lifebook_dmi_table)) | ||
104 | return -1; | ||
105 | |||
106 | if (set_properties) { | ||
107 | psmouse->vendor = "Fujitsu"; | ||
108 | psmouse->name = "Lifebook TouchScreen"; | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | int lifebook_init(struct psmouse *psmouse) | ||
115 | { | ||
116 | if (lifebook_absolute_mode(psmouse)) | ||
117 | return -1; | ||
118 | |||
119 | psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); | ||
120 | psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
121 | psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
122 | psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
123 | input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0); | ||
124 | input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0); | ||
125 | |||
126 | psmouse->protocol_handler = lifebook_process_byte; | ||
127 | psmouse->set_resolution = lifebook_set_resolution; | ||
128 | psmouse->disconnect = lifebook_disconnect; | ||
129 | psmouse->reconnect = lifebook_absolute_mode; | ||
130 | psmouse->pktsize = 3; | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h new file mode 100644 index 000000000000..be1c0943825d --- /dev/null +++ b/drivers/input/mouse/lifebook.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * Fujitsu B-series Lifebook PS/2 TouchScreen driver | ||
3 | * | ||
4 | * Copyright (c) 2005 Vojtech Pavlik | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _LIFEBOOK_H | ||
12 | #define _LIFEBOOK_H | ||
13 | |||
14 | int lifebook_detect(struct psmouse *psmouse, int set_properties); | ||
15 | int lifebook_init(struct psmouse *psmouse); | ||
16 | |||
17 | #endif | ||
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c index 77eb83e87f61..8b5243167227 100644 --- a/drivers/input/mouse/logibm.c +++ b/drivers/input/mouse/logibm.c | |||
@@ -18,18 +18,18 @@ | |||
18 | /* | 18 | /* |
19 | * This program is free software; you can redistribute it and/or modify | 19 | * This program is free software; you can redistribute it and/or modify |
20 | * it under the terms of the GNU General Public License as published by | 20 | * it under the terms of the GNU General Public License as published by |
21 | * the Free Software Foundation; either version 2 of the License, or | 21 | * the Free Software Foundation; either version 2 of the License, or |
22 | * (at your option) any later version. | 22 | * (at your option) any later version. |
23 | * | 23 | * |
24 | * This program is distributed in the hope that it will be useful, | 24 | * This program is distributed in the hope that it will be useful, |
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
27 | * GNU General Public License for more details. | 27 | * GNU General Public License for more details. |
28 | * | 28 | * |
29 | * You should have received a copy of the GNU General Public License | 29 | * You should have received a copy of the GNU General Public License |
30 | * along with this program; if not, write to the Free Software | 30 | * along with this program; if not, write to the Free Software |
31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
32 | * | 32 | * |
33 | * Should you need to contact me, the author, you can do so either by | 33 | * Should you need to contact me, the author, you can do so either by |
34 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 34 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
35 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 35 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
@@ -77,16 +77,11 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); | |||
77 | 77 | ||
78 | __obsolete_setup("logibm_irq="); | 78 | __obsolete_setup("logibm_irq="); |
79 | 79 | ||
80 | static int logibm_used = 0; | ||
81 | |||
82 | static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 80 | static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
83 | 81 | ||
84 | static int logibm_open(struct input_dev *dev) | 82 | static int logibm_open(struct input_dev *dev) |
85 | { | 83 | { |
86 | if (logibm_used++) | ||
87 | return 0; | ||
88 | if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) { | 84 | if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) { |
89 | logibm_used--; | ||
90 | printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq); | 85 | printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq); |
91 | return -EBUSY; | 86 | return -EBUSY; |
92 | } | 87 | } |
@@ -96,8 +91,6 @@ static int logibm_open(struct input_dev *dev) | |||
96 | 91 | ||
97 | static void logibm_close(struct input_dev *dev) | 92 | static void logibm_close(struct input_dev *dev) |
98 | { | 93 | { |
99 | if (--logibm_used) | ||
100 | return; | ||
101 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); | 94 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); |
102 | free_irq(logibm_irq, NULL); | 95 | free_irq(logibm_irq, NULL); |
103 | } | 96 | } |
@@ -167,7 +160,7 @@ static int __init logibm_init(void) | |||
167 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); | 160 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); |
168 | 161 | ||
169 | input_register_device(&logibm_dev); | 162 | input_register_device(&logibm_dev); |
170 | 163 | ||
171 | printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq); | 164 | printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq); |
172 | 165 | ||
173 | return 0; | 166 | return 0; |
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c index 12dc0ef5020f..e90c60cbbf05 100644 --- a/drivers/input/mouse/maplemouse.c +++ b/drivers/input/mouse/maplemouse.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $ | 2 | * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $ |
3 | * SEGA Dreamcast mouse driver | 3 | * SEGA Dreamcast mouse driver |
4 | * Based on drivers/usb/usbmouse.c | 4 | * Based on drivers/usb/usbmouse.c |
5 | */ | 5 | */ |
6 | 6 | ||
@@ -15,80 +15,51 @@ | |||
15 | MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>"); | 15 | MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>"); |
16 | MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); | 16 | MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); |
17 | 17 | ||
18 | struct dc_mouse { | ||
19 | struct input_dev dev; | ||
20 | int open; | ||
21 | }; | ||
22 | |||
23 | |||
24 | static void dc_mouse_callback(struct mapleq *mq) | 18 | static void dc_mouse_callback(struct mapleq *mq) |
25 | { | 19 | { |
26 | int buttons, relx, rely, relz; | 20 | int buttons, relx, rely, relz; |
27 | struct maple_device *mapledev = mq->dev; | 21 | struct maple_device *mapledev = mq->dev; |
28 | struct dc_mouse *mouse = mapledev->private_data; | 22 | struct input_dev *dev = mapledev->private_data; |
29 | struct input_dev *dev = &mouse->dev; | ||
30 | unsigned char *res = mq->recvbuf; | 23 | unsigned char *res = mq->recvbuf; |
31 | 24 | ||
32 | buttons = ~res[8]; | 25 | buttons = ~res[8]; |
33 | relx=*(unsigned short *)(res+12)-512; | 26 | relx = *(unsigned short *)(res + 12) - 512; |
34 | rely=*(unsigned short *)(res+14)-512; | 27 | rely = *(unsigned short *)(res + 14) - 512; |
35 | relz=*(unsigned short *)(res+16)-512; | 28 | relz = *(unsigned short *)(res + 16) - 512; |
36 | 29 | ||
37 | input_report_key(dev, BTN_LEFT, buttons&4); | 30 | input_report_key(dev, BTN_LEFT, buttons & 4); |
38 | input_report_key(dev, BTN_MIDDLE, buttons&9); | 31 | input_report_key(dev, BTN_MIDDLE, buttons & 9); |
39 | input_report_key(dev, BTN_RIGHT, buttons&2); | 32 | input_report_key(dev, BTN_RIGHT, buttons & 2); |
40 | input_report_rel(dev, REL_X, relx); | 33 | input_report_rel(dev, REL_X, relx); |
41 | input_report_rel(dev, REL_Y, rely); | 34 | input_report_rel(dev, REL_Y, rely); |
42 | input_report_rel(dev, REL_WHEEL, relz); | 35 | input_report_rel(dev, REL_WHEEL, relz); |
43 | input_sync(dev); | 36 | input_sync(dev); |
44 | } | 37 | } |
45 | 38 | ||
46 | |||
47 | static int dc_mouse_open(struct input_dev *dev) | ||
48 | { | ||
49 | struct dc_mouse *mouse = dev->private; | ||
50 | mouse->open++; | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | |||
55 | static void dc_mouse_close(struct input_dev *dev) | ||
56 | { | ||
57 | struct dc_mouse *mouse = dev->private; | ||
58 | mouse->open--; | ||
59 | } | ||
60 | |||
61 | |||
62 | static int dc_mouse_connect(struct maple_device *dev) | 39 | static int dc_mouse_connect(struct maple_device *dev) |
63 | { | 40 | { |
64 | unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); | 41 | unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); |
65 | struct dc_mouse *mouse; | 42 | struct input_dev *input_dev; |
66 | 43 | ||
67 | if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL))) | 44 | if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL))) |
68 | return -1; | 45 | return -1; |
69 | memset(mouse, 0, sizeof(struct dc_mouse)); | ||
70 | |||
71 | dev->private_data = mouse; | ||
72 | 46 | ||
73 | mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 47 | dev->private_data = input_dev; |
74 | mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
75 | mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); | ||
76 | 48 | ||
77 | init_input_dev(&mouse->dev); | 49 | memset(input_dev, 0, sizeof(struct dc_mouse)); |
50 | init_input_dev(input_dev); | ||
51 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
52 | input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
53 | input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); | ||
78 | 54 | ||
79 | mouse->dev.private = mouse; | 55 | input_dev->name = dev->product_name; |
80 | mouse->dev.open = dc_mouse_open; | 56 | input_dev->id.bustype = BUS_MAPLE; |
81 | mouse->dev.close = dc_mouse_close; | ||
82 | mouse->dev.event = NULL; | ||
83 | 57 | ||
84 | mouse->dev.name = dev->product_name; | 58 | input_register_device(input_dev); |
85 | mouse->dev.id.bustype = BUS_MAPLE; | ||
86 | |||
87 | input_register_device(&mouse->dev); | ||
88 | 59 | ||
89 | maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE); | 60 | maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE); |
90 | 61 | ||
91 | printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, mouse->dev.name); | 62 | printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name); |
92 | 63 | ||
93 | return 0; | 64 | return 0; |
94 | } | 65 | } |
@@ -96,10 +67,10 @@ static int dc_mouse_connect(struct maple_device *dev) | |||
96 | 67 | ||
97 | static void dc_mouse_disconnect(struct maple_device *dev) | 68 | static void dc_mouse_disconnect(struct maple_device *dev) |
98 | { | 69 | { |
99 | struct dc_mouse *mouse = dev->private_data; | 70 | struct input_dev *input_dev = dev->private_data; |
100 | 71 | ||
101 | input_unregister_device(&mouse->dev); | 72 | input_unregister_device(input_dev); |
102 | kfree(mouse); | 73 | kfree(input_dev); |
103 | } | 74 | } |
104 | 75 | ||
105 | 76 | ||
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index 0c74918fe254..93393d5c0078 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (c) 2000-2001 Vojtech Pavlik | 4 | * Copyright (c) 2000-2001 Vojtech Pavlik |
5 | * | 5 | * |
6 | * Based on the work of: | 6 | * Based on the work of: |
7 | * Alan Cox Robin O'Leary | 7 | * Alan Cox Robin O'Leary |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* | 10 | /* |
@@ -56,7 +56,6 @@ static int pc110pad_io = 0x15e0; | |||
56 | static struct input_dev pc110pad_dev; | 56 | static struct input_dev pc110pad_dev; |
57 | static int pc110pad_data[3]; | 57 | static int pc110pad_data[3]; |
58 | static int pc110pad_count; | 58 | static int pc110pad_count; |
59 | static int pc110pad_used; | ||
60 | 59 | ||
61 | static char *pc110pad_name = "IBM PC110 TouchPad"; | 60 | static char *pc110pad_name = "IBM PC110 TouchPad"; |
62 | static char *pc110pad_phys = "isa15e0/input0"; | 61 | static char *pc110pad_phys = "isa15e0/input0"; |
@@ -74,7 +73,7 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) | |||
74 | 73 | ||
75 | if (pc110pad_count < 3) | 74 | if (pc110pad_count < 3) |
76 | return IRQ_HANDLED; | 75 | return IRQ_HANDLED; |
77 | 76 | ||
78 | input_regs(&pc110pad_dev, regs); | 77 | input_regs(&pc110pad_dev, regs); |
79 | input_report_key(&pc110pad_dev, BTN_TOUCH, | 78 | input_report_key(&pc110pad_dev, BTN_TOUCH, |
80 | pc110pad_data[0] & 0x01); | 79 | pc110pad_data[0] & 0x01); |
@@ -90,15 +89,11 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) | |||
90 | 89 | ||
91 | static void pc110pad_close(struct input_dev *dev) | 90 | static void pc110pad_close(struct input_dev *dev) |
92 | { | 91 | { |
93 | if (!--pc110pad_used) | 92 | outb(PC110PAD_OFF, pc110pad_io + 2); |
94 | outb(PC110PAD_OFF, pc110pad_io + 2); | ||
95 | } | 93 | } |
96 | 94 | ||
97 | static int pc110pad_open(struct input_dev *dev) | 95 | static int pc110pad_open(struct input_dev *dev) |
98 | { | 96 | { |
99 | if (pc110pad_used++) | ||
100 | return 0; | ||
101 | |||
102 | pc110pad_interrupt(0,NULL,NULL); | 97 | pc110pad_interrupt(0,NULL,NULL); |
103 | pc110pad_interrupt(0,NULL,NULL); | 98 | pc110pad_interrupt(0,NULL,NULL); |
104 | pc110pad_interrupt(0,NULL,NULL); | 99 | pc110pad_interrupt(0,NULL,NULL); |
@@ -145,7 +140,7 @@ static int __init pc110pad_init(void) | |||
145 | 140 | ||
146 | pc110pad_dev.absmax[ABS_X] = 0x1ff; | 141 | pc110pad_dev.absmax[ABS_X] = 0x1ff; |
147 | pc110pad_dev.absmax[ABS_Y] = 0x0ff; | 142 | pc110pad_dev.absmax[ABS_Y] = 0x0ff; |
148 | 143 | ||
149 | pc110pad_dev.open = pc110pad_open; | 144 | pc110pad_dev.open = pc110pad_open; |
150 | pc110pad_dev.close = pc110pad_close; | 145 | pc110pad_dev.close = pc110pad_close; |
151 | 146 | ||
@@ -156,17 +151,17 @@ static int __init pc110pad_init(void) | |||
156 | pc110pad_dev.id.product = 0x0001; | 151 | pc110pad_dev.id.product = 0x0001; |
157 | pc110pad_dev.id.version = 0x0100; | 152 | pc110pad_dev.id.version = 0x0100; |
158 | 153 | ||
159 | input_register_device(&pc110pad_dev); | 154 | input_register_device(&pc110pad_dev); |
160 | 155 | ||
161 | printk(KERN_INFO "input: %s at %#x irq %d\n", | 156 | printk(KERN_INFO "input: %s at %#x irq %d\n", |
162 | pc110pad_name, pc110pad_io, pc110pad_irq); | 157 | pc110pad_name, pc110pad_io, pc110pad_irq); |
163 | 158 | ||
164 | return 0; | 159 | return 0; |
165 | } | 160 | } |
166 | 161 | ||
167 | static void __exit pc110pad_exit(void) | 162 | static void __exit pc110pad_exit(void) |
168 | { | 163 | { |
169 | input_unregister_device(&pc110pad_dev); | 164 | input_unregister_device(&pc110pad_dev); |
170 | 165 | ||
171 | outb(PC110PAD_OFF, pc110pad_io + 2); | 166 | outb(PC110PAD_OFF, pc110pad_io + 2); |
172 | 167 | ||
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 019034b21a0b..19785a6c5abd 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "synaptics.h" | 24 | #include "synaptics.h" |
25 | #include "logips2pp.h" | 25 | #include "logips2pp.h" |
26 | #include "alps.h" | 26 | #include "alps.h" |
27 | #include "lifebook.h" | ||
27 | 28 | ||
28 | #define DRIVER_DESC "PS/2 mouse driver" | 29 | #define DRIVER_DESC "PS/2 mouse driver" |
29 | 30 | ||
@@ -31,10 +32,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | |||
31 | MODULE_DESCRIPTION(DRIVER_DESC); | 32 | MODULE_DESCRIPTION(DRIVER_DESC); |
32 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
33 | 34 | ||
34 | static unsigned int psmouse_max_proto = -1U; | 35 | static unsigned int psmouse_max_proto = PSMOUSE_AUTO; |
35 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); | 36 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); |
36 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); | 37 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); |
37 | static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL }; | ||
38 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) | 38 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) |
39 | #define param_set_proto_abbrev psmouse_set_maxproto | 39 | #define param_set_proto_abbrev psmouse_set_maxproto |
40 | #define param_get_proto_abbrev psmouse_get_maxproto | 40 | #define param_get_proto_abbrev psmouse_get_maxproto |
@@ -57,6 +57,7 @@ static unsigned int psmouse_resetafter; | |||
57 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); | 57 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); |
58 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); | 58 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); |
59 | 59 | ||
60 | PSMOUSE_DEFINE_ATTR(protocol); | ||
60 | PSMOUSE_DEFINE_ATTR(rate); | 61 | PSMOUSE_DEFINE_ATTR(rate); |
61 | PSMOUSE_DEFINE_ATTR(resolution); | 62 | PSMOUSE_DEFINE_ATTR(resolution); |
62 | PSMOUSE_DEFINE_ATTR(resetafter); | 63 | PSMOUSE_DEFINE_ATTR(resetafter); |
@@ -67,7 +68,23 @@ __obsolete_setup("psmouse_smartscroll="); | |||
67 | __obsolete_setup("psmouse_resetafter="); | 68 | __obsolete_setup("psmouse_resetafter="); |
68 | __obsolete_setup("psmouse_rate="); | 69 | __obsolete_setup("psmouse_rate="); |
69 | 70 | ||
70 | static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" }; | 71 | /* |
72 | * psmouse_sem protects all operations changing state of mouse | ||
73 | * (connecting, disconnecting, changing rate or resolution via | ||
74 | * sysfs). We could use a per-device semaphore but since there | ||
75 | * rarely more than one PS/2 mouse connected and since semaphore | ||
76 | * is taken in "slow" paths it is not worth it. | ||
77 | */ | ||
78 | static DECLARE_MUTEX(psmouse_sem); | ||
79 | |||
80 | struct psmouse_protocol { | ||
81 | enum psmouse_type type; | ||
82 | char *name; | ||
83 | char *alias; | ||
84 | int maxproto; | ||
85 | int (*detect)(struct psmouse *, int); | ||
86 | int (*init)(struct psmouse *); | ||
87 | }; | ||
71 | 88 | ||
72 | /* | 89 | /* |
73 | * psmouse_process_byte() analyzes the PS/2 data stream and reports | 90 | * psmouse_process_byte() analyzes the PS/2 data stream and reports |
@@ -407,12 +424,15 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
407 | */ | 424 | */ |
408 | static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | 425 | static int ps2bare_detect(struct psmouse *psmouse, int set_properties) |
409 | { | 426 | { |
410 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 427 | if (set_properties) { |
411 | if (!psmouse->name) psmouse->name = "Mouse"; | 428 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
429 | if (!psmouse->name) psmouse->name = "Mouse"; | ||
430 | } | ||
412 | 431 | ||
413 | return 0; | 432 | return 0; |
414 | } | 433 | } |
415 | 434 | ||
435 | |||
416 | /* | 436 | /* |
417 | * psmouse_extensions() probes for any extensions to the basic PS/2 protocol | 437 | * psmouse_extensions() probes for any extensions to the basic PS/2 protocol |
418 | * the mouse may have. | 438 | * the mouse may have. |
@@ -424,6 +444,17 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
424 | int synaptics_hardware = 0; | 444 | int synaptics_hardware = 0; |
425 | 445 | ||
426 | /* | 446 | /* |
447 | * We always check for lifebook because it does not disturb mouse | ||
448 | * (it only checks DMI information). | ||
449 | */ | ||
450 | if (lifebook_detect(psmouse, set_properties) == 0) { | ||
451 | if (max_proto > PSMOUSE_IMEX) { | ||
452 | if (!set_properties || lifebook_init(psmouse) == 0) | ||
453 | return PSMOUSE_LIFEBOOK; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | /* | ||
427 | * Try Kensington ThinkingMouse (we try first, because synaptics probe | 458 | * Try Kensington ThinkingMouse (we try first, because synaptics probe |
428 | * upsets the thinkingmouse). | 459 | * upsets the thinkingmouse). |
429 | */ | 460 | */ |
@@ -506,6 +537,103 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
506 | return PSMOUSE_PS2; | 537 | return PSMOUSE_PS2; |
507 | } | 538 | } |
508 | 539 | ||
540 | static struct psmouse_protocol psmouse_protocols[] = { | ||
541 | { | ||
542 | .type = PSMOUSE_PS2, | ||
543 | .name = "PS/2", | ||
544 | .alias = "bare", | ||
545 | .maxproto = 1, | ||
546 | .detect = ps2bare_detect, | ||
547 | }, | ||
548 | { | ||
549 | .type = PSMOUSE_PS2PP, | ||
550 | .name = "PS2++", | ||
551 | .alias = "logitech", | ||
552 | .detect = ps2pp_init, | ||
553 | }, | ||
554 | { | ||
555 | .type = PSMOUSE_THINKPS, | ||
556 | .name = "ThinkPS/2", | ||
557 | .alias = "thinkps", | ||
558 | .detect = thinking_detect, | ||
559 | }, | ||
560 | { | ||
561 | .type = PSMOUSE_GENPS, | ||
562 | .name = "GenPS/2", | ||
563 | .alias = "genius", | ||
564 | .detect = genius_detect, | ||
565 | }, | ||
566 | { | ||
567 | .type = PSMOUSE_IMPS, | ||
568 | .name = "ImPS/2", | ||
569 | .alias = "imps", | ||
570 | .maxproto = 1, | ||
571 | .detect = intellimouse_detect, | ||
572 | }, | ||
573 | { | ||
574 | .type = PSMOUSE_IMEX, | ||
575 | .name = "ImExPS/2", | ||
576 | .alias = "exps", | ||
577 | .maxproto = 1, | ||
578 | .detect = im_explorer_detect, | ||
579 | }, | ||
580 | { | ||
581 | .type = PSMOUSE_SYNAPTICS, | ||
582 | .name = "SynPS/2", | ||
583 | .alias = "synaptics", | ||
584 | .detect = synaptics_detect, | ||
585 | .init = synaptics_init, | ||
586 | }, | ||
587 | { | ||
588 | .type = PSMOUSE_ALPS, | ||
589 | .name = "AlpsPS/2", | ||
590 | .alias = "alps", | ||
591 | .detect = alps_detect, | ||
592 | .init = alps_init, | ||
593 | }, | ||
594 | { | ||
595 | .type = PSMOUSE_LIFEBOOK, | ||
596 | .name = "LBPS/2", | ||
597 | .alias = "lifebook", | ||
598 | .init = lifebook_init, | ||
599 | }, | ||
600 | { | ||
601 | .type = PSMOUSE_AUTO, | ||
602 | .name = "auto", | ||
603 | .alias = "any", | ||
604 | .maxproto = 1, | ||
605 | }, | ||
606 | }; | ||
607 | |||
608 | static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) | ||
609 | { | ||
610 | int i; | ||
611 | |||
612 | for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) | ||
613 | if (psmouse_protocols[i].type == type) | ||
614 | return &psmouse_protocols[i]; | ||
615 | |||
616 | WARN_ON(1); | ||
617 | return &psmouse_protocols[0]; | ||
618 | } | ||
619 | |||
620 | static struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len) | ||
621 | { | ||
622 | struct psmouse_protocol *p; | ||
623 | int i; | ||
624 | |||
625 | for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) { | ||
626 | p = &psmouse_protocols[i]; | ||
627 | |||
628 | if ((strlen(p->name) == len && !strncmp(p->name, name, len)) || | ||
629 | (strlen(p->alias) == len && !strncmp(p->alias, name, len))) | ||
630 | return &psmouse_protocols[i]; | ||
631 | } | ||
632 | |||
633 | return NULL; | ||
634 | } | ||
635 | |||
636 | |||
509 | /* | 637 | /* |
510 | * psmouse_probe() probes for a PS/2 mouse. | 638 | * psmouse_probe() probes for a PS/2 mouse. |
511 | */ | 639 | */ |
@@ -653,30 +781,84 @@ static void psmouse_cleanup(struct serio *serio) | |||
653 | 781 | ||
654 | static void psmouse_disconnect(struct serio *serio) | 782 | static void psmouse_disconnect(struct serio *serio) |
655 | { | 783 | { |
656 | struct psmouse *psmouse, *parent; | 784 | struct psmouse *psmouse, *parent = NULL; |
657 | 785 | ||
786 | psmouse = serio_get_drvdata(serio); | ||
787 | |||
788 | device_remove_file(&serio->dev, &psmouse_attr_protocol); | ||
658 | device_remove_file(&serio->dev, &psmouse_attr_rate); | 789 | device_remove_file(&serio->dev, &psmouse_attr_rate); |
659 | device_remove_file(&serio->dev, &psmouse_attr_resolution); | 790 | device_remove_file(&serio->dev, &psmouse_attr_resolution); |
660 | device_remove_file(&serio->dev, &psmouse_attr_resetafter); | 791 | device_remove_file(&serio->dev, &psmouse_attr_resetafter); |
661 | 792 | ||
662 | psmouse = serio_get_drvdata(serio); | 793 | down(&psmouse_sem); |
794 | |||
663 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 795 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
664 | 796 | ||
665 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 797 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
666 | parent = serio_get_drvdata(serio->parent); | 798 | parent = serio_get_drvdata(serio->parent); |
667 | if (parent->pt_deactivate) | 799 | psmouse_deactivate(parent); |
668 | parent->pt_deactivate(parent); | ||
669 | } | 800 | } |
670 | 801 | ||
671 | if (psmouse->disconnect) | 802 | if (psmouse->disconnect) |
672 | psmouse->disconnect(psmouse); | 803 | psmouse->disconnect(psmouse); |
673 | 804 | ||
805 | if (parent && parent->pt_deactivate) | ||
806 | parent->pt_deactivate(parent); | ||
807 | |||
674 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 808 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
675 | 809 | ||
676 | input_unregister_device(&psmouse->dev); | 810 | input_unregister_device(&psmouse->dev); |
677 | serio_close(serio); | 811 | serio_close(serio); |
678 | serio_set_drvdata(serio, NULL); | 812 | serio_set_drvdata(serio, NULL); |
679 | kfree(psmouse); | 813 | kfree(psmouse); |
814 | |||
815 | if (parent) | ||
816 | psmouse_activate(parent); | ||
817 | |||
818 | up(&psmouse_sem); | ||
819 | } | ||
820 | |||
821 | static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto) | ||
822 | { | ||
823 | memset(&psmouse->dev, 0, sizeof(struct input_dev)); | ||
824 | |||
825 | init_input_dev(&psmouse->dev); | ||
826 | |||
827 | psmouse->dev.private = psmouse; | ||
828 | psmouse->dev.dev = &psmouse->ps2dev.serio->dev; | ||
829 | |||
830 | psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
831 | psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
832 | psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
833 | |||
834 | psmouse->set_rate = psmouse_set_rate; | ||
835 | psmouse->set_resolution = psmouse_set_resolution; | ||
836 | psmouse->protocol_handler = psmouse_process_byte; | ||
837 | psmouse->pktsize = 3; | ||
838 | |||
839 | if (proto && (proto->detect || proto->init)) { | ||
840 | if (proto->detect && proto->detect(psmouse, 1) < 0) | ||
841 | return -1; | ||
842 | |||
843 | if (proto->init && proto->init(psmouse) < 0) | ||
844 | return -1; | ||
845 | |||
846 | psmouse->type = proto->type; | ||
847 | } | ||
848 | else | ||
849 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | ||
850 | |||
851 | sprintf(psmouse->devname, "%s %s %s", | ||
852 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | ||
853 | |||
854 | psmouse->dev.name = psmouse->devname; | ||
855 | psmouse->dev.phys = psmouse->phys; | ||
856 | psmouse->dev.id.bustype = BUS_I8042; | ||
857 | psmouse->dev.id.vendor = 0x0002; | ||
858 | psmouse->dev.id.product = psmouse->type; | ||
859 | psmouse->dev.id.version = psmouse->model; | ||
860 | |||
861 | return 0; | ||
680 | } | 862 | } |
681 | 863 | ||
682 | /* | 864 | /* |
@@ -688,6 +870,8 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
688 | struct psmouse *psmouse, *parent = NULL; | 870 | struct psmouse *psmouse, *parent = NULL; |
689 | int retval; | 871 | int retval; |
690 | 872 | ||
873 | down(&psmouse_sem); | ||
874 | |||
691 | /* | 875 | /* |
692 | * If this is a pass-through port deactivate parent so the device | 876 | * If this is a pass-through port deactivate parent so the device |
693 | * connected to this port can be successfully identified | 877 | * connected to this port can be successfully identified |
@@ -697,20 +881,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
697 | psmouse_deactivate(parent); | 881 | psmouse_deactivate(parent); |
698 | } | 882 | } |
699 | 883 | ||
700 | if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) { | 884 | if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) { |
701 | retval = -ENOMEM; | 885 | retval = -ENOMEM; |
702 | goto out; | 886 | goto out; |
703 | } | 887 | } |
704 | 888 | ||
705 | memset(psmouse, 0, sizeof(struct psmouse)); | ||
706 | |||
707 | ps2_init(&psmouse->ps2dev, serio); | 889 | ps2_init(&psmouse->ps2dev, serio); |
708 | sprintf(psmouse->phys, "%s/input0", serio->phys); | 890 | sprintf(psmouse->phys, "%s/input0", serio->phys); |
709 | psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 891 | |
710 | psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
711 | psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
712 | psmouse->dev.private = psmouse; | ||
713 | psmouse->dev.dev = &serio->dev; | ||
714 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | 892 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); |
715 | 893 | ||
716 | serio_set_drvdata(serio, psmouse); | 894 | serio_set_drvdata(serio, psmouse); |
@@ -734,25 +912,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
734 | psmouse->resolution = psmouse_resolution; | 912 | psmouse->resolution = psmouse_resolution; |
735 | psmouse->resetafter = psmouse_resetafter; | 913 | psmouse->resetafter = psmouse_resetafter; |
736 | psmouse->smartscroll = psmouse_smartscroll; | 914 | psmouse->smartscroll = psmouse_smartscroll; |
737 | psmouse->set_rate = psmouse_set_rate; | ||
738 | psmouse->set_resolution = psmouse_set_resolution; | ||
739 | psmouse->protocol_handler = psmouse_process_byte; | ||
740 | psmouse->pktsize = 3; | ||
741 | 915 | ||
742 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 916 | psmouse_switch_protocol(psmouse, NULL); |
743 | |||
744 | sprintf(psmouse->devname, "%s %s %s", | ||
745 | psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name); | ||
746 | |||
747 | psmouse->dev.name = psmouse->devname; | ||
748 | psmouse->dev.phys = psmouse->phys; | ||
749 | psmouse->dev.id.bustype = BUS_I8042; | ||
750 | psmouse->dev.id.vendor = 0x0002; | ||
751 | psmouse->dev.id.product = psmouse->type; | ||
752 | psmouse->dev.id.version = psmouse->model; | ||
753 | 917 | ||
754 | input_register_device(&psmouse->dev); | 918 | input_register_device(&psmouse->dev); |
755 | |||
756 | printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); | 919 | printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); |
757 | 920 | ||
758 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 921 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
@@ -762,6 +925,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
762 | if (parent && parent->pt_activate) | 925 | if (parent && parent->pt_activate) |
763 | parent->pt_activate(parent); | 926 | parent->pt_activate(parent); |
764 | 927 | ||
928 | device_create_file(&serio->dev, &psmouse_attr_protocol); | ||
765 | device_create_file(&serio->dev, &psmouse_attr_rate); | 929 | device_create_file(&serio->dev, &psmouse_attr_rate); |
766 | device_create_file(&serio->dev, &psmouse_attr_resolution); | 930 | device_create_file(&serio->dev, &psmouse_attr_resolution); |
767 | device_create_file(&serio->dev, &psmouse_attr_resetafter); | 931 | device_create_file(&serio->dev, &psmouse_attr_resetafter); |
@@ -771,10 +935,11 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
771 | retval = 0; | 935 | retval = 0; |
772 | 936 | ||
773 | out: | 937 | out: |
774 | /* If this is a pass-through port the parent awaits to be activated */ | 938 | /* If this is a pass-through port the parent needs to be re-activated */ |
775 | if (parent) | 939 | if (parent) |
776 | psmouse_activate(parent); | 940 | psmouse_activate(parent); |
777 | 941 | ||
942 | up(&psmouse_sem); | ||
778 | return retval; | 943 | return retval; |
779 | } | 944 | } |
780 | 945 | ||
@@ -791,6 +956,8 @@ static int psmouse_reconnect(struct serio *serio) | |||
791 | return -1; | 956 | return -1; |
792 | } | 957 | } |
793 | 958 | ||
959 | down(&psmouse_sem); | ||
960 | |||
794 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 961 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
795 | parent = serio_get_drvdata(serio->parent); | 962 | parent = serio_get_drvdata(serio->parent); |
796 | psmouse_deactivate(parent); | 963 | psmouse_deactivate(parent); |
@@ -823,6 +990,7 @@ out: | |||
823 | if (parent) | 990 | if (parent) |
824 | psmouse_activate(parent); | 991 | psmouse_activate(parent); |
825 | 992 | ||
993 | up(&psmouse_sem); | ||
826 | return rc; | 994 | return rc; |
827 | } | 995 | } |
828 | 996 | ||
@@ -893,26 +1061,109 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun | |||
893 | 1061 | ||
894 | if (serio->drv != &psmouse_drv) { | 1062 | if (serio->drv != &psmouse_drv) { |
895 | retval = -ENODEV; | 1063 | retval = -ENODEV; |
896 | goto out; | 1064 | goto out_unpin; |
1065 | } | ||
1066 | |||
1067 | retval = down_interruptible(&psmouse_sem); | ||
1068 | if (retval) | ||
1069 | goto out_unpin; | ||
1070 | |||
1071 | if (psmouse->state == PSMOUSE_IGNORE) { | ||
1072 | retval = -ENODEV; | ||
1073 | goto out_up; | ||
897 | } | 1074 | } |
898 | 1075 | ||
899 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 1076 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
900 | parent = serio_get_drvdata(serio->parent); | 1077 | parent = serio_get_drvdata(serio->parent); |
901 | psmouse_deactivate(parent); | 1078 | psmouse_deactivate(parent); |
902 | } | 1079 | } |
1080 | |||
903 | psmouse_deactivate(psmouse); | 1081 | psmouse_deactivate(psmouse); |
904 | 1082 | ||
905 | retval = handler(psmouse, buf, count); | 1083 | retval = handler(psmouse, buf, count); |
906 | 1084 | ||
907 | psmouse_activate(psmouse); | 1085 | if (retval != -ENODEV) |
1086 | psmouse_activate(psmouse); | ||
1087 | |||
908 | if (parent) | 1088 | if (parent) |
909 | psmouse_activate(parent); | 1089 | psmouse_activate(parent); |
910 | 1090 | ||
911 | out: | 1091 | out_up: |
1092 | up(&psmouse_sem); | ||
1093 | out_unpin: | ||
912 | serio_unpin_driver(serio); | 1094 | serio_unpin_driver(serio); |
913 | return retval; | 1095 | return retval; |
914 | } | 1096 | } |
915 | 1097 | ||
1098 | static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf) | ||
1099 | { | ||
1100 | return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name); | ||
1101 | } | ||
1102 | |||
1103 | static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count) | ||
1104 | { | ||
1105 | struct serio *serio = psmouse->ps2dev.serio; | ||
1106 | struct psmouse *parent = NULL; | ||
1107 | struct psmouse_protocol *proto; | ||
1108 | int retry = 0; | ||
1109 | |||
1110 | if (!(proto = psmouse_protocol_by_name(buf, count))) | ||
1111 | return -EINVAL; | ||
1112 | |||
1113 | if (psmouse->type == proto->type) | ||
1114 | return count; | ||
1115 | |||
1116 | while (serio->child) { | ||
1117 | if (++retry > 3) { | ||
1118 | printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n"); | ||
1119 | return -EIO; | ||
1120 | } | ||
1121 | |||
1122 | up(&psmouse_sem); | ||
1123 | serio_unpin_driver(serio); | ||
1124 | serio_unregister_child_port(serio); | ||
1125 | serio_pin_driver_uninterruptible(serio); | ||
1126 | down(&psmouse_sem); | ||
1127 | |||
1128 | if (serio->drv != &psmouse_drv) | ||
1129 | return -ENODEV; | ||
1130 | |||
1131 | if (psmouse->type == proto->type) | ||
1132 | return count; /* switched by other thread */ | ||
1133 | } | ||
1134 | |||
1135 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | ||
1136 | parent = serio_get_drvdata(serio->parent); | ||
1137 | if (parent->pt_deactivate) | ||
1138 | parent->pt_deactivate(parent); | ||
1139 | } | ||
1140 | |||
1141 | if (psmouse->disconnect) | ||
1142 | psmouse->disconnect(psmouse); | ||
1143 | |||
1144 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
1145 | input_unregister_device(&psmouse->dev); | ||
1146 | |||
1147 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | ||
1148 | |||
1149 | if (psmouse_switch_protocol(psmouse, proto) < 0) { | ||
1150 | psmouse_reset(psmouse); | ||
1151 | /* default to PSMOUSE_PS2 */ | ||
1152 | psmouse_switch_protocol(psmouse, &psmouse_protocols[0]); | ||
1153 | } | ||
1154 | |||
1155 | psmouse_initialize(psmouse); | ||
1156 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
1157 | |||
1158 | input_register_device(&psmouse->dev); | ||
1159 | printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); | ||
1160 | |||
1161 | if (parent && parent->pt_activate) | ||
1162 | parent->pt_activate(parent); | ||
1163 | |||
1164 | return count; | ||
1165 | } | ||
1166 | |||
916 | static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) | 1167 | static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) |
917 | { | 1168 | { |
918 | return sprintf(buf, "%d\n", psmouse->rate); | 1169 | return sprintf(buf, "%d\n", psmouse->rate); |
@@ -969,34 +1220,26 @@ static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char * | |||
969 | 1220 | ||
970 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | 1221 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) |
971 | { | 1222 | { |
972 | int i; | 1223 | struct psmouse_protocol *proto; |
973 | 1224 | ||
974 | if (!val) | 1225 | if (!val) |
975 | return -EINVAL; | 1226 | return -EINVAL; |
976 | 1227 | ||
977 | if (!strncmp(val, "any", 3)) { | 1228 | proto = psmouse_protocol_by_name(val, strlen(val)); |
978 | *((unsigned int *)kp->arg) = -1U; | ||
979 | return 0; | ||
980 | } | ||
981 | 1229 | ||
982 | for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) { | 1230 | if (!proto || !proto->maxproto) |
983 | if (!psmouse_proto_abbrev[i]) | 1231 | return -EINVAL; |
984 | continue; | ||
985 | 1232 | ||
986 | if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) { | 1233 | *((unsigned int *)kp->arg) = proto->type; |
987 | *((unsigned int *)kp->arg) = i; | ||
988 | return 0; | ||
989 | } | ||
990 | } | ||
991 | 1234 | ||
992 | return -EINVAL; \ | 1235 | return 0; \ |
993 | } | 1236 | } |
994 | 1237 | ||
995 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | 1238 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) |
996 | { | 1239 | { |
997 | return sprintf(buffer, "%s\n", | 1240 | int type = *((unsigned int *)kp->arg); |
998 | psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ? | 1241 | |
999 | psmouse_proto_abbrev[psmouse_max_proto] : "any"); | 1242 | return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name); |
1000 | } | 1243 | } |
1001 | 1244 | ||
1002 | static int __init psmouse_init(void) | 1245 | static int __init psmouse_init(void) |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 79e17a0c4664..86691cf43433 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -77,6 +77,8 @@ enum psmouse_type { | |||
77 | PSMOUSE_IMEX, | 77 | PSMOUSE_IMEX, |
78 | PSMOUSE_SYNAPTICS, | 78 | PSMOUSE_SYNAPTICS, |
79 | PSMOUSE_ALPS, | 79 | PSMOUSE_ALPS, |
80 | PSMOUSE_LIFEBOOK, | ||
81 | PSMOUSE_AUTO /* This one should always be last */ | ||
80 | }; | 82 | }; |
81 | 83 | ||
82 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); | 84 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); |
@@ -99,7 +101,7 @@ static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute | |||
99 | { \ | 101 | { \ |
100 | return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ | 102 | return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ |
101 | } \ | 103 | } \ |
102 | static struct device_attribute psmouse_attr_##_name = \ | 104 | static struct device_attribute psmouse_attr_##_name = \ |
103 | __ATTR(_name, S_IWUSR | S_IRUGO, \ | 105 | __ATTR(_name, S_IWUSR | S_IRUGO, \ |
104 | psmouse_do_show_##_name, psmouse_do_set_##_name); | 106 | psmouse_do_show_##_name, psmouse_do_set_##_name); |
105 | 107 | ||
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c index 7280f68afcee..8fe1212b8fd7 100644 --- a/drivers/input/mouse/rpcmouse.c +++ b/drivers/input/mouse/rpcmouse.c | |||
@@ -59,7 +59,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
59 | b = (short) (__raw_readl(0xe0310000) ^ 0x70); | 59 | b = (short) (__raw_readl(0xe0310000) ^ 0x70); |
60 | 60 | ||
61 | dx = x - rpcmouse_lastx; | 61 | dx = x - rpcmouse_lastx; |
62 | dy = y - rpcmouse_lasty; | 62 | dy = y - rpcmouse_lasty; |
63 | 63 | ||
64 | rpcmouse_lastx = x; | 64 | rpcmouse_lastx = x; |
65 | rpcmouse_lasty = y; | 65 | rpcmouse_lasty = y; |
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index b2cb101c8110..f024be9b44d2 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) | 2 | * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) |
3 | * DEC VSXXX-GA mouse (rectangular mouse, with ball) | 3 | * DEC VSXXX-GA mouse (rectangular mouse, with ball) |
4 | * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) | 4 | * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) |
5 | * | 5 | * |
6 | * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de> | 6 | * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de> |
7 | * | 7 | * |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 062848ac7e6b..c6194a9dd174 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -220,6 +220,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h | |||
220 | struct mousedev_list *list; | 220 | struct mousedev_list *list; |
221 | struct mousedev_motion *p; | 221 | struct mousedev_motion *p; |
222 | unsigned long flags; | 222 | unsigned long flags; |
223 | int wake_readers = 0; | ||
223 | 224 | ||
224 | list_for_each_entry(list, &mousedev->list, node) { | 225 | list_for_each_entry(list, &mousedev->list, node) { |
225 | spin_lock_irqsave(&list->packet_lock, flags); | 226 | spin_lock_irqsave(&list->packet_lock, flags); |
@@ -255,11 +256,14 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h | |||
255 | 256 | ||
256 | spin_unlock_irqrestore(&list->packet_lock, flags); | 257 | spin_unlock_irqrestore(&list->packet_lock, flags); |
257 | 258 | ||
258 | if (list->ready) | 259 | if (list->ready) { |
259 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | 260 | kill_fasync(&list->fasync, SIGIO, POLL_IN); |
261 | wake_readers = 1; | ||
262 | } | ||
260 | } | 263 | } |
261 | 264 | ||
262 | wake_up_interruptible(&mousedev->wait); | 265 | if (wake_readers) |
266 | wake_up_interruptible(&mousedev->wait); | ||
263 | } | 267 | } |
264 | 268 | ||
265 | static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | 269 | static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index c978657068c5..d4c990f7c85e 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL"); | |||
29 | 29 | ||
30 | EXPORT_SYMBOL(ps2_init); | 30 | EXPORT_SYMBOL(ps2_init); |
31 | EXPORT_SYMBOL(ps2_sendbyte); | 31 | EXPORT_SYMBOL(ps2_sendbyte); |
32 | EXPORT_SYMBOL(ps2_drain); | ||
32 | EXPORT_SYMBOL(ps2_command); | 33 | EXPORT_SYMBOL(ps2_command); |
33 | EXPORT_SYMBOL(ps2_schedule_command); | 34 | EXPORT_SYMBOL(ps2_schedule_command); |
34 | EXPORT_SYMBOL(ps2_handle_ack); | 35 | EXPORT_SYMBOL(ps2_handle_ack); |
@@ -45,11 +46,11 @@ struct ps2work { | |||
45 | 46 | ||
46 | 47 | ||
47 | /* | 48 | /* |
48 | * ps2_sendbyte() sends a byte to the mouse, and waits for acknowledge. | 49 | * ps2_sendbyte() sends a byte to the device and waits for acknowledge. |
49 | * It doesn't handle retransmission, though it could - because when there would | 50 | * It doesn't handle retransmission, though it could - because if there |
50 | * be need for retransmissions, the mouse has to be replaced anyway. | 51 | * is a need for retransmissions device has to be replaced anyway. |
51 | * | 52 | * |
52 | * ps2_sendbyte() can only be called from a process context | 53 | * ps2_sendbyte() can only be called from a process context. |
53 | */ | 54 | */ |
54 | 55 | ||
55 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | 56 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) |
@@ -72,6 +73,91 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | |||
72 | } | 73 | } |
73 | 74 | ||
74 | /* | 75 | /* |
76 | * ps2_drain() waits for device to transmit requested number of bytes | ||
77 | * and discards them. | ||
78 | */ | ||
79 | |||
80 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | ||
81 | { | ||
82 | if (maxbytes > sizeof(ps2dev->cmdbuf)) { | ||
83 | WARN_ON(1); | ||
84 | maxbytes = sizeof(ps2dev->cmdbuf); | ||
85 | } | ||
86 | |||
87 | down(&ps2dev->cmd_sem); | ||
88 | |||
89 | serio_pause_rx(ps2dev->serio); | ||
90 | ps2dev->flags = PS2_FLAG_CMD; | ||
91 | ps2dev->cmdcnt = maxbytes; | ||
92 | serio_continue_rx(ps2dev->serio); | ||
93 | |||
94 | wait_event_timeout(ps2dev->wait, | ||
95 | !(ps2dev->flags & PS2_FLAG_CMD), | ||
96 | msecs_to_jiffies(timeout)); | ||
97 | up(&ps2dev->cmd_sem); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * ps2_is_keyboard_id() checks received ID byte against the list of | ||
102 | * known keyboard IDs. | ||
103 | */ | ||
104 | |||
105 | static inline int ps2_is_keyboard_id(char id_byte) | ||
106 | { | ||
107 | static char keyboard_ids[] = { | ||
108 | 0xab, /* Regular keyboards */ | ||
109 | 0xac, /* NCD Sun keyboard */ | ||
110 | 0x2b, /* Trust keyboard, translated */ | ||
111 | 0x5d, /* Trust keyboard */ | ||
112 | 0x60, /* NMB SGI keyboard, translated */ | ||
113 | 0x47, /* NMB SGI keyboard */ | ||
114 | }; | ||
115 | |||
116 | return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * ps2_adjust_timeout() is called after receiving 1st byte of command | ||
121 | * response and tries to reduce remaining timeout to speed up command | ||
122 | * completion. | ||
123 | */ | ||
124 | |||
125 | static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) | ||
126 | { | ||
127 | switch (command) { | ||
128 | case PS2_CMD_RESET_BAT: | ||
129 | /* | ||
130 | * Device has sent the first response byte after | ||
131 | * reset command, reset is thus done, so we can | ||
132 | * shorten the timeout. | ||
133 | * The next byte will come soon (keyboard) or not | ||
134 | * at all (mouse). | ||
135 | */ | ||
136 | if (timeout > msecs_to_jiffies(100)) | ||
137 | timeout = msecs_to_jiffies(100); | ||
138 | break; | ||
139 | |||
140 | case PS2_CMD_GETID: | ||
141 | /* | ||
142 | * If device behind the port is not a keyboard there | ||
143 | * won't be 2nd byte of ID response. | ||
144 | */ | ||
145 | if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) { | ||
146 | serio_pause_rx(ps2dev->serio); | ||
147 | ps2dev->flags = ps2dev->cmdcnt = 0; | ||
148 | serio_continue_rx(ps2dev->serio); | ||
149 | timeout = 0; | ||
150 | } | ||
151 | break; | ||
152 | |||
153 | default: | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | return timeout; | ||
158 | } | ||
159 | |||
160 | /* | ||
75 | * ps2_command() sends a command and its parameters to the mouse, | 161 | * ps2_command() sends a command and its parameters to the mouse, |
76 | * then waits for the response and puts it in the param array. | 162 | * then waits for the response and puts it in the param array. |
77 | * | 163 | * |
@@ -86,6 +172,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
86 | int rc = -1; | 172 | int rc = -1; |
87 | int i; | 173 | int i; |
88 | 174 | ||
175 | if (receive > sizeof(ps2dev->cmdbuf)) { | ||
176 | WARN_ON(1); | ||
177 | return -1; | ||
178 | } | ||
179 | |||
89 | down(&ps2dev->cmd_sem); | 180 | down(&ps2dev->cmd_sem); |
90 | 181 | ||
91 | serio_pause_rx(ps2dev->serio); | 182 | serio_pause_rx(ps2dev->serio); |
@@ -101,10 +192,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
101 | * ACKing the reset command, and so it can take a long | 192 | * ACKing the reset command, and so it can take a long |
102 | * time before the ACK arrrives. | 193 | * time before the ACK arrrives. |
103 | */ | 194 | */ |
104 | if (command & 0xff) | 195 | if (ps2_sendbyte(ps2dev, command & 0xff, |
105 | if (ps2_sendbyte(ps2dev, command & 0xff, | 196 | command == PS2_CMD_RESET_BAT ? 1000 : 200)) |
106 | command == PS2_CMD_RESET_BAT ? 1000 : 200)) | 197 | goto out; |
107 | goto out; | ||
108 | 198 | ||
109 | for (i = 0; i < send; i++) | 199 | for (i = 0; i < send; i++) |
110 | if (ps2_sendbyte(ps2dev, param[i], 200)) | 200 | if (ps2_sendbyte(ps2dev, param[i], 200)) |
@@ -120,33 +210,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
120 | 210 | ||
121 | if (ps2dev->cmdcnt && timeout > 0) { | 211 | if (ps2dev->cmdcnt && timeout > 0) { |
122 | 212 | ||
123 | if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) { | 213 | timeout = ps2_adjust_timeout(ps2dev, command, timeout); |
124 | /* | ||
125 | * Device has sent the first response byte | ||
126 | * after a reset command, reset is thus done, | ||
127 | * shorten the timeout. The next byte will come | ||
128 | * soon (keyboard) or not at all (mouse). | ||
129 | */ | ||
130 | timeout = msecs_to_jiffies(100); | ||
131 | } | ||
132 | |||
133 | if (command == PS2_CMD_GETID && | ||
134 | ps2dev->cmdbuf[receive - 1] != 0xab && /* Regular keyboards */ | ||
135 | ps2dev->cmdbuf[receive - 1] != 0xac && /* NCD Sun keyboard */ | ||
136 | ps2dev->cmdbuf[receive - 1] != 0x2b && /* Trust keyboard, translated */ | ||
137 | ps2dev->cmdbuf[receive - 1] != 0x5d && /* Trust keyboard */ | ||
138 | ps2dev->cmdbuf[receive - 1] != 0x60 && /* NMB SGI keyboard, translated */ | ||
139 | ps2dev->cmdbuf[receive - 1] != 0x47) { /* NMB SGI keyboard */ | ||
140 | /* | ||
141 | * Device behind the port is not a keyboard | ||
142 | * so we don't need to wait for the 2nd byte | ||
143 | * of ID response. | ||
144 | */ | ||
145 | serio_pause_rx(ps2dev->serio); | ||
146 | ps2dev->flags = ps2dev->cmdcnt = 0; | ||
147 | serio_continue_rx(ps2dev->serio); | ||
148 | } | ||
149 | |||
150 | wait_event_timeout(ps2dev->wait, | 214 | wait_event_timeout(ps2dev->wait, |
151 | !(ps2dev->flags & PS2_FLAG_CMD), timeout); | 215 | !(ps2dev->flags & PS2_FLAG_CMD), timeout); |
152 | } | 216 | } |
@@ -160,7 +224,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
160 | 224 | ||
161 | rc = 0; | 225 | rc = 0; |
162 | 226 | ||
163 | out: | 227 | out: |
164 | serio_pause_rx(ps2dev->serio); | 228 | serio_pause_rx(ps2dev->serio); |
165 | ps2dev->flags = 0; | 229 | ps2dev->flags = 0; |
166 | serio_continue_rx(ps2dev->serio); | 230 | serio_continue_rx(ps2dev->serio); |
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 546ce599334e..3cdc9cab688d 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c | |||
@@ -226,7 +226,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
226 | input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); | 226 | input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); |
227 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0); | 227 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0); |
228 | break; | 228 | break; |
229 | 229 | ||
230 | case 1: /* 6-byte protocol */ | 230 | case 1: /* 6-byte protocol */ |
231 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0); | 231 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0); |
232 | 232 | ||
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index acb9137a0226..bcfa1e36f957 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
@@ -89,9 +89,9 @@ MODULE_LICENSE("GPL"); | |||
89 | #define H3600_SCANCODE_Q 4 /* 4 -> Q button */ | 89 | #define H3600_SCANCODE_Q 4 /* 4 -> Q button */ |
90 | #define H3600_SCANCODE_START 5 /* 5 -> start menu */ | 90 | #define H3600_SCANCODE_START 5 /* 5 -> start menu */ |
91 | #define H3600_SCANCODE_UP 6 /* 6 -> up */ | 91 | #define H3600_SCANCODE_UP 6 /* 6 -> up */ |
92 | #define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ | 92 | #define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ |
93 | #define H3600_SCANCODE_LEFT 8 /* 8 -> left */ | 93 | #define H3600_SCANCODE_LEFT 8 /* 8 -> left */ |
94 | #define H3600_SCANCODE_DOWN 9 /* 9 -> down */ | 94 | #define H3600_SCANCODE_DOWN 9 /* 9 -> down */ |
95 | 95 | ||
96 | static char *h3600_name = "H3600 TouchScreen"; | 96 | static char *h3600_name = "H3600 TouchScreen"; |
97 | 97 | ||
@@ -113,7 +113,7 @@ struct h3600_dev { | |||
113 | 113 | ||
114 | static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs) | 114 | static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs) |
115 | { | 115 | { |
116 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; | 116 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; |
117 | struct input_dev *dev = (struct input_dev *) dev_id; | 117 | struct input_dev *dev = (struct input_dev *) dev_id; |
118 | 118 | ||
119 | input_regs(dev, regs); | 119 | input_regs(dev, regs); |
@@ -125,7 +125,7 @@ static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs * | |||
125 | 125 | ||
126 | static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) | 126 | static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) |
127 | { | 127 | { |
128 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; | 128 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; |
129 | struct input_dev *dev = (struct input_dev *) dev_id; | 129 | struct input_dev *dev = (struct input_dev *) dev_id; |
130 | 130 | ||
131 | /* | 131 | /* |
@@ -145,8 +145,8 @@ static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs * | |||
145 | static int flite_brightness = 25; | 145 | static int flite_brightness = 25; |
146 | 146 | ||
147 | enum flite_pwr { | 147 | enum flite_pwr { |
148 | FLITE_PWR_OFF = 0, | 148 | FLITE_PWR_OFF = 0, |
149 | FLITE_PWR_ON = 1 | 149 | FLITE_PWR_ON = 1 |
150 | }; | 150 | }; |
151 | 151 | ||
152 | /* | 152 | /* |
@@ -157,9 +157,9 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) | |||
157 | struct h3600_dev *ts = dev->private; | 157 | struct h3600_dev *ts = dev->private; |
158 | 158 | ||
159 | /* Must be in this order */ | 159 | /* Must be in this order */ |
160 | ts->serio->write(ts->serio, 1); | 160 | ts->serio->write(ts->serio, 1); |
161 | ts->serio->write(ts->serio, pwr); | 161 | ts->serio->write(ts->serio, pwr); |
162 | ts->serio->write(ts->serio, brightness); | 162 | ts->serio->write(ts->serio, brightness); |
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
165 | 165 | ||
@@ -169,26 +169,26 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, | |||
169 | { | 169 | { |
170 | struct input_dev *dev = (struct input_dev *) data; | 170 | struct input_dev *dev = (struct input_dev *) data; |
171 | 171 | ||
172 | switch (req) { | 172 | switch (req) { |
173 | case PM_SUSPEND: /* enter D1-D3 */ | 173 | case PM_SUSPEND: /* enter D1-D3 */ |
174 | suspended = 1; | 174 | suspended = 1; |
175 | h3600_flite_power(dev, FLITE_PWR_OFF); | 175 | h3600_flite_power(dev, FLITE_PWR_OFF); |
176 | break; | 176 | break; |
177 | case PM_BLANK: | 177 | case PM_BLANK: |
178 | if (!suspended) | 178 | if (!suspended) |
179 | h3600_flite_power(dev, FLITE_PWR_OFF); | 179 | h3600_flite_power(dev, FLITE_PWR_OFF); |
180 | break; | 180 | break; |
181 | case PM_RESUME: /* enter D0 */ | 181 | case PM_RESUME: /* enter D0 */ |
182 | /* same as unblank */ | 182 | /* same as unblank */ |
183 | case PM_UNBLANK: | 183 | case PM_UNBLANK: |
184 | if (suspended) { | 184 | if (suspended) { |
185 | //initSerial(); | 185 | //initSerial(); |
186 | suspended = 0; | 186 | suspended = 0; |
187 | } | 187 | } |
188 | h3600_flite_power(dev, FLITE_PWR_ON); | 188 | h3600_flite_power(dev, FLITE_PWR_ON); |
189 | break; | 189 | break; |
190 | } | 190 | } |
191 | return 0; | 191 | return 0; |
192 | } | 192 | } |
193 | #endif | 193 | #endif |
194 | 194 | ||
@@ -199,25 +199,25 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, | |||
199 | */ | 199 | */ |
200 | static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | 200 | static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) |
201 | { | 201 | { |
202 | struct input_dev *dev = &ts->dev; | 202 | struct input_dev *dev = &ts->dev; |
203 | static int touched = 0; | 203 | static int touched = 0; |
204 | int key, down = 0; | 204 | int key, down = 0; |
205 | 205 | ||
206 | input_regs(dev, regs); | 206 | input_regs(dev, regs); |
207 | 207 | ||
208 | switch (ts->event) { | 208 | switch (ts->event) { |
209 | /* | 209 | /* |
210 | Buttons - returned as a single byte | 210 | Buttons - returned as a single byte |
211 | 7 6 5 4 3 2 1 0 | 211 | 7 6 5 4 3 2 1 0 |
212 | S x x x N N N N | 212 | S x x x N N N N |
213 | 213 | ||
214 | S switch state ( 0=pressed 1=released) | 214 | S switch state ( 0=pressed 1=released) |
215 | x Unused. | 215 | x Unused. |
216 | NNNN switch number 0-15 | 216 | NNNN switch number 0-15 |
217 | 217 | ||
218 | Note: This is true for non interrupt generated key events. | 218 | Note: This is true for non interrupt generated key events. |
219 | */ | 219 | */ |
220 | case KEYBD_ID: | 220 | case KEYBD_ID: |
221 | down = (ts->buf[0] & 0x80) ? 0 : 1; | 221 | down = (ts->buf[0] & 0x80) ? 0 : 1; |
222 | 222 | ||
223 | switch (ts->buf[0] & 0x7f) { | 223 | switch (ts->buf[0] & 0x7f) { |
@@ -229,40 +229,40 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | |||
229 | break; | 229 | break; |
230 | case H3600_SCANCODE_CONTACTS: | 230 | case H3600_SCANCODE_CONTACTS: |
231 | key = KEY_PROG2; | 231 | key = KEY_PROG2; |
232 | break; | 232 | break; |
233 | case H3600_SCANCODE_Q: | 233 | case H3600_SCANCODE_Q: |
234 | key = KEY_Q; | 234 | key = KEY_Q; |
235 | break; | 235 | break; |
236 | case H3600_SCANCODE_START: | 236 | case H3600_SCANCODE_START: |
237 | key = KEY_PROG3; | 237 | key = KEY_PROG3; |
238 | break; | 238 | break; |
239 | case H3600_SCANCODE_UP: | 239 | case H3600_SCANCODE_UP: |
240 | key = KEY_UP; | 240 | key = KEY_UP; |
241 | break; | 241 | break; |
242 | case H3600_SCANCODE_RIGHT: | 242 | case H3600_SCANCODE_RIGHT: |
243 | key = KEY_RIGHT; | 243 | key = KEY_RIGHT; |
244 | break; | 244 | break; |
245 | case H3600_SCANCODE_LEFT: | 245 | case H3600_SCANCODE_LEFT: |
246 | key = KEY_LEFT; | 246 | key = KEY_LEFT; |
247 | break; | 247 | break; |
248 | case H3600_SCANCODE_DOWN: | 248 | case H3600_SCANCODE_DOWN: |
249 | key = KEY_DOWN; | 249 | key = KEY_DOWN; |
250 | break; | 250 | break; |
251 | default: | 251 | default: |
252 | key = 0; | 252 | key = 0; |
253 | } | 253 | } |
254 | if (key) | 254 | if (key) |
255 | input_report_key(dev, key, down); | 255 | input_report_key(dev, key, down); |
256 | break; | 256 | break; |
257 | /* | 257 | /* |
258 | * Native touchscreen event data is formatted as shown below:- | 258 | * Native touchscreen event data is formatted as shown below:- |
259 | * | 259 | * |
260 | * +-------+-------+-------+-------+ | 260 | * +-------+-------+-------+-------+ |
261 | * | Xmsb | Xlsb | Ymsb | Ylsb | | 261 | * | Xmsb | Xlsb | Ymsb | Ylsb | |
262 | * +-------+-------+-------+-------+ | 262 | * +-------+-------+-------+-------+ |
263 | * byte 0 1 2 3 | 263 | * byte 0 1 2 3 |
264 | */ | 264 | */ |
265 | case TOUCHS_ID: | 265 | case TOUCHS_ID: |
266 | if (!touched) { | 266 | if (!touched) { |
267 | input_report_key(dev, BTN_TOUCH, 1); | 267 | input_report_key(dev, BTN_TOUCH, 1); |
268 | touched = 1; | 268 | touched = 1; |
@@ -272,19 +272,19 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | |||
272 | unsigned short x, y; | 272 | unsigned short x, y; |
273 | 273 | ||
274 | x = ts->buf[0]; x <<= 8; x += ts->buf[1]; | 274 | x = ts->buf[0]; x <<= 8; x += ts->buf[1]; |
275 | y = ts->buf[2]; y <<= 8; y += ts->buf[3]; | 275 | y = ts->buf[2]; y <<= 8; y += ts->buf[3]; |
276 | 276 | ||
277 | input_report_abs(dev, ABS_X, x); | 277 | input_report_abs(dev, ABS_X, x); |
278 | input_report_abs(dev, ABS_Y, y); | 278 | input_report_abs(dev, ABS_Y, y); |
279 | } else { | 279 | } else { |
280 | input_report_key(dev, BTN_TOUCH, 0); | 280 | input_report_key(dev, BTN_TOUCH, 0); |
281 | touched = 0; | 281 | touched = 0; |
282 | } | 282 | } |
283 | break; | 283 | break; |
284 | default: | 284 | default: |
285 | /* Send a non input event elsewhere */ | 285 | /* Send a non input event elsewhere */ |
286 | break; | 286 | break; |
287 | } | 287 | } |
288 | 288 | ||
289 | input_sync(dev); | 289 | input_sync(dev); |
290 | } | 290 | } |
@@ -293,7 +293,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | |||
293 | * h3600ts_event() handles events from the input module. | 293 | * h3600ts_event() handles events from the input module. |
294 | */ | 294 | */ |
295 | static int h3600ts_event(struct input_dev *dev, unsigned int type, | 295 | static int h3600ts_event(struct input_dev *dev, unsigned int type, |
296 | unsigned int code, int value) | 296 | unsigned int code, int value) |
297 | { | 297 | { |
298 | struct h3600_dev *ts = dev->private; | 298 | struct h3600_dev *ts = dev->private; |
299 | 299 | ||
@@ -332,41 +332,41 @@ static int state; | |||
332 | static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, | 332 | static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, |
333 | unsigned int flags, struct pt_regs *regs) | 333 | unsigned int flags, struct pt_regs *regs) |
334 | { | 334 | { |
335 | struct h3600_dev *ts = serio_get_drvdata(serio); | 335 | struct h3600_dev *ts = serio_get_drvdata(serio); |
336 | 336 | ||
337 | /* | 337 | /* |
338 | * We have a new frame coming in. | 338 | * We have a new frame coming in. |
339 | */ | 339 | */ |
340 | switch (state) { | 340 | switch (state) { |
341 | case STATE_SOF: | 341 | case STATE_SOF: |
342 | if (data == CHAR_SOF) | 342 | if (data == CHAR_SOF) |
343 | state = STATE_ID; | 343 | state = STATE_ID; |
344 | break; | 344 | break; |
345 | case STATE_ID: | 345 | case STATE_ID: |
346 | ts->event = (data & 0xf0) >> 4; | 346 | ts->event = (data & 0xf0) >> 4; |
347 | ts->len = (data & 0xf); | 347 | ts->len = (data & 0xf); |
348 | ts->idx = 0; | 348 | ts->idx = 0; |
349 | if (ts->event >= MAX_ID) { | 349 | if (ts->event >= MAX_ID) { |
350 | state = STATE_SOF; | 350 | state = STATE_SOF; |
351 | break; | 351 | break; |
352 | } | 352 | } |
353 | ts->chksum = data; | 353 | ts->chksum = data; |
354 | state = (ts->len > 0) ? STATE_DATA : STATE_EOF; | 354 | state = (ts->len > 0) ? STATE_DATA : STATE_EOF; |
355 | break; | 355 | break; |
356 | case STATE_DATA: | 356 | case STATE_DATA: |
357 | ts->chksum += data; | 357 | ts->chksum += data; |
358 | ts->buf[ts->idx]= data; | 358 | ts->buf[ts->idx]= data; |
359 | if(++ts->idx == ts->len) | 359 | if (++ts->idx == ts->len) |
360 | state = STATE_EOF; | 360 | state = STATE_EOF; |
361 | break; | 361 | break; |
362 | case STATE_EOF: | 362 | case STATE_EOF: |
363 | state = STATE_SOF; | 363 | state = STATE_SOF; |
364 | if (data == CHAR_EOF || data == ts->chksum) | 364 | if (data == CHAR_EOF || data == ts->chksum) |
365 | h3600ts_process_packet(ts, regs); | 365 | h3600ts_process_packet(ts, regs); |
366 | break; | 366 | break; |
367 | default: | 367 | default: |
368 | printk("Error3\n"); | 368 | printk("Error3\n"); |
369 | break; | 369 | break; |
370 | } | 370 | } |
371 | 371 | ||
372 | return IRQ_HANDLED; | 372 | return IRQ_HANDLED; |
@@ -390,10 +390,10 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
390 | init_input_dev(&ts->dev); | 390 | init_input_dev(&ts->dev); |
391 | 391 | ||
392 | /* Device specific stuff */ | 392 | /* Device specific stuff */ |
393 | set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); | 393 | set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); |
394 | set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); | 394 | set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); |
395 | 395 | ||
396 | if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, | 396 | if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, |
397 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, | 397 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, |
398 | "h3600_action", &ts->dev)) { | 398 | "h3600_action", &ts->dev)) { |
399 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); | 399 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); |
@@ -401,7 +401,7 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
401 | return -EBUSY; | 401 | return -EBUSY; |
402 | } | 402 | } |
403 | 403 | ||
404 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, | 404 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, |
405 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, | 405 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, |
406 | "h3600_suspend", &ts->dev)) { | 406 | "h3600_suspend", &ts->dev)) { |
407 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); | 407 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); |
@@ -433,7 +433,7 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
433 | 433 | ||
434 | sprintf(ts->phys, "%s/input0", serio->phys); | 434 | sprintf(ts->phys, "%s/input0", serio->phys); |
435 | 435 | ||
436 | ts->dev.event = h3600ts_event; | 436 | ts->dev.event = h3600ts_event; |
437 | ts->dev.private = ts; | 437 | ts->dev.private = ts; |
438 | ts->dev.name = h3600_name; | 438 | ts->dev.name = h3600_name; |
439 | ts->dev.phys = ts->phys; | 439 | ts->dev.phys = ts->phys; |
@@ -446,8 +446,8 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
446 | 446 | ||
447 | err = serio_open(serio, drv); | 447 | err = serio_open(serio, drv); |
448 | if (err) { | 448 | if (err) { |
449 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts); | 449 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts); |
450 | free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts); | 450 | free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts); |
451 | serio_set_drvdata(serio, NULL); | 451 | serio_set_drvdata(serio, NULL); |
452 | kfree(ts); | 452 | kfree(ts); |
453 | return err; | 453 | return err; |
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c index 2d14a57a05e5..afaaebe5225b 100644 --- a/drivers/input/touchscreen/mk712.c +++ b/drivers/input/touchscreen/mk712.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * found in Gateway AOL Connected Touchpad computers. | 17 | * found in Gateway AOL Connected Touchpad computers. |
18 | * | 18 | * |
19 | * Documentation for ICS MK712 can be found at: | 19 | * Documentation for ICS MK712 can be found at: |
20 | * http://www.icst.com/pdf/mk712.pdf | 20 | * http://www.icst.com/pdf/mk712.pdf |
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* | 23 | /* |
@@ -77,7 +77,6 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller"); | |||
77 | #define MK712_READ_ONE_POINT 0x20 | 77 | #define MK712_READ_ONE_POINT 0x20 |
78 | #define MK712_POWERUP 0x40 | 78 | #define MK712_POWERUP 0x40 |
79 | 79 | ||
80 | static int mk712_used = 0; | ||
81 | static struct input_dev mk712_dev; | 80 | static struct input_dev mk712_dev; |
82 | static DEFINE_SPINLOCK(mk712_lock); | 81 | static DEFINE_SPINLOCK(mk712_lock); |
83 | 82 | ||
@@ -130,17 +129,14 @@ static int mk712_open(struct input_dev *dev) | |||
130 | 129 | ||
131 | spin_lock_irqsave(&mk712_lock, flags); | 130 | spin_lock_irqsave(&mk712_lock, flags); |
132 | 131 | ||
133 | if (!mk712_used++) { | 132 | outb(0, mk712_io + MK712_CONTROL); /* Reset */ |
134 | 133 | ||
135 | outb(0, mk712_io + MK712_CONTROL); /* Reset */ | 134 | outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | |
135 | MK712_INT_ON_CHANGE_IN_TOUCH_STATUS | | ||
136 | MK712_ENABLE_PERIODIC_CONVERSIONS | | ||
137 | MK712_POWERUP, mk712_io + MK712_CONTROL); | ||
136 | 138 | ||
137 | outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | | 139 | outb(10, mk712_io + MK712_RATE); /* 187 points per second */ |
138 | MK712_INT_ON_CHANGE_IN_TOUCH_STATUS | | ||
139 | MK712_ENABLE_PERIODIC_CONVERSIONS | | ||
140 | MK712_POWERUP, mk712_io + MK712_CONTROL); | ||
141 | |||
142 | outb(10, mk712_io + MK712_RATE); /* 187 points per second */ | ||
143 | } | ||
144 | 140 | ||
145 | spin_unlock_irqrestore(&mk712_lock, flags); | 141 | spin_unlock_irqrestore(&mk712_lock, flags); |
146 | 142 | ||
@@ -153,8 +149,7 @@ static void mk712_close(struct input_dev *dev) | |||
153 | 149 | ||
154 | spin_lock_irqsave(&mk712_lock, flags); | 150 | spin_lock_irqsave(&mk712_lock, flags); |
155 | 151 | ||
156 | if (!--mk712_used) | 152 | outb(0, mk712_io + MK712_CONTROL); |
157 | outb(0, mk712_io + MK712_CONTROL); | ||
158 | 153 | ||
159 | spin_unlock_irqrestore(&mk712_lock, flags); | 154 | spin_unlock_irqrestore(&mk712_lock, flags); |
160 | } | 155 | } |
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 8a7117a08cf0..91691a6c004e 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
@@ -86,33 +86,18 @@ config PMAC_SMU | |||
86 | on the "SMU" system control chip which replaces the old PMU. | 86 | on the "SMU" system control chip which replaces the old PMU. |
87 | If you don't know, say Y. | 87 | If you don't know, say Y. |
88 | 88 | ||
89 | config PMAC_PBOOK | ||
90 | bool "Power management support for PowerBooks" | ||
91 | depends on ADB_PMU | ||
92 | ---help--- | ||
93 | This provides support for putting a PowerBook to sleep; it also | ||
94 | enables media bay support. Power management works on the | ||
95 | PB2400/3400/3500, Wallstreet, Lombard, and Bronze PowerBook G3 and | ||
96 | the Titanium Powerbook G4, as well as the iBooks. You should get | ||
97 | the power management daemon, pmud, to make it work and you must have | ||
98 | the /dev/pmu device (see the pmud README). | ||
99 | |||
100 | Get pmud from <ftp://ftp.samba.org/pub/ppclinux/pmud/>. | ||
101 | |||
102 | If you have a PowerBook, you should say Y here. | ||
103 | |||
104 | You may also want to compile the dma sound driver as a module and | ||
105 | have it autoloaded. The act of removing the module shuts down the | ||
106 | sound hardware for more power savings. | ||
107 | |||
108 | config PM | ||
109 | bool | ||
110 | depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK | ||
111 | default y | ||
112 | |||
113 | config PMAC_APM_EMU | 89 | config PMAC_APM_EMU |
114 | tristate "APM emulation" | 90 | tristate "APM emulation" |
115 | depends on PMAC_PBOOK | 91 | depends on PPC_PMAC && PPC32 && PM |
92 | |||
93 | config PMAC_MEDIABAY | ||
94 | bool "Support PowerBook hotswap media bay" | ||
95 | depends on PPC_PMAC && PPC32 | ||
96 | help | ||
97 | This option adds support for older PowerBook's hotswap media bay | ||
98 | that can contains batteries, floppy drives, or IDE devices. PCI | ||
99 | devices are not fully supported in the bay as I never had one to | ||
100 | try with | ||
116 | 101 | ||
117 | # made a separate option since backlight may end up beeing used | 102 | # made a separate option since backlight may end up beeing used |
118 | # on non-powerbook machines (but only on PMU based ones AFAIK) | 103 | # on non-powerbook machines (but only on PMU based ones AFAIK) |
@@ -126,13 +111,6 @@ config PMAC_BACKLIGHT | |||
126 | events; also, the PowerBook button device will be enabled so you can | 111 | events; also, the PowerBook button device will be enabled so you can |
127 | change the screen brightness. | 112 | change the screen brightness. |
128 | 113 | ||
129 | config MAC_SERIAL | ||
130 | tristate "Support for PowerMac serial ports (OBSOLETE DRIVER)" | ||
131 | depends on PPC_PMAC && BROKEN | ||
132 | help | ||
133 | This driver is obsolete. Use CONFIG_SERIAL_PMACZILOG in | ||
134 | "Character devices --> Serial drivers --> PowerMac z85c30" option. | ||
135 | |||
136 | config ADB_MACIO | 114 | config ADB_MACIO |
137 | bool "Include MacIO (CHRP) ADB driver" | 115 | bool "Include MacIO (CHRP) ADB driver" |
138 | depends on ADB && PPC_CHRP && !PPC_PMAC64 | 116 | depends on ADB && PPC_CHRP && !PPC_PMAC64 |
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index c3a4705a8295..f5ae171dbfef 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile | |||
@@ -6,8 +6,7 @@ | |||
6 | 6 | ||
7 | obj-$(CONFIG_PPC_PMAC) += macio_asic.o | 7 | obj-$(CONFIG_PPC_PMAC) += macio_asic.o |
8 | 8 | ||
9 | obj-$(CONFIG_PMAC_PBOOK) += mediabay.o | 9 | obj-$(CONFIG_PMAC_MEDIABAY) += mediabay.o |
10 | obj-$(CONFIG_MAC_SERIAL) += macserial.o | ||
11 | obj-$(CONFIG_MAC_EMUMOUSEBTN) += mac_hid.o | 10 | obj-$(CONFIG_MAC_EMUMOUSEBTN) += mac_hid.o |
12 | obj-$(CONFIG_INPUT_ADBHID) += adbhid.o | 11 | obj-$(CONFIG_INPUT_ADBHID) += adbhid.o |
13 | obj-$(CONFIG_ANSLCD) += ans-lcd.o | 12 | obj-$(CONFIG_ANSLCD) += ans-lcd.o |
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index 493e2afa191c..c0dc1e3fa58b 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c | |||
@@ -90,7 +90,7 @@ static int sleepy_trackpad; | |||
90 | static int autopoll_devs; | 90 | static int autopoll_devs; |
91 | int __adb_probe_sync; | 91 | int __adb_probe_sync; |
92 | 92 | ||
93 | #ifdef CONFIG_PMAC_PBOOK | 93 | #ifdef CONFIG_PM |
94 | static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when); | 94 | static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when); |
95 | static struct pmu_sleep_notifier adb_sleep_notifier = { | 95 | static struct pmu_sleep_notifier adb_sleep_notifier = { |
96 | adb_notify_sleep, | 96 | adb_notify_sleep, |
@@ -320,9 +320,9 @@ int __init adb_init(void) | |||
320 | printk(KERN_WARNING "Warning: no ADB interface detected\n"); | 320 | printk(KERN_WARNING "Warning: no ADB interface detected\n"); |
321 | adb_controller = NULL; | 321 | adb_controller = NULL; |
322 | } else { | 322 | } else { |
323 | #ifdef CONFIG_PMAC_PBOOK | 323 | #ifdef CONFIG_PM |
324 | pmu_register_sleep_notifier(&adb_sleep_notifier); | 324 | pmu_register_sleep_notifier(&adb_sleep_notifier); |
325 | #endif /* CONFIG_PMAC_PBOOK */ | 325 | #endif /* CONFIG_PM */ |
326 | #ifdef CONFIG_PPC | 326 | #ifdef CONFIG_PPC |
327 | if (machine_is_compatible("AAPL,PowerBook1998") || | 327 | if (machine_is_compatible("AAPL,PowerBook1998") || |
328 | machine_is_compatible("PowerBook1,1")) | 328 | machine_is_compatible("PowerBook1,1")) |
@@ -337,7 +337,7 @@ int __init adb_init(void) | |||
337 | 337 | ||
338 | __initcall(adb_init); | 338 | __initcall(adb_init); |
339 | 339 | ||
340 | #ifdef CONFIG_PMAC_PBOOK | 340 | #ifdef CONFIG_PM |
341 | /* | 341 | /* |
342 | * notify clients before sleep and reset bus afterwards | 342 | * notify clients before sleep and reset bus afterwards |
343 | */ | 343 | */ |
@@ -378,7 +378,7 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when) | |||
378 | } | 378 | } |
379 | return PBOOK_SLEEP_OK; | 379 | return PBOOK_SLEEP_OK; |
380 | } | 380 | } |
381 | #endif /* CONFIG_PMAC_PBOOK */ | 381 | #endif /* CONFIG_PM */ |
382 | 382 | ||
383 | static int | 383 | static int |
384 | do_adb_reset_bus(void) | 384 | do_adb_reset_bus(void) |
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c deleted file mode 100644 index 0be3ac6cc169..000000000000 --- a/drivers/macintosh/macserial.c +++ /dev/null | |||
@@ -1,3036 +0,0 @@ | |||
1 | /* | ||
2 | * macserial.c: Serial port driver for Power Macintoshes. | ||
3 | * | ||
4 | * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. | ||
5 | * | ||
6 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) | ||
7 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
8 | * | ||
9 | * Receive DMA code by Takashi Oe <toe@unlserve.unl.edu>. | ||
10 | * | ||
11 | * $Id: macserial.c,v 1.24.2.4 1999/10/19 04:36:42 paulus Exp $ | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/signal.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <linux/tty.h> | ||
23 | #include <linux/tty_flip.h> | ||
24 | #include <linux/major.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/fcntl.h> | ||
27 | #include <linux/mm.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/init.h> | ||
31 | #ifdef CONFIG_SERIAL_CONSOLE | ||
32 | #include <linux/console.h> | ||
33 | #endif | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/bitops.h> | ||
36 | |||
37 | #include <asm/sections.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <asm/pgtable.h> | ||
40 | #include <asm/irq.h> | ||
41 | #include <asm/prom.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/segment.h> | ||
44 | #include <asm/machdep.h> | ||
45 | #include <asm/pmac_feature.h> | ||
46 | #include <linux/adb.h> | ||
47 | #include <linux/pmu.h> | ||
48 | #ifdef CONFIG_KGDB | ||
49 | #include <asm/kgdb.h> | ||
50 | #endif | ||
51 | #include <asm/dbdma.h> | ||
52 | |||
53 | #include "macserial.h" | ||
54 | |||
55 | #ifdef CONFIG_PMAC_PBOOK | ||
56 | static int serial_notify_sleep(struct pmu_sleep_notifier *self, int when); | ||
57 | static struct pmu_sleep_notifier serial_sleep_notifier = { | ||
58 | serial_notify_sleep, | ||
59 | SLEEP_LEVEL_MISC, | ||
60 | }; | ||
61 | #endif | ||
62 | |||
63 | #define SUPPORT_SERIAL_DMA | ||
64 | #define MACSERIAL_VERSION "2.0" | ||
65 | |||
66 | /* | ||
67 | * It would be nice to dynamically allocate everything that | ||
68 | * depends on NUM_SERIAL, so we could support any number of | ||
69 | * Z8530s, but for now... | ||
70 | */ | ||
71 | #define NUM_SERIAL 2 /* Max number of ZS chips supported */ | ||
72 | #define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ | ||
73 | |||
74 | /* On PowerMacs, the hardware takes care of the SCC recovery time, | ||
75 | but we need the eieio to make sure that the accesses occur | ||
76 | in the order we want. */ | ||
77 | #define RECOVERY_DELAY eieio() | ||
78 | |||
79 | static struct tty_driver *serial_driver; | ||
80 | |||
81 | struct mac_zschannel zs_channels[NUM_CHANNELS]; | ||
82 | |||
83 | struct mac_serial zs_soft[NUM_CHANNELS]; | ||
84 | int zs_channels_found; | ||
85 | struct mac_serial *zs_chain; /* list of all channels */ | ||
86 | |||
87 | struct tty_struct zs_ttys[NUM_CHANNELS]; | ||
88 | |||
89 | static int is_powerbook; | ||
90 | |||
91 | #ifdef CONFIG_SERIAL_CONSOLE | ||
92 | static struct console sercons; | ||
93 | #endif | ||
94 | |||
95 | #ifdef CONFIG_KGDB | ||
96 | struct mac_zschannel *zs_kgdbchan; | ||
97 | static unsigned char scc_inittab[] = { | ||
98 | 9, 0x80, /* reset A side (CHRA) */ | ||
99 | 13, 0, /* set baud rate divisor */ | ||
100 | 12, 1, | ||
101 | 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */ | ||
102 | 11, 0x50, /* clocks = br gen (RCBR | TCBR) */ | ||
103 | 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */ | ||
104 | 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/ | ||
105 | 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/ | ||
106 | }; | ||
107 | #endif | ||
108 | #define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */ | ||
109 | |||
110 | /* serial subtype definitions */ | ||
111 | #define SERIAL_TYPE_NORMAL 1 | ||
112 | |||
113 | /* number of characters left in xmit buffer before we ask for more */ | ||
114 | #define WAKEUP_CHARS 256 | ||
115 | |||
116 | /* | ||
117 | * Debugging. | ||
118 | */ | ||
119 | #undef SERIAL_DEBUG_INTR | ||
120 | #undef SERIAL_DEBUG_OPEN | ||
121 | #undef SERIAL_DEBUG_FLOW | ||
122 | #undef SERIAL_DEBUG_POWER | ||
123 | #undef SERIAL_DEBUG_THROTTLE | ||
124 | #undef SERIAL_DEBUG_STOP | ||
125 | #undef SERIAL_DEBUG_BAUDS | ||
126 | |||
127 | #define RS_STROBE_TIME 10 | ||
128 | #define RS_ISR_PASS_LIMIT 256 | ||
129 | |||
130 | #define _INLINE_ inline | ||
131 | |||
132 | #ifdef SERIAL_DEBUG_OPEN | ||
133 | #define OPNDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg) | ||
134 | #else | ||
135 | #define OPNDBG(fmt, arg...) do { } while (0) | ||
136 | #endif | ||
137 | #ifdef SERIAL_DEBUG_POWER | ||
138 | #define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg) | ||
139 | #else | ||
140 | #define PWRDBG(fmt, arg...) do { } while (0) | ||
141 | #endif | ||
142 | #ifdef SERIAL_DEBUG_BAUDS | ||
143 | #define BAUDBG(fmt, arg...) printk(fmt , ## arg) | ||
144 | #else | ||
145 | #define BAUDBG(fmt, arg...) do { } while (0) | ||
146 | #endif | ||
147 | |||
148 | static void probe_sccs(void); | ||
149 | static void change_speed(struct mac_serial *info, struct termios *old); | ||
150 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout); | ||
151 | static int set_scc_power(struct mac_serial * info, int state); | ||
152 | static int setup_scc(struct mac_serial * info); | ||
153 | static void dbdma_reset(volatile struct dbdma_regs *dma); | ||
154 | static void dbdma_flush(volatile struct dbdma_regs *dma); | ||
155 | static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs); | ||
156 | static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs); | ||
157 | static void dma_init(struct mac_serial * info); | ||
158 | static void rxdma_start(struct mac_serial * info, int curr); | ||
159 | static void rxdma_to_tty(struct mac_serial * info); | ||
160 | |||
161 | /* | ||
162 | * tmp_buf is used as a temporary buffer by serial_write. We need to | ||
163 | * lock it in case the copy_from_user blocks while swapping in a page, | ||
164 | * and some other program tries to do a serial write at the same time. | ||
165 | * Since the lock will only come under contention when the system is | ||
166 | * swapping and available memory is low, it makes sense to share one | ||
167 | * buffer across all the serial ports, since it significantly saves | ||
168 | * memory if large numbers of serial ports are open. | ||
169 | */ | ||
170 | static unsigned char *tmp_buf; | ||
171 | static DECLARE_MUTEX(tmp_buf_sem); | ||
172 | |||
173 | |||
174 | static inline int __pmac | ||
175 | serial_paranoia_check(struct mac_serial *info, | ||
176 | char *name, const char *routine) | ||
177 | { | ||
178 | #ifdef SERIAL_PARANOIA_CHECK | ||
179 | static const char badmagic[] = KERN_WARNING | ||
180 | "Warning: bad magic number for serial struct %s in %s\n"; | ||
181 | static const char badinfo[] = KERN_WARNING | ||
182 | "Warning: null mac_serial for %s in %s\n"; | ||
183 | |||
184 | if (!info) { | ||
185 | printk(badinfo, name, routine); | ||
186 | return 1; | ||
187 | } | ||
188 | if (info->magic != SERIAL_MAGIC) { | ||
189 | printk(badmagic, name, routine); | ||
190 | return 1; | ||
191 | } | ||
192 | #endif | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * Reading and writing Z8530 registers. | ||
198 | */ | ||
199 | static inline unsigned char __pmac read_zsreg(struct mac_zschannel *channel, | ||
200 | unsigned char reg) | ||
201 | { | ||
202 | unsigned char retval; | ||
203 | unsigned long flags; | ||
204 | |||
205 | /* | ||
206 | * We have to make this atomic. | ||
207 | */ | ||
208 | spin_lock_irqsave(&channel->lock, flags); | ||
209 | if (reg != 0) { | ||
210 | *channel->control = reg; | ||
211 | RECOVERY_DELAY; | ||
212 | } | ||
213 | retval = *channel->control; | ||
214 | RECOVERY_DELAY; | ||
215 | spin_unlock_irqrestore(&channel->lock, flags); | ||
216 | return retval; | ||
217 | } | ||
218 | |||
219 | static inline void __pmac write_zsreg(struct mac_zschannel *channel, | ||
220 | unsigned char reg, unsigned char value) | ||
221 | { | ||
222 | unsigned long flags; | ||
223 | |||
224 | spin_lock_irqsave(&channel->lock, flags); | ||
225 | if (reg != 0) { | ||
226 | *channel->control = reg; | ||
227 | RECOVERY_DELAY; | ||
228 | } | ||
229 | *channel->control = value; | ||
230 | RECOVERY_DELAY; | ||
231 | spin_unlock_irqrestore(&channel->lock, flags); | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | static inline unsigned char __pmac read_zsdata(struct mac_zschannel *channel) | ||
236 | { | ||
237 | unsigned char retval; | ||
238 | |||
239 | retval = *channel->data; | ||
240 | RECOVERY_DELAY; | ||
241 | return retval; | ||
242 | } | ||
243 | |||
244 | static inline void write_zsdata(struct mac_zschannel *channel, | ||
245 | unsigned char value) | ||
246 | { | ||
247 | *channel->data = value; | ||
248 | RECOVERY_DELAY; | ||
249 | return; | ||
250 | } | ||
251 | |||
252 | static inline void load_zsregs(struct mac_zschannel *channel, | ||
253 | unsigned char *regs) | ||
254 | { | ||
255 | ZS_CLEARERR(channel); | ||
256 | ZS_CLEARFIFO(channel); | ||
257 | /* Load 'em up */ | ||
258 | write_zsreg(channel, R4, regs[R4]); | ||
259 | write_zsreg(channel, R10, regs[R10]); | ||
260 | write_zsreg(channel, R3, regs[R3] & ~RxENABLE); | ||
261 | write_zsreg(channel, R5, regs[R5] & ~TxENAB); | ||
262 | write_zsreg(channel, R1, regs[R1]); | ||
263 | write_zsreg(channel, R9, regs[R9]); | ||
264 | write_zsreg(channel, R11, regs[R11]); | ||
265 | write_zsreg(channel, R12, regs[R12]); | ||
266 | write_zsreg(channel, R13, regs[R13]); | ||
267 | write_zsreg(channel, R14, regs[R14]); | ||
268 | write_zsreg(channel, R15, regs[R15]); | ||
269 | write_zsreg(channel, R3, regs[R3]); | ||
270 | write_zsreg(channel, R5, regs[R5]); | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | /* Sets or clears DTR/RTS on the requested line */ | ||
275 | static inline void zs_rtsdtr(struct mac_serial *ss, int set) | ||
276 | { | ||
277 | if (set) | ||
278 | ss->curregs[5] |= (RTS | DTR); | ||
279 | else | ||
280 | ss->curregs[5] &= ~(RTS | DTR); | ||
281 | write_zsreg(ss->zs_channel, 5, ss->curregs[5]); | ||
282 | return; | ||
283 | } | ||
284 | |||
285 | /* Utility routines for the Zilog */ | ||
286 | static inline int get_zsbaud(struct mac_serial *ss) | ||
287 | { | ||
288 | struct mac_zschannel *channel = ss->zs_channel; | ||
289 | int brg; | ||
290 | |||
291 | if ((ss->curregs[R11] & TCBR) == 0) { | ||
292 | /* higher rates don't use the baud rate generator */ | ||
293 | return (ss->curregs[R4] & X32CLK)? ZS_CLOCK/32: ZS_CLOCK/16; | ||
294 | } | ||
295 | /* The baud rate is split up between two 8-bit registers in | ||
296 | * what is termed 'BRG time constant' format in my docs for | ||
297 | * the chip, it is a function of the clk rate the chip is | ||
298 | * receiving which happens to be constant. | ||
299 | */ | ||
300 | brg = (read_zsreg(channel, 13) << 8); | ||
301 | brg |= read_zsreg(channel, 12); | ||
302 | return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor))); | ||
303 | } | ||
304 | |||
305 | /* On receive, this clears errors and the receiver interrupts */ | ||
306 | static inline void rs_recv_clear(struct mac_zschannel *zsc) | ||
307 | { | ||
308 | write_zsreg(zsc, 0, ERR_RES); | ||
309 | write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */ | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * Reset a Descriptor-Based DMA channel. | ||
314 | */ | ||
315 | static void dbdma_reset(volatile struct dbdma_regs *dma) | ||
316 | { | ||
317 | int i; | ||
318 | |||
319 | out_le32(&dma->control, (WAKE|FLUSH|PAUSE|RUN) << 16); | ||
320 | |||
321 | /* | ||
322 | * Yes this looks peculiar, but apparently it needs to be this | ||
323 | * way on some machines. (We need to make sure the DBDMA | ||
324 | * engine has actually got the write above and responded | ||
325 | * to it. - paulus) | ||
326 | */ | ||
327 | for (i = 200; i > 0; --i) | ||
328 | if (ld_le32(&dma->status) & RUN) | ||
329 | udelay(1); | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | * Tells a DBDMA channel to stop and write any buffered data | ||
334 | * it might have to memory. | ||
335 | */ | ||
336 | static _INLINE_ void dbdma_flush(volatile struct dbdma_regs *dma) | ||
337 | { | ||
338 | int i = 0; | ||
339 | |||
340 | out_le32(&dma->control, (FLUSH << 16) | FLUSH); | ||
341 | while (((in_le32(&dma->status) & FLUSH) != 0) && (i++ < 100)) | ||
342 | udelay(1); | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * ---------------------------------------------------------------------- | ||
347 | * | ||
348 | * Here starts the interrupt handling routines. All of the following | ||
349 | * subroutines are declared as inline and are folded into | ||
350 | * rs_interrupt(). They were separated out for readability's sake. | ||
351 | * | ||
352 | * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 | ||
353 | * ----------------------------------------------------------------------- | ||
354 | */ | ||
355 | |||
356 | /* | ||
357 | * This routine is used by the interrupt handler to schedule | ||
358 | * processing in the software interrupt portion of the driver. | ||
359 | */ | ||
360 | static _INLINE_ void rs_sched_event(struct mac_serial *info, | ||
361 | int event) | ||
362 | { | ||
363 | info->event |= 1 << event; | ||
364 | schedule_work(&info->tqueue); | ||
365 | } | ||
366 | |||
367 | /* Work out the flag value for a z8530 status value. */ | ||
368 | static _INLINE_ int stat_to_flag(int stat) | ||
369 | { | ||
370 | int flag; | ||
371 | |||
372 | if (stat & Rx_OVR) { | ||
373 | flag = TTY_OVERRUN; | ||
374 | } else if (stat & FRM_ERR) { | ||
375 | flag = TTY_FRAME; | ||
376 | } else if (stat & PAR_ERR) { | ||
377 | flag = TTY_PARITY; | ||
378 | } else | ||
379 | flag = 0; | ||
380 | return flag; | ||
381 | } | ||
382 | |||
383 | static _INLINE_ void receive_chars(struct mac_serial *info, | ||
384 | struct pt_regs *regs) | ||
385 | { | ||
386 | struct tty_struct *tty = info->tty; | ||
387 | unsigned char ch, stat, flag; | ||
388 | |||
389 | while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) { | ||
390 | |||
391 | stat = read_zsreg(info->zs_channel, R1); | ||
392 | ch = read_zsdata(info->zs_channel); | ||
393 | |||
394 | #ifdef CONFIG_KGDB | ||
395 | if (info->kgdb_channel) { | ||
396 | if (ch == 0x03 || ch == '$') | ||
397 | breakpoint(); | ||
398 | if (stat & (Rx_OVR|FRM_ERR|PAR_ERR)) | ||
399 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
400 | return; | ||
401 | } | ||
402 | #endif | ||
403 | if (!tty) | ||
404 | continue; | ||
405 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) | ||
406 | tty_flip_buffer_push(tty); | ||
407 | |||
408 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
409 | static int flip_buf_ovf; | ||
410 | if (++flip_buf_ovf <= 1) | ||
411 | printk(KERN_WARNING "FB. overflow: %d\n", | ||
412 | flip_buf_ovf); | ||
413 | break; | ||
414 | } | ||
415 | tty->flip.count++; | ||
416 | { | ||
417 | static int flip_max_cnt; | ||
418 | if (flip_max_cnt < tty->flip.count) | ||
419 | flip_max_cnt = tty->flip.count; | ||
420 | } | ||
421 | flag = stat_to_flag(stat); | ||
422 | if (flag) | ||
423 | /* reset the error indication */ | ||
424 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
425 | *tty->flip.flag_buf_ptr++ = flag; | ||
426 | *tty->flip.char_buf_ptr++ = ch; | ||
427 | } | ||
428 | if (tty) | ||
429 | tty_flip_buffer_push(tty); | ||
430 | } | ||
431 | |||
432 | static void transmit_chars(struct mac_serial *info) | ||
433 | { | ||
434 | if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) | ||
435 | return; | ||
436 | info->tx_active = 0; | ||
437 | |||
438 | if (info->x_char && !info->power_wait) { | ||
439 | /* Send next char */ | ||
440 | write_zsdata(info->zs_channel, info->x_char); | ||
441 | info->x_char = 0; | ||
442 | info->tx_active = 1; | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped | ||
447 | || info->power_wait) { | ||
448 | write_zsreg(info->zs_channel, 0, RES_Tx_P); | ||
449 | return; | ||
450 | } | ||
451 | |||
452 | /* Send char */ | ||
453 | write_zsdata(info->zs_channel, info->xmit_buf[info->xmit_tail++]); | ||
454 | info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); | ||
455 | info->xmit_cnt--; | ||
456 | info->tx_active = 1; | ||
457 | |||
458 | if (info->xmit_cnt < WAKEUP_CHARS) | ||
459 | rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); | ||
460 | } | ||
461 | |||
462 | static void powerup_done(unsigned long data) | ||
463 | { | ||
464 | struct mac_serial *info = (struct mac_serial *) data; | ||
465 | unsigned long flags; | ||
466 | |||
467 | spin_lock_irqsave(&info->lock, flags); | ||
468 | info->power_wait = 0; | ||
469 | transmit_chars(info); | ||
470 | spin_unlock_irqrestore(&info->lock, flags); | ||
471 | } | ||
472 | |||
473 | static _INLINE_ void status_handle(struct mac_serial *info) | ||
474 | { | ||
475 | unsigned char status; | ||
476 | |||
477 | /* Get status from Read Register 0 */ | ||
478 | status = read_zsreg(info->zs_channel, 0); | ||
479 | |||
480 | /* Check for DCD transitions */ | ||
481 | if (((status ^ info->read_reg_zero) & DCD) != 0 | ||
482 | && info->tty && !C_CLOCAL(info->tty)) { | ||
483 | if (status & DCD) { | ||
484 | wake_up_interruptible(&info->open_wait); | ||
485 | } else { | ||
486 | if (info->tty) | ||
487 | tty_hangup(info->tty); | ||
488 | } | ||
489 | } | ||
490 | |||
491 | /* Check for CTS transitions */ | ||
492 | if (info->tty && C_CRTSCTS(info->tty)) { | ||
493 | /* | ||
494 | * For some reason, on the Power Macintosh, | ||
495 | * it seems that the CTS bit is 1 when CTS is | ||
496 | * *negated* and 0 when it is asserted. | ||
497 | * The DCD bit doesn't seem to be inverted | ||
498 | * like this. | ||
499 | */ | ||
500 | if ((status & CTS) == 0) { | ||
501 | if (info->tx_stopped) { | ||
502 | #ifdef SERIAL_DEBUG_FLOW | ||
503 | printk(KERN_DEBUG "CTS up\n"); | ||
504 | #endif | ||
505 | info->tx_stopped = 0; | ||
506 | if (!info->tx_active) | ||
507 | transmit_chars(info); | ||
508 | } | ||
509 | } else { | ||
510 | #ifdef SERIAL_DEBUG_FLOW | ||
511 | printk(KERN_DEBUG "CTS down\n"); | ||
512 | #endif | ||
513 | info->tx_stopped = 1; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | /* Clear status condition... */ | ||
518 | write_zsreg(info->zs_channel, 0, RES_EXT_INT); | ||
519 | info->read_reg_zero = status; | ||
520 | } | ||
521 | |||
522 | static _INLINE_ void receive_special_dma(struct mac_serial *info) | ||
523 | { | ||
524 | unsigned char stat, flag; | ||
525 | volatile struct dbdma_regs *rd = &info->rx->dma; | ||
526 | int where = RX_BUF_SIZE; | ||
527 | |||
528 | spin_lock(&info->rx_dma_lock); | ||
529 | if ((ld_le32(&rd->status) & ACTIVE) != 0) | ||
530 | dbdma_flush(rd); | ||
531 | if (in_le32(&rd->cmdptr) | ||
532 | == virt_to_bus(info->rx_cmds[info->rx_cbuf] + 1)) | ||
533 | where -= in_le16(&info->rx->res_count); | ||
534 | where--; | ||
535 | |||
536 | stat = read_zsreg(info->zs_channel, R1); | ||
537 | |||
538 | flag = stat_to_flag(stat); | ||
539 | if (flag) { | ||
540 | info->rx_flag_buf[info->rx_cbuf][where] = flag; | ||
541 | /* reset the error indication */ | ||
542 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
543 | } | ||
544 | |||
545 | spin_unlock(&info->rx_dma_lock); | ||
546 | } | ||
547 | |||
548 | /* | ||
549 | * This is the serial driver's generic interrupt routine | ||
550 | */ | ||
551 | static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) | ||
552 | { | ||
553 | struct mac_serial *info = (struct mac_serial *) dev_id; | ||
554 | unsigned char zs_intreg; | ||
555 | int shift; | ||
556 | unsigned long flags; | ||
557 | int handled = 0; | ||
558 | |||
559 | if (!(info->flags & ZILOG_INITIALIZED)) { | ||
560 | printk(KERN_WARNING "rs_interrupt: irq %d, port not " | ||
561 | "initialized\n", irq); | ||
562 | disable_irq(irq); | ||
563 | return IRQ_NONE; | ||
564 | } | ||
565 | |||
566 | /* NOTE: The read register 3, which holds the irq status, | ||
567 | * does so for both channels on each chip. Although | ||
568 | * the status value itself must be read from the A | ||
569 | * channel and is only valid when read from channel A. | ||
570 | * Yes... broken hardware... | ||
571 | */ | ||
572 | #define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT) | ||
573 | |||
574 | if (info->zs_chan_a == info->zs_channel) | ||
575 | shift = 3; /* Channel A */ | ||
576 | else | ||
577 | shift = 0; /* Channel B */ | ||
578 | |||
579 | spin_lock_irqsave(&info->lock, flags); | ||
580 | for (;;) { | ||
581 | zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; | ||
582 | #ifdef SERIAL_DEBUG_INTR | ||
583 | printk(KERN_DEBUG "rs_interrupt: irq %d, zs_intreg 0x%x\n", | ||
584 | irq, (int)zs_intreg); | ||
585 | #endif | ||
586 | |||
587 | if ((zs_intreg & CHAN_IRQMASK) == 0) | ||
588 | break; | ||
589 | handled = 1; | ||
590 | |||
591 | if (zs_intreg & CHBRxIP) { | ||
592 | /* If we are doing DMA, we only ask for interrupts | ||
593 | on characters with errors or special conditions. */ | ||
594 | if (info->dma_initted) | ||
595 | receive_special_dma(info); | ||
596 | else | ||
597 | receive_chars(info, regs); | ||
598 | } | ||
599 | if (zs_intreg & CHBTxIP) | ||
600 | transmit_chars(info); | ||
601 | if (zs_intreg & CHBEXT) | ||
602 | status_handle(info); | ||
603 | } | ||
604 | spin_unlock_irqrestore(&info->lock, flags); | ||
605 | return IRQ_RETVAL(handled); | ||
606 | } | ||
607 | |||
608 | /* Transmit DMA interrupt - not used at present */ | ||
609 | static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
610 | { | ||
611 | return IRQ_HANDLED; | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | * Receive DMA interrupt. | ||
616 | */ | ||
617 | static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
618 | { | ||
619 | struct mac_serial *info = (struct mac_serial *) dev_id; | ||
620 | volatile struct dbdma_cmd *cd; | ||
621 | |||
622 | if (!info->dma_initted) | ||
623 | return IRQ_NONE; | ||
624 | spin_lock(&info->rx_dma_lock); | ||
625 | /* First, confirm that this interrupt is, indeed, coming */ | ||
626 | /* from Rx DMA */ | ||
627 | cd = info->rx_cmds[info->rx_cbuf] + 2; | ||
628 | if ((in_le16(&cd->xfer_status) & (RUN | ACTIVE)) != (RUN | ACTIVE)) { | ||
629 | spin_unlock(&info->rx_dma_lock); | ||
630 | return IRQ_NONE; | ||
631 | } | ||
632 | if (info->rx_fbuf != RX_NO_FBUF) { | ||
633 | info->rx_cbuf = info->rx_fbuf; | ||
634 | if (++info->rx_fbuf == info->rx_nbuf) | ||
635 | info->rx_fbuf = 0; | ||
636 | if (info->rx_fbuf == info->rx_ubuf) | ||
637 | info->rx_fbuf = RX_NO_FBUF; | ||
638 | } | ||
639 | spin_unlock(&info->rx_dma_lock); | ||
640 | return IRQ_HANDLED; | ||
641 | } | ||
642 | |||
643 | /* | ||
644 | * ------------------------------------------------------------------- | ||
645 | * Here ends the serial interrupt routines. | ||
646 | * ------------------------------------------------------------------- | ||
647 | */ | ||
648 | |||
649 | /* | ||
650 | * ------------------------------------------------------------ | ||
651 | * rs_stop() and rs_start() | ||
652 | * | ||
653 | * This routines are called before setting or resetting tty->stopped. | ||
654 | * ------------------------------------------------------------ | ||
655 | */ | ||
656 | static void rs_stop(struct tty_struct *tty) | ||
657 | { | ||
658 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
659 | |||
660 | #ifdef SERIAL_DEBUG_STOP | ||
661 | printk(KERN_DEBUG "rs_stop %ld....\n", | ||
662 | tty->ldisc.chars_in_buffer(tty)); | ||
663 | #endif | ||
664 | |||
665 | if (serial_paranoia_check(info, tty->name, "rs_stop")) | ||
666 | return; | ||
667 | |||
668 | #if 0 | ||
669 | spin_lock_irqsave(&info->lock, flags); | ||
670 | if (info->curregs[5] & TxENAB) { | ||
671 | info->curregs[5] &= ~TxENAB; | ||
672 | info->pendregs[5] &= ~TxENAB; | ||
673 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
674 | } | ||
675 | spin_unlock_irqrestore(&info->lock, flags); | ||
676 | #endif | ||
677 | } | ||
678 | |||
679 | static void rs_start(struct tty_struct *tty) | ||
680 | { | ||
681 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
682 | unsigned long flags; | ||
683 | |||
684 | #ifdef SERIAL_DEBUG_STOP | ||
685 | printk(KERN_DEBUG "rs_start %ld....\n", | ||
686 | tty->ldisc.chars_in_buffer(tty)); | ||
687 | #endif | ||
688 | |||
689 | if (serial_paranoia_check(info, tty->name, "rs_start")) | ||
690 | return; | ||
691 | |||
692 | spin_lock_irqsave(&info->lock, flags); | ||
693 | #if 0 | ||
694 | if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) { | ||
695 | info->curregs[5] |= TxENAB; | ||
696 | info->pendregs[5] = info->curregs[5]; | ||
697 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
698 | } | ||
699 | #else | ||
700 | if (info->xmit_cnt && info->xmit_buf && !info->tx_active) { | ||
701 | transmit_chars(info); | ||
702 | } | ||
703 | #endif | ||
704 | spin_unlock_irqrestore(&info->lock, flags); | ||
705 | } | ||
706 | |||
707 | static void do_softint(void *private_) | ||
708 | { | ||
709 | struct mac_serial *info = (struct mac_serial *) private_; | ||
710 | struct tty_struct *tty; | ||
711 | |||
712 | tty = info->tty; | ||
713 | if (!tty) | ||
714 | return; | ||
715 | |||
716 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) | ||
717 | tty_wakeup(tty); | ||
718 | } | ||
719 | |||
720 | static int startup(struct mac_serial * info) | ||
721 | { | ||
722 | int delay; | ||
723 | |||
724 | OPNDBG("startup() (ttyS%d, irq %d)\n", info->line, info->irq); | ||
725 | |||
726 | if (info->flags & ZILOG_INITIALIZED) { | ||
727 | OPNDBG(" -> already inited\n"); | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | if (!info->xmit_buf) { | ||
732 | info->xmit_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL); | ||
733 | if (!info->xmit_buf) | ||
734 | return -ENOMEM; | ||
735 | } | ||
736 | |||
737 | OPNDBG("starting up ttyS%d (irq %d)...\n", info->line, info->irq); | ||
738 | |||
739 | delay = set_scc_power(info, 1); | ||
740 | |||
741 | setup_scc(info); | ||
742 | |||
743 | if (delay) { | ||
744 | unsigned long flags; | ||
745 | |||
746 | /* delay is in ms */ | ||
747 | spin_lock_irqsave(&info->lock, flags); | ||
748 | info->power_wait = 1; | ||
749 | mod_timer(&info->powerup_timer, | ||
750 | jiffies + (delay * HZ + 999) / 1000); | ||
751 | spin_unlock_irqrestore(&info->lock, flags); | ||
752 | } | ||
753 | |||
754 | OPNDBG("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq); | ||
755 | |||
756 | info->flags |= ZILOG_INITIALIZED; | ||
757 | enable_irq(info->irq); | ||
758 | if (info->dma_initted) { | ||
759 | enable_irq(info->rx_dma_irq); | ||
760 | } | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | static _INLINE_ void rxdma_start(struct mac_serial * info, int curr) | ||
766 | { | ||
767 | volatile struct dbdma_regs *rd = &info->rx->dma; | ||
768 | volatile struct dbdma_cmd *cd = info->rx_cmds[curr]; | ||
769 | |||
770 | //printk(KERN_DEBUG "SCC: rxdma_start\n"); | ||
771 | |||
772 | st_le32(&rd->cmdptr, virt_to_bus(cd)); | ||
773 | out_le32(&rd->control, (RUN << 16) | RUN); | ||
774 | } | ||
775 | |||
776 | static void rxdma_to_tty(struct mac_serial *info) | ||
777 | { | ||
778 | struct tty_struct *tty = info->tty; | ||
779 | volatile struct dbdma_regs *rd = &info->rx->dma; | ||
780 | unsigned long flags; | ||
781 | int residue, available, space, do_queue; | ||
782 | |||
783 | if (!tty) | ||
784 | return; | ||
785 | |||
786 | do_queue = 0; | ||
787 | spin_lock_irqsave(&info->rx_dma_lock, flags); | ||
788 | more: | ||
789 | space = TTY_FLIPBUF_SIZE - tty->flip.count; | ||
790 | if (!space) { | ||
791 | do_queue++; | ||
792 | goto out; | ||
793 | } | ||
794 | residue = 0; | ||
795 | if (info->rx_ubuf == info->rx_cbuf) { | ||
796 | if ((ld_le32(&rd->status) & ACTIVE) != 0) { | ||
797 | dbdma_flush(rd); | ||
798 | if (in_le32(&rd->cmdptr) | ||
799 | == virt_to_bus(info->rx_cmds[info->rx_cbuf]+1)) | ||
800 | residue = in_le16(&info->rx->res_count); | ||
801 | } | ||
802 | } | ||
803 | available = RX_BUF_SIZE - residue - info->rx_done_bytes; | ||
804 | if (available > space) | ||
805 | available = space; | ||
806 | if (available) { | ||
807 | memcpy(tty->flip.char_buf_ptr, | ||
808 | info->rx_char_buf[info->rx_ubuf] + info->rx_done_bytes, | ||
809 | available); | ||
810 | memcpy(tty->flip.flag_buf_ptr, | ||
811 | info->rx_flag_buf[info->rx_ubuf] + info->rx_done_bytes, | ||
812 | available); | ||
813 | tty->flip.char_buf_ptr += available; | ||
814 | tty->flip.count += available; | ||
815 | tty->flip.flag_buf_ptr += available; | ||
816 | memset(info->rx_flag_buf[info->rx_ubuf] + info->rx_done_bytes, | ||
817 | 0, available); | ||
818 | info->rx_done_bytes += available; | ||
819 | do_queue++; | ||
820 | } | ||
821 | if (info->rx_done_bytes == RX_BUF_SIZE) { | ||
822 | volatile struct dbdma_cmd *cd = info->rx_cmds[info->rx_ubuf]; | ||
823 | |||
824 | if (info->rx_ubuf == info->rx_cbuf) | ||
825 | goto out; | ||
826 | /* mark rx_char_buf[rx_ubuf] free */ | ||
827 | st_le16(&cd->command, DBDMA_NOP); | ||
828 | cd++; | ||
829 | st_le32(&cd->cmd_dep, 0); | ||
830 | st_le32((unsigned int *)&cd->res_count, 0); | ||
831 | cd++; | ||
832 | st_le16(&cd->xfer_status, 0); | ||
833 | |||
834 | if (info->rx_fbuf == RX_NO_FBUF) { | ||
835 | info->rx_fbuf = info->rx_ubuf; | ||
836 | if (!(ld_le32(&rd->status) & ACTIVE)) { | ||
837 | dbdma_reset(&info->rx->dma); | ||
838 | rxdma_start(info, info->rx_ubuf); | ||
839 | info->rx_cbuf = info->rx_ubuf; | ||
840 | } | ||
841 | } | ||
842 | info->rx_done_bytes = 0; | ||
843 | if (++info->rx_ubuf == info->rx_nbuf) | ||
844 | info->rx_ubuf = 0; | ||
845 | if (info->rx_fbuf == info->rx_ubuf) | ||
846 | info->rx_fbuf = RX_NO_FBUF; | ||
847 | goto more; | ||
848 | } | ||
849 | out: | ||
850 | spin_unlock_irqrestore(&info->rx_dma_lock, flags); | ||
851 | if (do_queue) | ||
852 | tty_flip_buffer_push(tty); | ||
853 | } | ||
854 | |||
855 | static void poll_rxdma(unsigned long private_) | ||
856 | { | ||
857 | struct mac_serial *info = (struct mac_serial *) private_; | ||
858 | unsigned long flags; | ||
859 | |||
860 | rxdma_to_tty(info); | ||
861 | spin_lock_irqsave(&info->rx_dma_lock, flags); | ||
862 | mod_timer(&info->poll_dma_timer, RX_DMA_TIMER); | ||
863 | spin_unlock_irqrestore(&info->rx_dma_lock, flags); | ||
864 | } | ||
865 | |||
866 | static void dma_init(struct mac_serial * info) | ||
867 | { | ||
868 | int i, size; | ||
869 | volatile struct dbdma_cmd *cd; | ||
870 | unsigned char *p; | ||
871 | |||
872 | info->rx_nbuf = 8; | ||
873 | |||
874 | /* various mem set up */ | ||
875 | size = sizeof(struct dbdma_cmd) * (3 * info->rx_nbuf + 2) | ||
876 | + (RX_BUF_SIZE * 2 + sizeof(*info->rx_cmds) | ||
877 | + sizeof(*info->rx_char_buf) + sizeof(*info->rx_flag_buf)) | ||
878 | * info->rx_nbuf; | ||
879 | info->dma_priv = kmalloc(size, GFP_KERNEL | GFP_DMA); | ||
880 | if (info->dma_priv == NULL) | ||
881 | return; | ||
882 | memset(info->dma_priv, 0, size); | ||
883 | |||
884 | info->rx_cmds = (volatile struct dbdma_cmd **)info->dma_priv; | ||
885 | info->rx_char_buf = (unsigned char **) (info->rx_cmds + info->rx_nbuf); | ||
886 | info->rx_flag_buf = info->rx_char_buf + info->rx_nbuf; | ||
887 | p = (unsigned char *) (info->rx_flag_buf + info->rx_nbuf); | ||
888 | for (i = 0; i < info->rx_nbuf; i++, p += RX_BUF_SIZE) | ||
889 | info->rx_char_buf[i] = p; | ||
890 | for (i = 0; i < info->rx_nbuf; i++, p += RX_BUF_SIZE) | ||
891 | info->rx_flag_buf[i] = p; | ||
892 | |||
893 | /* a bit of DMA programming */ | ||
894 | cd = info->rx_cmds[0] = (volatile struct dbdma_cmd *) DBDMA_ALIGN(p); | ||
895 | st_le16(&cd->command, DBDMA_NOP); | ||
896 | cd++; | ||
897 | st_le16(&cd->req_count, RX_BUF_SIZE); | ||
898 | st_le16(&cd->command, INPUT_MORE); | ||
899 | st_le32(&cd->phy_addr, virt_to_bus(info->rx_char_buf[0])); | ||
900 | cd++; | ||
901 | st_le16(&cd->req_count, 4); | ||
902 | st_le16(&cd->command, STORE_WORD | INTR_ALWAYS); | ||
903 | st_le32(&cd->phy_addr, virt_to_bus(cd-2)); | ||
904 | st_le32(&cd->cmd_dep, DBDMA_STOP); | ||
905 | for (i = 1; i < info->rx_nbuf; i++) { | ||
906 | info->rx_cmds[i] = ++cd; | ||
907 | st_le16(&cd->command, DBDMA_NOP); | ||
908 | cd++; | ||
909 | st_le16(&cd->req_count, RX_BUF_SIZE); | ||
910 | st_le16(&cd->command, INPUT_MORE); | ||
911 | st_le32(&cd->phy_addr, virt_to_bus(info->rx_char_buf[i])); | ||
912 | cd++; | ||
913 | st_le16(&cd->req_count, 4); | ||
914 | st_le16(&cd->command, STORE_WORD | INTR_ALWAYS); | ||
915 | st_le32(&cd->phy_addr, virt_to_bus(cd-2)); | ||
916 | st_le32(&cd->cmd_dep, DBDMA_STOP); | ||
917 | } | ||
918 | cd++; | ||
919 | st_le16(&cd->command, DBDMA_NOP | BR_ALWAYS); | ||
920 | st_le32(&cd->cmd_dep, virt_to_bus(info->rx_cmds[0])); | ||
921 | |||
922 | /* setup DMA to our liking */ | ||
923 | dbdma_reset(&info->rx->dma); | ||
924 | st_le32(&info->rx->dma.intr_sel, 0x10001); | ||
925 | st_le32(&info->rx->dma.br_sel, 0x10001); | ||
926 | out_le32(&info->rx->dma.wait_sel, 0x10001); | ||
927 | |||
928 | /* set various flags */ | ||
929 | info->rx_ubuf = 0; | ||
930 | info->rx_cbuf = 0; | ||
931 | info->rx_fbuf = info->rx_ubuf + 1; | ||
932 | if (info->rx_fbuf == info->rx_nbuf) | ||
933 | info->rx_fbuf = RX_NO_FBUF; | ||
934 | info->rx_done_bytes = 0; | ||
935 | |||
936 | /* setup polling */ | ||
937 | init_timer(&info->poll_dma_timer); | ||
938 | info->poll_dma_timer.function = (void *)&poll_rxdma; | ||
939 | info->poll_dma_timer.data = (unsigned long)info; | ||
940 | |||
941 | info->dma_initted = 1; | ||
942 | } | ||
943 | |||
944 | /* | ||
945 | * FixZeroBug....Works around a bug in the SCC receving channel. | ||
946 | * Taken from Darwin code, 15 Sept. 2000 -DanM | ||
947 | * | ||
948 | * The following sequence prevents a problem that is seen with O'Hare ASICs | ||
949 | * (most versions -- also with some Heathrow and Hydra ASICs) where a zero | ||
950 | * at the input to the receiver becomes 'stuck' and locks up the receiver. | ||
951 | * This problem can occur as a result of a zero bit at the receiver input | ||
952 | * coincident with any of the following events: | ||
953 | * | ||
954 | * The SCC is initialized (hardware or software). | ||
955 | * A framing error is detected. | ||
956 | * The clocking option changes from synchronous or X1 asynchronous | ||
957 | * clocking to X16, X32, or X64 asynchronous clocking. | ||
958 | * The decoding mode is changed among NRZ, NRZI, FM0, or FM1. | ||
959 | * | ||
960 | * This workaround attempts to recover from the lockup condition by placing | ||
961 | * the SCC in synchronous loopback mode with a fast clock before programming | ||
962 | * any of the asynchronous modes. | ||
963 | */ | ||
964 | static void fix_zero_bug_scc(struct mac_serial * info) | ||
965 | { | ||
966 | write_zsreg(info->zs_channel, 9, | ||
967 | (info->zs_channel == info->zs_chan_a? CHRA: CHRB)); | ||
968 | udelay(10); | ||
969 | write_zsreg(info->zs_channel, 9, | ||
970 | ((info->zs_channel == info->zs_chan_a? CHRA: CHRB) | NV)); | ||
971 | |||
972 | write_zsreg(info->zs_channel, 4, (X1CLK | EXTSYNC)); | ||
973 | |||
974 | /* I think this is wrong....but, I just copying code.... | ||
975 | */ | ||
976 | write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE)); | ||
977 | |||
978 | write_zsreg(info->zs_channel, 5, (8 & ~TxENAB)); | ||
979 | write_zsreg(info->zs_channel, 9, NV); /* Didn't we already do this? */ | ||
980 | write_zsreg(info->zs_channel, 11, (RCBR | TCBR)); | ||
981 | write_zsreg(info->zs_channel, 12, 0); | ||
982 | write_zsreg(info->zs_channel, 13, 0); | ||
983 | write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR)); | ||
984 | write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR | BRENABL)); | ||
985 | write_zsreg(info->zs_channel, 3, (8 | RxENABLE)); | ||
986 | write_zsreg(info->zs_channel, 0, RES_EXT_INT); | ||
987 | write_zsreg(info->zs_channel, 0, RES_EXT_INT); /* to kill some time */ | ||
988 | |||
989 | /* The channel should be OK now, but it is probably receiving | ||
990 | * loopback garbage. | ||
991 | * Switch to asynchronous mode, disable the receiver, | ||
992 | * and discard everything in the receive buffer. | ||
993 | */ | ||
994 | write_zsreg(info->zs_channel, 9, NV); | ||
995 | write_zsreg(info->zs_channel, 4, PAR_ENA); | ||
996 | write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE)); | ||
997 | |||
998 | while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV) { | ||
999 | (void)read_zsreg(info->zs_channel, 8); | ||
1000 | write_zsreg(info->zs_channel, 0, RES_EXT_INT); | ||
1001 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | static int setup_scc(struct mac_serial * info) | ||
1006 | { | ||
1007 | unsigned long flags; | ||
1008 | |||
1009 | OPNDBG("setting up ttyS%d SCC...\n", info->line); | ||
1010 | |||
1011 | spin_lock_irqsave(&info->lock, flags); | ||
1012 | |||
1013 | /* Nice buggy HW ... */ | ||
1014 | fix_zero_bug_scc(info); | ||
1015 | |||
1016 | /* | ||
1017 | * Reset the chip. | ||
1018 | */ | ||
1019 | write_zsreg(info->zs_channel, 9, | ||
1020 | (info->zs_channel == info->zs_chan_a? CHRA: CHRB)); | ||
1021 | udelay(10); | ||
1022 | write_zsreg(info->zs_channel, 9, 0); | ||
1023 | |||
1024 | /* | ||
1025 | * Clear the receive FIFO. | ||
1026 | */ | ||
1027 | ZS_CLEARFIFO(info->zs_channel); | ||
1028 | info->xmit_fifo_size = 1; | ||
1029 | |||
1030 | /* | ||
1031 | * Reset DMAs | ||
1032 | */ | ||
1033 | if (info->has_dma) | ||
1034 | dma_init(info); | ||
1035 | |||
1036 | /* | ||
1037 | * Clear the interrupt registers. | ||
1038 | */ | ||
1039 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
1040 | write_zsreg(info->zs_channel, 0, RES_H_IUS); | ||
1041 | |||
1042 | /* | ||
1043 | * Turn on RTS and DTR. | ||
1044 | */ | ||
1045 | if (!info->is_irda) | ||
1046 | zs_rtsdtr(info, 1); | ||
1047 | |||
1048 | /* | ||
1049 | * Finally, enable sequencing and interrupts | ||
1050 | */ | ||
1051 | if (!info->dma_initted) { | ||
1052 | /* interrupt on ext/status changes, all received chars, | ||
1053 | transmit ready */ | ||
1054 | info->curregs[1] = (info->curregs[1] & ~0x18) | ||
1055 | | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); | ||
1056 | } else { | ||
1057 | /* interrupt on ext/status changes, W/Req pin is | ||
1058 | receive DMA request */ | ||
1059 | info->curregs[1] = (info->curregs[1] & ~(0x18 | TxINT_ENAB)) | ||
1060 | | (EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN); | ||
1061 | write_zsreg(info->zs_channel, 1, info->curregs[1]); | ||
1062 | /* enable W/Req pin */ | ||
1063 | info->curregs[1] |= WT_RDY_ENAB; | ||
1064 | write_zsreg(info->zs_channel, 1, info->curregs[1]); | ||
1065 | /* enable interrupts on transmit ready and receive errors */ | ||
1066 | info->curregs[1] |= INT_ERR_Rx | TxINT_ENAB; | ||
1067 | } | ||
1068 | info->pendregs[1] = info->curregs[1]; | ||
1069 | info->curregs[3] |= (RxENABLE | Rx8); | ||
1070 | info->pendregs[3] = info->curregs[3]; | ||
1071 | info->curregs[5] |= (TxENAB | Tx8); | ||
1072 | info->pendregs[5] = info->curregs[5]; | ||
1073 | info->curregs[9] |= (NV | MIE); | ||
1074 | info->pendregs[9] = info->curregs[9]; | ||
1075 | write_zsreg(info->zs_channel, 3, info->curregs[3]); | ||
1076 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1077 | write_zsreg(info->zs_channel, 9, info->curregs[9]); | ||
1078 | |||
1079 | if (info->tty) | ||
1080 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | ||
1081 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
1082 | |||
1083 | spin_unlock_irqrestore(&info->lock, flags); | ||
1084 | |||
1085 | /* | ||
1086 | * Set the speed of the serial port | ||
1087 | */ | ||
1088 | change_speed(info, 0); | ||
1089 | |||
1090 | /* Save the current value of RR0 */ | ||
1091 | info->read_reg_zero = read_zsreg(info->zs_channel, 0); | ||
1092 | |||
1093 | if (info->dma_initted) { | ||
1094 | spin_lock_irqsave(&info->rx_dma_lock, flags); | ||
1095 | rxdma_start(info, 0); | ||
1096 | info->poll_dma_timer.expires = RX_DMA_TIMER; | ||
1097 | add_timer(&info->poll_dma_timer); | ||
1098 | spin_unlock_irqrestore(&info->rx_dma_lock, flags); | ||
1099 | } | ||
1100 | |||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | /* | ||
1105 | * This routine will shutdown a serial port; interrupts are disabled, and | ||
1106 | * DTR is dropped if the hangup on close termio flag is on. | ||
1107 | */ | ||
1108 | static void shutdown(struct mac_serial * info) | ||
1109 | { | ||
1110 | OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line, | ||
1111 | info->irq); | ||
1112 | |||
1113 | if (!(info->flags & ZILOG_INITIALIZED)) { | ||
1114 | OPNDBG("(already shutdown)\n"); | ||
1115 | return; | ||
1116 | } | ||
1117 | |||
1118 | if (info->has_dma) { | ||
1119 | del_timer(&info->poll_dma_timer); | ||
1120 | dbdma_reset(info->tx_dma); | ||
1121 | dbdma_reset(&info->rx->dma); | ||
1122 | disable_irq(info->tx_dma_irq); | ||
1123 | disable_irq(info->rx_dma_irq); | ||
1124 | } | ||
1125 | disable_irq(info->irq); | ||
1126 | |||
1127 | info->pendregs[1] = info->curregs[1] = 0; | ||
1128 | write_zsreg(info->zs_channel, 1, 0); /* no interrupts */ | ||
1129 | |||
1130 | info->curregs[3] &= ~RxENABLE; | ||
1131 | info->pendregs[3] = info->curregs[3]; | ||
1132 | write_zsreg(info->zs_channel, 3, info->curregs[3]); | ||
1133 | |||
1134 | info->curregs[5] &= ~TxENAB; | ||
1135 | if (!info->tty || C_HUPCL(info->tty)) | ||
1136 | info->curregs[5] &= ~DTR; | ||
1137 | info->pendregs[5] = info->curregs[5]; | ||
1138 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1139 | |||
1140 | if (info->tty) | ||
1141 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
1142 | |||
1143 | set_scc_power(info, 0); | ||
1144 | |||
1145 | if (info->xmit_buf) { | ||
1146 | free_page((unsigned long) info->xmit_buf); | ||
1147 | info->xmit_buf = 0; | ||
1148 | } | ||
1149 | |||
1150 | if (info->has_dma && info->dma_priv) { | ||
1151 | kfree(info->dma_priv); | ||
1152 | info->dma_priv = NULL; | ||
1153 | info->dma_initted = 0; | ||
1154 | } | ||
1155 | |||
1156 | memset(info->curregs, 0, sizeof(info->curregs)); | ||
1157 | memset(info->pendregs, 0, sizeof(info->pendregs)); | ||
1158 | |||
1159 | info->flags &= ~ZILOG_INITIALIZED; | ||
1160 | } | ||
1161 | |||
1162 | /* | ||
1163 | * Turn power on or off to the SCC and associated stuff | ||
1164 | * (port drivers, modem, IR port, etc.) | ||
1165 | * Returns the number of milliseconds we should wait before | ||
1166 | * trying to use the port. | ||
1167 | */ | ||
1168 | static int set_scc_power(struct mac_serial * info, int state) | ||
1169 | { | ||
1170 | int delay = 0; | ||
1171 | |||
1172 | if (state) { | ||
1173 | PWRDBG("ttyS%d: powering up hardware\n", info->line); | ||
1174 | pmac_call_feature( | ||
1175 | PMAC_FTR_SCC_ENABLE, | ||
1176 | info->dev_node, info->port_type, 1); | ||
1177 | if (info->is_internal_modem) { | ||
1178 | pmac_call_feature( | ||
1179 | PMAC_FTR_MODEM_ENABLE, | ||
1180 | info->dev_node, 0, 1); | ||
1181 | delay = 2500; /* wait for 2.5s before using */ | ||
1182 | } else if (info->is_irda) | ||
1183 | mdelay(50); /* Do better here once the problems | ||
1184 | * with blocking have been ironed out | ||
1185 | */ | ||
1186 | } else { | ||
1187 | /* TODO: Make that depend on a timer, don't power down | ||
1188 | * immediately | ||
1189 | */ | ||
1190 | PWRDBG("ttyS%d: shutting down hardware\n", info->line); | ||
1191 | if (info->is_internal_modem) { | ||
1192 | PWRDBG("ttyS%d: shutting down modem\n", info->line); | ||
1193 | pmac_call_feature( | ||
1194 | PMAC_FTR_MODEM_ENABLE, | ||
1195 | info->dev_node, 0, 0); | ||
1196 | } | ||
1197 | pmac_call_feature( | ||
1198 | PMAC_FTR_SCC_ENABLE, | ||
1199 | info->dev_node, info->port_type, 0); | ||
1200 | } | ||
1201 | return delay; | ||
1202 | } | ||
1203 | |||
1204 | static void irda_rts_pulses(struct mac_serial *info, int w) | ||
1205 | { | ||
1206 | udelay(w); | ||
1207 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB); | ||
1208 | udelay(2); | ||
1209 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); | ||
1210 | udelay(8); | ||
1211 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB); | ||
1212 | udelay(4); | ||
1213 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); | ||
1214 | } | ||
1215 | |||
1216 | /* | ||
1217 | * Set the irda codec on the imac to the specified baud rate. | ||
1218 | */ | ||
1219 | static void irda_setup(struct mac_serial *info) | ||
1220 | { | ||
1221 | int code, speed, t; | ||
1222 | |||
1223 | speed = info->tty->termios->c_cflag & CBAUD; | ||
1224 | if (speed < B2400 || speed > B115200) | ||
1225 | return; | ||
1226 | code = 0x4d + B115200 - speed; | ||
1227 | |||
1228 | /* disable serial interrupts and receive DMA */ | ||
1229 | write_zsreg(info->zs_channel, 1, info->curregs[1] & ~0x9f); | ||
1230 | |||
1231 | /* wait for transmitter to drain */ | ||
1232 | t = 10000; | ||
1233 | while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0 | ||
1234 | || (read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { | ||
1235 | if (--t <= 0) { | ||
1236 | printk(KERN_ERR "transmitter didn't drain\n"); | ||
1237 | return; | ||
1238 | } | ||
1239 | udelay(10); | ||
1240 | } | ||
1241 | udelay(100); | ||
1242 | |||
1243 | /* set to 8 bits, no parity, 19200 baud, RTS on, DTR off */ | ||
1244 | write_zsreg(info->zs_channel, 4, X16CLK | SB1); | ||
1245 | write_zsreg(info->zs_channel, 11, TCBR | RCBR); | ||
1246 | t = BPS_TO_BRG(19200, ZS_CLOCK/16); | ||
1247 | write_zsreg(info->zs_channel, 12, t); | ||
1248 | write_zsreg(info->zs_channel, 13, t >> 8); | ||
1249 | write_zsreg(info->zs_channel, 14, BRENABL); | ||
1250 | write_zsreg(info->zs_channel, 3, Rx8 | RxENABLE); | ||
1251 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); | ||
1252 | |||
1253 | /* set TxD low for ~104us and pulse RTS */ | ||
1254 | udelay(1000); | ||
1255 | write_zsdata(info->zs_channel, 0xfe); | ||
1256 | irda_rts_pulses(info, 150); | ||
1257 | irda_rts_pulses(info, 180); | ||
1258 | irda_rts_pulses(info, 50); | ||
1259 | udelay(100); | ||
1260 | |||
1261 | /* assert DTR, wait 30ms, talk to the chip */ | ||
1262 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS | DTR); | ||
1263 | mdelay(30); | ||
1264 | while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV) | ||
1265 | read_zsdata(info->zs_channel); | ||
1266 | |||
1267 | write_zsdata(info->zs_channel, 1); | ||
1268 | t = 1000; | ||
1269 | while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) { | ||
1270 | if (--t <= 0) { | ||
1271 | printk(KERN_ERR "irda_setup timed out on 1st byte\n"); | ||
1272 | goto out; | ||
1273 | } | ||
1274 | udelay(10); | ||
1275 | } | ||
1276 | t = read_zsdata(info->zs_channel); | ||
1277 | if (t != 4) | ||
1278 | printk(KERN_ERR "irda_setup 1st byte = %x\n", t); | ||
1279 | |||
1280 | write_zsdata(info->zs_channel, code); | ||
1281 | t = 1000; | ||
1282 | while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) { | ||
1283 | if (--t <= 0) { | ||
1284 | printk(KERN_ERR "irda_setup timed out on 2nd byte\n"); | ||
1285 | goto out; | ||
1286 | } | ||
1287 | udelay(10); | ||
1288 | } | ||
1289 | t = read_zsdata(info->zs_channel); | ||
1290 | if (t != code) | ||
1291 | printk(KERN_ERR "irda_setup 2nd byte = %x (%x)\n", t, code); | ||
1292 | |||
1293 | /* Drop DTR again and do some more RTS pulses */ | ||
1294 | out: | ||
1295 | udelay(100); | ||
1296 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); | ||
1297 | irda_rts_pulses(info, 80); | ||
1298 | |||
1299 | /* We should be right to go now. We assume that load_zsregs | ||
1300 | will get called soon to load up the correct baud rate etc. */ | ||
1301 | info->curregs[5] = (info->curregs[5] | RTS) & ~DTR; | ||
1302 | info->pendregs[5] = info->curregs[5]; | ||
1303 | } | ||
1304 | |||
1305 | /* | ||
1306 | * This routine is called to set the UART divisor registers to match | ||
1307 | * the specified baud rate for a serial port. | ||
1308 | */ | ||
1309 | static void change_speed(struct mac_serial *info, struct termios *old_termios) | ||
1310 | { | ||
1311 | unsigned cflag; | ||
1312 | int bits; | ||
1313 | int brg, baud; | ||
1314 | unsigned long flags; | ||
1315 | |||
1316 | if (!info->tty || !info->tty->termios) | ||
1317 | return; | ||
1318 | |||
1319 | cflag = info->tty->termios->c_cflag; | ||
1320 | baud = tty_get_baud_rate(info->tty); | ||
1321 | if (baud == 0) { | ||
1322 | if (old_termios) { | ||
1323 | info->tty->termios->c_cflag &= ~CBAUD; | ||
1324 | info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); | ||
1325 | cflag = info->tty->termios->c_cflag; | ||
1326 | baud = tty_get_baud_rate(info->tty); | ||
1327 | } | ||
1328 | else | ||
1329 | baud = info->zs_baud; | ||
1330 | } | ||
1331 | if (baud > 230400) | ||
1332 | baud = 230400; | ||
1333 | else if (baud == 0) | ||
1334 | baud = 38400; | ||
1335 | |||
1336 | spin_lock_irqsave(&info->lock, flags); | ||
1337 | info->zs_baud = baud; | ||
1338 | info->clk_divisor = 16; | ||
1339 | |||
1340 | BAUDBG(KERN_DEBUG "set speed to %d bds, ", baud); | ||
1341 | |||
1342 | switch (baud) { | ||
1343 | case ZS_CLOCK/16: /* 230400 */ | ||
1344 | info->curregs[4] = X16CLK; | ||
1345 | info->curregs[11] = 0; | ||
1346 | break; | ||
1347 | case ZS_CLOCK/32: /* 115200 */ | ||
1348 | info->curregs[4] = X32CLK; | ||
1349 | info->curregs[11] = 0; | ||
1350 | break; | ||
1351 | default: | ||
1352 | info->curregs[4] = X16CLK; | ||
1353 | info->curregs[11] = TCBR | RCBR; | ||
1354 | brg = BPS_TO_BRG(baud, ZS_CLOCK/info->clk_divisor); | ||
1355 | info->curregs[12] = (brg & 255); | ||
1356 | info->curregs[13] = ((brg >> 8) & 255); | ||
1357 | info->curregs[14] = BRENABL; | ||
1358 | } | ||
1359 | |||
1360 | /* byte size and parity */ | ||
1361 | info->curregs[3] &= ~RxNBITS_MASK; | ||
1362 | info->curregs[5] &= ~TxNBITS_MASK; | ||
1363 | switch (cflag & CSIZE) { | ||
1364 | case CS5: | ||
1365 | info->curregs[3] |= Rx5; | ||
1366 | info->curregs[5] |= Tx5; | ||
1367 | BAUDBG("5 bits, "); | ||
1368 | bits = 7; | ||
1369 | break; | ||
1370 | case CS6: | ||
1371 | info->curregs[3] |= Rx6; | ||
1372 | info->curregs[5] |= Tx6; | ||
1373 | BAUDBG("6 bits, "); | ||
1374 | bits = 8; | ||
1375 | break; | ||
1376 | case CS7: | ||
1377 | info->curregs[3] |= Rx7; | ||
1378 | info->curregs[5] |= Tx7; | ||
1379 | BAUDBG("7 bits, "); | ||
1380 | bits = 9; | ||
1381 | break; | ||
1382 | case CS8: | ||
1383 | default: /* defaults to 8 bits */ | ||
1384 | info->curregs[3] |= Rx8; | ||
1385 | info->curregs[5] |= Tx8; | ||
1386 | BAUDBG("8 bits, "); | ||
1387 | bits = 10; | ||
1388 | break; | ||
1389 | } | ||
1390 | info->pendregs[3] = info->curregs[3]; | ||
1391 | info->pendregs[5] = info->curregs[5]; | ||
1392 | |||
1393 | info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); | ||
1394 | if (cflag & CSTOPB) { | ||
1395 | info->curregs[4] |= SB2; | ||
1396 | bits++; | ||
1397 | BAUDBG("2 stop, "); | ||
1398 | } else { | ||
1399 | info->curregs[4] |= SB1; | ||
1400 | BAUDBG("1 stop, "); | ||
1401 | } | ||
1402 | if (cflag & PARENB) { | ||
1403 | bits++; | ||
1404 | info->curregs[4] |= PAR_ENA; | ||
1405 | BAUDBG("parity, "); | ||
1406 | } | ||
1407 | if (!(cflag & PARODD)) { | ||
1408 | info->curregs[4] |= PAR_EVEN; | ||
1409 | } | ||
1410 | info->pendregs[4] = info->curregs[4]; | ||
1411 | |||
1412 | if (!(cflag & CLOCAL)) { | ||
1413 | if (!(info->curregs[15] & DCDIE)) | ||
1414 | info->read_reg_zero = read_zsreg(info->zs_channel, 0); | ||
1415 | info->curregs[15] |= DCDIE; | ||
1416 | } else | ||
1417 | info->curregs[15] &= ~DCDIE; | ||
1418 | if (cflag & CRTSCTS) { | ||
1419 | info->curregs[15] |= CTSIE; | ||
1420 | if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) | ||
1421 | info->tx_stopped = 1; | ||
1422 | } else { | ||
1423 | info->curregs[15] &= ~CTSIE; | ||
1424 | info->tx_stopped = 0; | ||
1425 | } | ||
1426 | info->pendregs[15] = info->curregs[15]; | ||
1427 | |||
1428 | /* Calc timeout value. This is pretty broken with high baud rates with HZ=100. | ||
1429 | This code would love a larger HZ and a >1 fifo size, but this is not | ||
1430 | a priority. The resulting value must be >HZ/2 | ||
1431 | */ | ||
1432 | info->timeout = ((info->xmit_fifo_size*HZ*bits) / baud); | ||
1433 | info->timeout += HZ/50+1; /* Add .02 seconds of slop */ | ||
1434 | |||
1435 | BAUDBG("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ, | ||
1436 | (int)info->baud_base); | ||
1437 | |||
1438 | /* set the irda codec to the right rate */ | ||
1439 | if (info->is_irda) | ||
1440 | irda_setup(info); | ||
1441 | |||
1442 | /* Load up the new values */ | ||
1443 | load_zsregs(info->zs_channel, info->curregs); | ||
1444 | |||
1445 | spin_unlock_irqrestore(&info->lock, flags); | ||
1446 | } | ||
1447 | |||
1448 | static void rs_flush_chars(struct tty_struct *tty) | ||
1449 | { | ||
1450 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1451 | unsigned long flags; | ||
1452 | |||
1453 | if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) | ||
1454 | return; | ||
1455 | |||
1456 | spin_lock_irqsave(&info->lock, flags); | ||
1457 | if (!(info->xmit_cnt <= 0 || tty->stopped || info->tx_stopped || | ||
1458 | !info->xmit_buf)) | ||
1459 | /* Enable transmitter */ | ||
1460 | transmit_chars(info); | ||
1461 | spin_unlock_irqrestore(&info->lock, flags); | ||
1462 | } | ||
1463 | |||
1464 | static int rs_write(struct tty_struct * tty, | ||
1465 | const unsigned char *buf, int count) | ||
1466 | { | ||
1467 | int c, ret = 0; | ||
1468 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1469 | unsigned long flags; | ||
1470 | |||
1471 | if (serial_paranoia_check(info, tty->name, "rs_write")) | ||
1472 | return 0; | ||
1473 | |||
1474 | if (!tty || !info->xmit_buf || !tmp_buf) | ||
1475 | return 0; | ||
1476 | |||
1477 | while (1) { | ||
1478 | spin_lock_irqsave(&info->lock, flags); | ||
1479 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | ||
1480 | SERIAL_XMIT_SIZE - info->xmit_head)); | ||
1481 | if (c <= 0) { | ||
1482 | spin_unlock_irqrestore(&info->lock, flags); | ||
1483 | break; | ||
1484 | } | ||
1485 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
1486 | info->xmit_head = ((info->xmit_head + c) & | ||
1487 | (SERIAL_XMIT_SIZE-1)); | ||
1488 | info->xmit_cnt += c; | ||
1489 | spin_unlock_irqrestore(&info->lock, flags); | ||
1490 | buf += c; | ||
1491 | count -= c; | ||
1492 | ret += c; | ||
1493 | } | ||
1494 | spin_lock_irqsave(&info->lock, flags); | ||
1495 | if (info->xmit_cnt && !tty->stopped && !info->tx_stopped | ||
1496 | && !info->tx_active) | ||
1497 | transmit_chars(info); | ||
1498 | spin_unlock_irqrestore(&info->lock, flags); | ||
1499 | return ret; | ||
1500 | } | ||
1501 | |||
1502 | static int rs_write_room(struct tty_struct *tty) | ||
1503 | { | ||
1504 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1505 | int ret; | ||
1506 | |||
1507 | if (serial_paranoia_check(info, tty->name, "rs_write_room")) | ||
1508 | return 0; | ||
1509 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; | ||
1510 | if (ret < 0) | ||
1511 | ret = 0; | ||
1512 | return ret; | ||
1513 | } | ||
1514 | |||
1515 | static int rs_chars_in_buffer(struct tty_struct *tty) | ||
1516 | { | ||
1517 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1518 | |||
1519 | if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) | ||
1520 | return 0; | ||
1521 | return info->xmit_cnt; | ||
1522 | } | ||
1523 | |||
1524 | static void rs_flush_buffer(struct tty_struct *tty) | ||
1525 | { | ||
1526 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1527 | unsigned long flags; | ||
1528 | |||
1529 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) | ||
1530 | return; | ||
1531 | spin_lock_irqsave(&info->lock, flags); | ||
1532 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
1533 | spin_unlock_irqrestore(&info->lock, flags); | ||
1534 | tty_wakeup(tty); | ||
1535 | } | ||
1536 | |||
1537 | /* | ||
1538 | * ------------------------------------------------------------ | ||
1539 | * rs_throttle() | ||
1540 | * | ||
1541 | * This routine is called by the upper-layer tty layer to signal that | ||
1542 | * incoming characters should be throttled. | ||
1543 | * ------------------------------------------------------------ | ||
1544 | */ | ||
1545 | static void rs_throttle(struct tty_struct * tty) | ||
1546 | { | ||
1547 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1548 | unsigned long flags; | ||
1549 | #ifdef SERIAL_DEBUG_THROTTLE | ||
1550 | printk(KERN_DEBUG "throttle %ld....\n",tty->ldisc.chars_in_buffer(tty)); | ||
1551 | #endif | ||
1552 | |||
1553 | if (serial_paranoia_check(info, tty->name, "rs_throttle")) | ||
1554 | return; | ||
1555 | |||
1556 | if (I_IXOFF(tty)) { | ||
1557 | spin_lock_irqsave(&info->lock, flags); | ||
1558 | info->x_char = STOP_CHAR(tty); | ||
1559 | if (!info->tx_active) | ||
1560 | transmit_chars(info); | ||
1561 | spin_unlock_irqrestore(&info->lock, flags); | ||
1562 | } | ||
1563 | |||
1564 | if (C_CRTSCTS(tty)) { | ||
1565 | /* | ||
1566 | * Here we want to turn off the RTS line. On Macintoshes, | ||
1567 | * the external serial ports using a DIN-8 or DIN-9 | ||
1568 | * connector only have the DTR line (which is usually | ||
1569 | * wired to both RTS and DTR on an external modem in | ||
1570 | * the cable). RTS doesn't go out to the serial port | ||
1571 | * socket, it acts as an output enable for the transmit | ||
1572 | * data line. So in this case we don't drop RTS. | ||
1573 | * | ||
1574 | * Macs with internal modems generally do have both RTS | ||
1575 | * and DTR wired to the modem, so in that case we do | ||
1576 | * drop RTS. | ||
1577 | */ | ||
1578 | if (info->is_internal_modem) { | ||
1579 | spin_lock_irqsave(&info->lock, flags); | ||
1580 | info->curregs[5] &= ~RTS; | ||
1581 | info->pendregs[5] &= ~RTS; | ||
1582 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1583 | spin_unlock_irqrestore(&info->lock, flags); | ||
1584 | } | ||
1585 | } | ||
1586 | |||
1587 | #ifdef CDTRCTS | ||
1588 | if (tty->termios->c_cflag & CDTRCTS) { | ||
1589 | spin_lock_irqsave(&info->lock, flags); | ||
1590 | info->curregs[5] &= ~DTR; | ||
1591 | info->pendregs[5] &= ~DTR; | ||
1592 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1593 | spin_unlock_irqrestore(&info->lock, flags); | ||
1594 | } | ||
1595 | #endif /* CDTRCTS */ | ||
1596 | } | ||
1597 | |||
1598 | static void rs_unthrottle(struct tty_struct * tty) | ||
1599 | { | ||
1600 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1601 | unsigned long flags; | ||
1602 | #ifdef SERIAL_DEBUG_THROTTLE | ||
1603 | printk(KERN_DEBUG "unthrottle %s: %d....\n", | ||
1604 | tty->ldisc.chars_in_buffer(tty)); | ||
1605 | #endif | ||
1606 | |||
1607 | if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) | ||
1608 | return; | ||
1609 | |||
1610 | if (I_IXOFF(tty)) { | ||
1611 | spin_lock_irqsave(&info->lock, flags); | ||
1612 | if (info->x_char) | ||
1613 | info->x_char = 0; | ||
1614 | else { | ||
1615 | info->x_char = START_CHAR(tty); | ||
1616 | if (!info->tx_active) | ||
1617 | transmit_chars(info); | ||
1618 | } | ||
1619 | spin_unlock_irqrestore(&info->lock, flags); | ||
1620 | } | ||
1621 | |||
1622 | if (C_CRTSCTS(tty) && info->is_internal_modem) { | ||
1623 | /* Assert RTS line */ | ||
1624 | spin_lock_irqsave(&info->lock, flags); | ||
1625 | info->curregs[5] |= RTS; | ||
1626 | info->pendregs[5] |= RTS; | ||
1627 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1628 | spin_unlock_irqrestore(&info->lock, flags); | ||
1629 | } | ||
1630 | |||
1631 | #ifdef CDTRCTS | ||
1632 | if (tty->termios->c_cflag & CDTRCTS) { | ||
1633 | /* Assert DTR line */ | ||
1634 | spin_lock_irqsave(&info->lock, flags); | ||
1635 | info->curregs[5] |= DTR; | ||
1636 | info->pendregs[5] |= DTR; | ||
1637 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1638 | spin_unlock_irqrestore(&info->lock, flags); | ||
1639 | } | ||
1640 | #endif | ||
1641 | } | ||
1642 | |||
1643 | /* | ||
1644 | * ------------------------------------------------------------ | ||
1645 | * rs_ioctl() and friends | ||
1646 | * ------------------------------------------------------------ | ||
1647 | */ | ||
1648 | |||
1649 | static int get_serial_info(struct mac_serial * info, | ||
1650 | struct serial_struct __user * retinfo) | ||
1651 | { | ||
1652 | struct serial_struct tmp; | ||
1653 | |||
1654 | if (!retinfo) | ||
1655 | return -EFAULT; | ||
1656 | memset(&tmp, 0, sizeof(tmp)); | ||
1657 | tmp.type = info->type; | ||
1658 | tmp.line = info->line; | ||
1659 | tmp.port = info->port; | ||
1660 | tmp.irq = info->irq; | ||
1661 | tmp.flags = info->flags; | ||
1662 | tmp.baud_base = info->baud_base; | ||
1663 | tmp.close_delay = info->close_delay; | ||
1664 | tmp.closing_wait = info->closing_wait; | ||
1665 | tmp.custom_divisor = info->custom_divisor; | ||
1666 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) | ||
1667 | return -EFAULT; | ||
1668 | return 0; | ||
1669 | } | ||
1670 | |||
1671 | static int set_serial_info(struct mac_serial * info, | ||
1672 | struct serial_struct __user * new_info) | ||
1673 | { | ||
1674 | struct serial_struct new_serial; | ||
1675 | struct mac_serial old_info; | ||
1676 | int retval = 0; | ||
1677 | |||
1678 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) | ||
1679 | return -EFAULT; | ||
1680 | old_info = *info; | ||
1681 | |||
1682 | if (!capable(CAP_SYS_ADMIN)) { | ||
1683 | if ((new_serial.baud_base != info->baud_base) || | ||
1684 | (new_serial.type != info->type) || | ||
1685 | (new_serial.close_delay != info->close_delay) || | ||
1686 | ((new_serial.flags & ~ZILOG_USR_MASK) != | ||
1687 | (info->flags & ~ZILOG_USR_MASK))) | ||
1688 | return -EPERM; | ||
1689 | info->flags = ((info->flags & ~ZILOG_USR_MASK) | | ||
1690 | (new_serial.flags & ZILOG_USR_MASK)); | ||
1691 | info->custom_divisor = new_serial.custom_divisor; | ||
1692 | goto check_and_exit; | ||
1693 | } | ||
1694 | |||
1695 | if (info->count > 1) | ||
1696 | return -EBUSY; | ||
1697 | |||
1698 | /* | ||
1699 | * OK, past this point, all the error checking has been done. | ||
1700 | * At this point, we start making changes..... | ||
1701 | */ | ||
1702 | |||
1703 | info->baud_base = new_serial.baud_base; | ||
1704 | info->flags = ((info->flags & ~ZILOG_FLAGS) | | ||
1705 | (new_serial.flags & ZILOG_FLAGS)); | ||
1706 | info->type = new_serial.type; | ||
1707 | info->close_delay = new_serial.close_delay; | ||
1708 | info->closing_wait = new_serial.closing_wait; | ||
1709 | |||
1710 | check_and_exit: | ||
1711 | if (info->flags & ZILOG_INITIALIZED) | ||
1712 | retval = setup_scc(info); | ||
1713 | return retval; | ||
1714 | } | ||
1715 | |||
1716 | /* | ||
1717 | * get_lsr_info - get line status register info | ||
1718 | * | ||
1719 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
1720 | * is emptied. On bus types like RS485, the transmitter must | ||
1721 | * release the bus after transmitting. This must be done when | ||
1722 | * the transmit shift register is empty, not be done when the | ||
1723 | * transmit holding register is empty. This functionality | ||
1724 | * allows an RS485 driver to be written in user space. | ||
1725 | */ | ||
1726 | static int get_lsr_info(struct mac_serial * info, unsigned int *value) | ||
1727 | { | ||
1728 | unsigned char status; | ||
1729 | unsigned long flags; | ||
1730 | |||
1731 | spin_lock_irqsave(&info->lock, flags); | ||
1732 | status = read_zsreg(info->zs_channel, 0); | ||
1733 | spin_unlock_irqrestore(&info->lock, flags); | ||
1734 | status = (status & Tx_BUF_EMP)? TIOCSER_TEMT: 0; | ||
1735 | return put_user(status,value); | ||
1736 | } | ||
1737 | |||
1738 | static int rs_tiocmget(struct tty_struct *tty, struct file *file) | ||
1739 | { | ||
1740 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
1741 | unsigned char control, status; | ||
1742 | unsigned long flags; | ||
1743 | |||
1744 | #ifdef CONFIG_KGDB | ||
1745 | if (info->kgdb_channel) | ||
1746 | return -ENODEV; | ||
1747 | #endif | ||
1748 | if (serial_paranoia_check(info, tty->name, __FUNCTION__)) | ||
1749 | return -ENODEV; | ||
1750 | |||
1751 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1752 | return -EIO; | ||
1753 | |||
1754 | spin_lock_irqsave(&info->lock, flags); | ||
1755 | control = info->curregs[5]; | ||
1756 | status = read_zsreg(info->zs_channel, 0); | ||
1757 | spin_unlock_irqrestore(&info->lock, flags); | ||
1758 | return ((control & RTS) ? TIOCM_RTS: 0) | ||
1759 | | ((control & DTR) ? TIOCM_DTR: 0) | ||
1760 | | ((status & DCD) ? TIOCM_CAR: 0) | ||
1761 | | ((status & CTS) ? 0: TIOCM_CTS); | ||
1762 | } | ||
1763 | |||
1764 | static int rs_tiocmset(struct tty_struct *tty, struct file *file, | ||
1765 | unsigned int set, unsigned int clear) | ||
1766 | { | ||
1767 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
1768 | unsigned int arg, bits; | ||
1769 | unsigned long flags; | ||
1770 | |||
1771 | #ifdef CONFIG_KGDB | ||
1772 | if (info->kgdb_channel) | ||
1773 | return -ENODEV; | ||
1774 | #endif | ||
1775 | if (serial_paranoia_check(info, tty->name, __FUNCTION__)) | ||
1776 | return -ENODEV; | ||
1777 | |||
1778 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1779 | return -EIO; | ||
1780 | |||
1781 | spin_lock_irqsave(&info->lock, flags); | ||
1782 | if (set & TIOCM_RTS) | ||
1783 | info->curregs[5] |= RTS; | ||
1784 | if (set & TIOCM_DTR) | ||
1785 | info->curregs[5] |= DTR; | ||
1786 | if (clear & TIOCM_RTS) | ||
1787 | info->curregs[5] &= ~RTS; | ||
1788 | if (clear & TIOCM_DTR) | ||
1789 | info->curregs[5] &= ~DTR; | ||
1790 | |||
1791 | info->pendregs[5] = info->curregs[5]; | ||
1792 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1793 | spin_unlock_irqrestore(&info->lock, flags); | ||
1794 | return 0; | ||
1795 | } | ||
1796 | |||
1797 | /* | ||
1798 | * rs_break - turn transmit break condition on/off | ||
1799 | */ | ||
1800 | static void rs_break(struct tty_struct *tty, int break_state) | ||
1801 | { | ||
1802 | struct mac_serial *info = (struct mac_serial *) tty->driver_data; | ||
1803 | unsigned long flags; | ||
1804 | |||
1805 | if (serial_paranoia_check(info, tty->name, "rs_break")) | ||
1806 | return; | ||
1807 | |||
1808 | spin_lock_irqsave(&info->lock, flags); | ||
1809 | if (break_state == -1) | ||
1810 | info->curregs[5] |= SND_BRK; | ||
1811 | else | ||
1812 | info->curregs[5] &= ~SND_BRK; | ||
1813 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1814 | spin_unlock_irqrestore(&info->lock, flags); | ||
1815 | } | ||
1816 | |||
1817 | static int rs_ioctl(struct tty_struct *tty, struct file * file, | ||
1818 | unsigned int cmd, unsigned long arg) | ||
1819 | { | ||
1820 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
1821 | |||
1822 | #ifdef CONFIG_KGDB | ||
1823 | if (info->kgdb_channel) | ||
1824 | return -ENODEV; | ||
1825 | #endif | ||
1826 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) | ||
1827 | return -ENODEV; | ||
1828 | |||
1829 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | ||
1830 | (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) { | ||
1831 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1832 | return -EIO; | ||
1833 | } | ||
1834 | |||
1835 | switch (cmd) { | ||
1836 | case TIOCGSERIAL: | ||
1837 | return get_serial_info(info, | ||
1838 | (struct serial_struct __user *) arg); | ||
1839 | case TIOCSSERIAL: | ||
1840 | return set_serial_info(info, | ||
1841 | (struct serial_struct __user *) arg); | ||
1842 | case TIOCSERGETLSR: /* Get line status register */ | ||
1843 | return get_lsr_info(info, (unsigned int *) arg); | ||
1844 | |||
1845 | case TIOCSERGSTRUCT: | ||
1846 | if (copy_to_user((struct mac_serial __user *) arg, | ||
1847 | info, sizeof(struct mac_serial))) | ||
1848 | return -EFAULT; | ||
1849 | return 0; | ||
1850 | |||
1851 | default: | ||
1852 | return -ENOIOCTLCMD; | ||
1853 | } | ||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) | ||
1858 | { | ||
1859 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1860 | int was_stopped; | ||
1861 | |||
1862 | if (tty->termios->c_cflag == old_termios->c_cflag) | ||
1863 | return; | ||
1864 | was_stopped = info->tx_stopped; | ||
1865 | |||
1866 | change_speed(info, old_termios); | ||
1867 | |||
1868 | if (was_stopped && !info->tx_stopped) { | ||
1869 | tty->hw_stopped = 0; | ||
1870 | rs_start(tty); | ||
1871 | } | ||
1872 | } | ||
1873 | |||
1874 | /* | ||
1875 | * ------------------------------------------------------------ | ||
1876 | * rs_close() | ||
1877 | * | ||
1878 | * This routine is called when the serial port gets closed. | ||
1879 | * Wait for the last remaining data to be sent. | ||
1880 | * ------------------------------------------------------------ | ||
1881 | */ | ||
1882 | static void rs_close(struct tty_struct *tty, struct file * filp) | ||
1883 | { | ||
1884 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
1885 | unsigned long flags; | ||
1886 | |||
1887 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) | ||
1888 | return; | ||
1889 | |||
1890 | spin_lock_irqsave(&info->lock, flags); | ||
1891 | |||
1892 | if (tty_hung_up_p(filp)) { | ||
1893 | spin_unlock_irqrestore(&info->lock, flags); | ||
1894 | return; | ||
1895 | } | ||
1896 | |||
1897 | OPNDBG("rs_close ttyS%d, count = %d\n", info->line, info->count); | ||
1898 | if ((tty->count == 1) && (info->count != 1)) { | ||
1899 | /* | ||
1900 | * Uh, oh. tty->count is 1, which means that the tty | ||
1901 | * structure will be freed. Info->count should always | ||
1902 | * be one in these conditions. If it's greater than | ||
1903 | * one, we've got real problems, since it means the | ||
1904 | * serial port won't be shutdown. | ||
1905 | */ | ||
1906 | printk(KERN_ERR "rs_close: bad serial port count; tty->count " | ||
1907 | "is 1, info->count is %d\n", info->count); | ||
1908 | info->count = 1; | ||
1909 | } | ||
1910 | if (--info->count < 0) { | ||
1911 | printk(KERN_ERR "rs_close: bad serial port count for " | ||
1912 | "ttyS%d: %d\n", info->line, info->count); | ||
1913 | info->count = 0; | ||
1914 | } | ||
1915 | if (info->count) { | ||
1916 | spin_unlock_irqrestore(&info->lock, flags); | ||
1917 | return; | ||
1918 | } | ||
1919 | info->flags |= ZILOG_CLOSING; | ||
1920 | /* | ||
1921 | * Now we wait for the transmit buffer to clear; and we notify | ||
1922 | * the line discipline to only process XON/XOFF characters. | ||
1923 | */ | ||
1924 | OPNDBG("waiting end of Tx... (timeout:%d)\n", info->closing_wait); | ||
1925 | tty->closing = 1; | ||
1926 | if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) { | ||
1927 | spin_unlock_irqrestore(&info->lock, flags); | ||
1928 | tty_wait_until_sent(tty, info->closing_wait); | ||
1929 | spin_lock_irqsave(&info->lock, flags); | ||
1930 | } | ||
1931 | |||
1932 | /* | ||
1933 | * At this point we stop accepting input. To do this, we | ||
1934 | * disable the receiver and receive interrupts. | ||
1935 | */ | ||
1936 | info->curregs[3] &= ~RxENABLE; | ||
1937 | info->pendregs[3] = info->curregs[3]; | ||
1938 | write_zsreg(info->zs_channel, 3, info->curregs[3]); | ||
1939 | info->curregs[1] &= ~(0x18); /* disable any rx ints */ | ||
1940 | info->pendregs[1] = info->curregs[1]; | ||
1941 | write_zsreg(info->zs_channel, 1, info->curregs[1]); | ||
1942 | ZS_CLEARFIFO(info->zs_channel); | ||
1943 | if (info->flags & ZILOG_INITIALIZED) { | ||
1944 | /* | ||
1945 | * Before we drop DTR, make sure the SCC transmitter | ||
1946 | * has completely drained. | ||
1947 | */ | ||
1948 | OPNDBG("waiting end of Rx...\n"); | ||
1949 | spin_unlock_irqrestore(&info->lock, flags); | ||
1950 | rs_wait_until_sent(tty, info->timeout); | ||
1951 | spin_lock_irqsave(&info->lock, flags); | ||
1952 | } | ||
1953 | |||
1954 | shutdown(info); | ||
1955 | /* restore flags now since shutdown() will have disabled this port's | ||
1956 | specific irqs */ | ||
1957 | spin_unlock_irqrestore(&info->lock, flags); | ||
1958 | |||
1959 | if (tty->driver->flush_buffer) | ||
1960 | tty->driver->flush_buffer(tty); | ||
1961 | tty_ldisc_flush(tty); | ||
1962 | tty->closing = 0; | ||
1963 | info->event = 0; | ||
1964 | info->tty = 0; | ||
1965 | |||
1966 | if (info->blocked_open) { | ||
1967 | if (info->close_delay) { | ||
1968 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | ||
1969 | } | ||
1970 | wake_up_interruptible(&info->open_wait); | ||
1971 | } | ||
1972 | info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING); | ||
1973 | wake_up_interruptible(&info->close_wait); | ||
1974 | } | ||
1975 | |||
1976 | /* | ||
1977 | * rs_wait_until_sent() --- wait until the transmitter is empty | ||
1978 | */ | ||
1979 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | ||
1980 | { | ||
1981 | struct mac_serial *info = (struct mac_serial *) tty->driver_data; | ||
1982 | unsigned long orig_jiffies, char_time; | ||
1983 | |||
1984 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) | ||
1985 | return; | ||
1986 | |||
1987 | /* printk("rs_wait_until_sent, timeout:%d, tty_stopped:%d, tx_stopped:%d\n", | ||
1988 | timeout, tty->stopped, info->tx_stopped); | ||
1989 | */ | ||
1990 | orig_jiffies = jiffies; | ||
1991 | /* | ||
1992 | * Set the check interval to be 1/5 of the estimated time to | ||
1993 | * send a single character, and make it at least 1. The check | ||
1994 | * interval should also be less than the timeout. | ||
1995 | */ | ||
1996 | if (info->timeout <= HZ/50) { | ||
1997 | printk(KERN_INFO "macserial: invalid info->timeout=%d\n", | ||
1998 | info->timeout); | ||
1999 | info->timeout = HZ/50+1; | ||
2000 | } | ||
2001 | |||
2002 | char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; | ||
2003 | char_time = char_time / 5; | ||
2004 | if (char_time > HZ) { | ||
2005 | printk(KERN_WARNING "macserial: char_time %ld >HZ !!!\n", | ||
2006 | char_time); | ||
2007 | char_time = 1; | ||
2008 | } else if (char_time == 0) | ||
2009 | char_time = 1; | ||
2010 | if (timeout) | ||
2011 | char_time = min_t(unsigned long, char_time, timeout); | ||
2012 | while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { | ||
2013 | msleep_interruptible(jiffies_to_msecs(char_time)); | ||
2014 | if (signal_pending(current)) | ||
2015 | break; | ||
2016 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | ||
2017 | break; | ||
2018 | } | ||
2019 | current->state = TASK_RUNNING; | ||
2020 | } | ||
2021 | |||
2022 | /* | ||
2023 | * rs_hangup() --- called by tty_hangup() when a hangup is signaled. | ||
2024 | */ | ||
2025 | static void rs_hangup(struct tty_struct *tty) | ||
2026 | { | ||
2027 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
2028 | |||
2029 | if (serial_paranoia_check(info, tty->name, "rs_hangup")) | ||
2030 | return; | ||
2031 | |||
2032 | rs_flush_buffer(tty); | ||
2033 | shutdown(info); | ||
2034 | info->event = 0; | ||
2035 | info->count = 0; | ||
2036 | info->flags &= ~ZILOG_NORMAL_ACTIVE; | ||
2037 | info->tty = 0; | ||
2038 | wake_up_interruptible(&info->open_wait); | ||
2039 | } | ||
2040 | |||
2041 | /* | ||
2042 | * ------------------------------------------------------------ | ||
2043 | * rs_open() and friends | ||
2044 | * ------------------------------------------------------------ | ||
2045 | */ | ||
2046 | static int block_til_ready(struct tty_struct *tty, struct file * filp, | ||
2047 | struct mac_serial *info) | ||
2048 | { | ||
2049 | DECLARE_WAITQUEUE(wait,current); | ||
2050 | int retval; | ||
2051 | int do_clocal = 0; | ||
2052 | |||
2053 | /* | ||
2054 | * If the device is in the middle of being closed, then block | ||
2055 | * until it's done, and then try again. | ||
2056 | */ | ||
2057 | if (info->flags & ZILOG_CLOSING) { | ||
2058 | interruptible_sleep_on(&info->close_wait); | ||
2059 | return -EAGAIN; | ||
2060 | } | ||
2061 | |||
2062 | /* | ||
2063 | * If non-blocking mode is set, or the port is not enabled, | ||
2064 | * then make the check up front and then exit. | ||
2065 | */ | ||
2066 | if ((filp->f_flags & O_NONBLOCK) || | ||
2067 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
2068 | info->flags |= ZILOG_NORMAL_ACTIVE; | ||
2069 | return 0; | ||
2070 | } | ||
2071 | |||
2072 | if (tty->termios->c_cflag & CLOCAL) | ||
2073 | do_clocal = 1; | ||
2074 | |||
2075 | /* | ||
2076 | * Block waiting for the carrier detect and the line to become | ||
2077 | * free (i.e., not in use by the callout). While we are in | ||
2078 | * this loop, info->count is dropped by one, so that | ||
2079 | * rs_close() knows when to free things. We restore it upon | ||
2080 | * exit, either normal or abnormal. | ||
2081 | */ | ||
2082 | retval = 0; | ||
2083 | add_wait_queue(&info->open_wait, &wait); | ||
2084 | OPNDBG("block_til_ready before block: ttyS%d, count = %d\n", | ||
2085 | info->line, info->count); | ||
2086 | spin_lock_irq(&info->lock); | ||
2087 | if (!tty_hung_up_p(filp)) | ||
2088 | info->count--; | ||
2089 | spin_unlock_irq(&info->lock); | ||
2090 | info->blocked_open++; | ||
2091 | while (1) { | ||
2092 | spin_lock_irq(&info->lock); | ||
2093 | if ((tty->termios->c_cflag & CBAUD) && | ||
2094 | !info->is_irda) | ||
2095 | zs_rtsdtr(info, 1); | ||
2096 | spin_unlock_irq(&info->lock); | ||
2097 | set_current_state(TASK_INTERRUPTIBLE); | ||
2098 | if (tty_hung_up_p(filp) || | ||
2099 | !(info->flags & ZILOG_INITIALIZED)) { | ||
2100 | retval = -EAGAIN; | ||
2101 | break; | ||
2102 | } | ||
2103 | if (!(info->flags & ZILOG_CLOSING) && | ||
2104 | (do_clocal || (read_zsreg(info->zs_channel, 0) & DCD))) | ||
2105 | break; | ||
2106 | if (signal_pending(current)) { | ||
2107 | retval = -ERESTARTSYS; | ||
2108 | break; | ||
2109 | } | ||
2110 | OPNDBG("block_til_ready blocking: ttyS%d, count = %d\n", | ||
2111 | info->line, info->count); | ||
2112 | schedule(); | ||
2113 | } | ||
2114 | current->state = TASK_RUNNING; | ||
2115 | remove_wait_queue(&info->open_wait, &wait); | ||
2116 | if (!tty_hung_up_p(filp)) | ||
2117 | info->count++; | ||
2118 | info->blocked_open--; | ||
2119 | OPNDBG("block_til_ready after blocking: ttyS%d, count = %d\n", | ||
2120 | info->line, info->count); | ||
2121 | if (retval) | ||
2122 | return retval; | ||
2123 | info->flags |= ZILOG_NORMAL_ACTIVE; | ||
2124 | return 0; | ||
2125 | } | ||
2126 | |||
2127 | /* | ||
2128 | * This routine is called whenever a serial port is opened. It | ||
2129 | * enables interrupts for a serial port, linking in its ZILOG structure into | ||
2130 | * the IRQ chain. It also performs the serial-specific | ||
2131 | * initialization for the tty structure. | ||
2132 | */ | ||
2133 | static int rs_open(struct tty_struct *tty, struct file * filp) | ||
2134 | { | ||
2135 | struct mac_serial *info; | ||
2136 | int retval, line; | ||
2137 | unsigned long page; | ||
2138 | |||
2139 | line = tty->index; | ||
2140 | if ((line < 0) || (line >= zs_channels_found)) { | ||
2141 | return -ENODEV; | ||
2142 | } | ||
2143 | info = zs_soft + line; | ||
2144 | |||
2145 | #ifdef CONFIG_KGDB | ||
2146 | if (info->kgdb_channel) { | ||
2147 | return -ENODEV; | ||
2148 | } | ||
2149 | #endif | ||
2150 | if (serial_paranoia_check(info, tty->name, "rs_open")) | ||
2151 | return -ENODEV; | ||
2152 | OPNDBG("rs_open %s, count = %d, tty=%p\n", tty->name, | ||
2153 | info->count, tty); | ||
2154 | |||
2155 | info->count++; | ||
2156 | tty->driver_data = info; | ||
2157 | info->tty = tty; | ||
2158 | |||
2159 | if (!tmp_buf) { | ||
2160 | page = get_zeroed_page(GFP_KERNEL); | ||
2161 | if (!page) | ||
2162 | return -ENOMEM; | ||
2163 | if (tmp_buf) | ||
2164 | free_page(page); | ||
2165 | else | ||
2166 | tmp_buf = (unsigned char *) page; | ||
2167 | } | ||
2168 | |||
2169 | /* | ||
2170 | * If the port is the middle of closing, bail out now | ||
2171 | */ | ||
2172 | if (tty_hung_up_p(filp) || | ||
2173 | (info->flags & ZILOG_CLOSING)) { | ||
2174 | if (info->flags & ZILOG_CLOSING) | ||
2175 | interruptible_sleep_on(&info->close_wait); | ||
2176 | return -EAGAIN; | ||
2177 | } | ||
2178 | |||
2179 | /* | ||
2180 | * Start up serial port | ||
2181 | */ | ||
2182 | |||
2183 | retval = startup(info); | ||
2184 | if (retval) | ||
2185 | return retval; | ||
2186 | |||
2187 | retval = block_til_ready(tty, filp, info); | ||
2188 | if (retval) { | ||
2189 | OPNDBG("rs_open returning after block_til_ready with %d\n", | ||
2190 | retval); | ||
2191 | return retval; | ||
2192 | } | ||
2193 | |||
2194 | #ifdef CONFIG_SERIAL_CONSOLE | ||
2195 | if (sercons.cflag && sercons.index == line) { | ||
2196 | tty->termios->c_cflag = sercons.cflag; | ||
2197 | sercons.cflag = 0; | ||
2198 | change_speed(info, 0); | ||
2199 | } | ||
2200 | #endif | ||
2201 | |||
2202 | OPNDBG("rs_open %s successful...\n", tty->name); | ||
2203 | return 0; | ||
2204 | } | ||
2205 | |||
2206 | /* Finally, routines used to initialize the serial driver. */ | ||
2207 | |||
2208 | static void show_serial_version(void) | ||
2209 | { | ||
2210 | printk(KERN_INFO "PowerMac Z8530 serial driver version " MACSERIAL_VERSION "\n"); | ||
2211 | } | ||
2212 | |||
2213 | /* | ||
2214 | * Initialize one channel, both the mac_serial and mac_zschannel | ||
2215 | * structs. We use the dev_node field of the mac_serial struct. | ||
2216 | */ | ||
2217 | static int | ||
2218 | chan_init(struct mac_serial *zss, struct mac_zschannel *zs_chan, | ||
2219 | struct mac_zschannel *zs_chan_a) | ||
2220 | { | ||
2221 | struct device_node *ch = zss->dev_node; | ||
2222 | char *conn; | ||
2223 | int len; | ||
2224 | struct slot_names_prop { | ||
2225 | int count; | ||
2226 | char name[1]; | ||
2227 | } *slots; | ||
2228 | |||
2229 | zss->irq = ch->intrs[0].line; | ||
2230 | zss->has_dma = 0; | ||
2231 | #if !defined(CONFIG_KGDB) && defined(SUPPORT_SERIAL_DMA) | ||
2232 | if (ch->n_addrs >= 3 && ch->n_intrs == 3) | ||
2233 | zss->has_dma = 1; | ||
2234 | #endif | ||
2235 | zss->dma_initted = 0; | ||
2236 | |||
2237 | zs_chan->control = (volatile unsigned char *) | ||
2238 | ioremap(ch->addrs[0].address, 0x1000); | ||
2239 | zs_chan->data = zs_chan->control + 0x10; | ||
2240 | spin_lock_init(&zs_chan->lock); | ||
2241 | zs_chan->parent = zss; | ||
2242 | zss->zs_channel = zs_chan; | ||
2243 | zss->zs_chan_a = zs_chan_a; | ||
2244 | |||
2245 | /* setup misc varariables */ | ||
2246 | zss->kgdb_channel = 0; | ||
2247 | |||
2248 | /* For now, we assume you either have a slot-names property | ||
2249 | * with "Modem" in it, or your channel is compatible with | ||
2250 | * "cobalt". Might need additional fixups | ||
2251 | */ | ||
2252 | zss->is_internal_modem = device_is_compatible(ch, "cobalt"); | ||
2253 | conn = get_property(ch, "AAPL,connector", &len); | ||
2254 | zss->is_irda = conn && (strcmp(conn, "infrared") == 0); | ||
2255 | zss->port_type = PMAC_SCC_ASYNC; | ||
2256 | /* 1999 Powerbook G3 has slot-names property instead */ | ||
2257 | slots = (struct slot_names_prop *)get_property(ch, "slot-names", &len); | ||
2258 | if (slots && slots->count > 0) { | ||
2259 | if (strcmp(slots->name, "IrDA") == 0) | ||
2260 | zss->is_irda = 1; | ||
2261 | else if (strcmp(slots->name, "Modem") == 0) | ||
2262 | zss->is_internal_modem = 1; | ||
2263 | } | ||
2264 | if (zss->is_irda) | ||
2265 | zss->port_type = PMAC_SCC_IRDA; | ||
2266 | if (zss->is_internal_modem) { | ||
2267 | struct device_node* i2c_modem = find_devices("i2c-modem"); | ||
2268 | if (i2c_modem) { | ||
2269 | char* mid = get_property(i2c_modem, "modem-id", NULL); | ||
2270 | if (mid) switch(*mid) { | ||
2271 | case 0x04 : | ||
2272 | case 0x05 : | ||
2273 | case 0x07 : | ||
2274 | case 0x08 : | ||
2275 | case 0x0b : | ||
2276 | case 0x0c : | ||
2277 | zss->port_type = PMAC_SCC_I2S1; | ||
2278 | } | ||
2279 | printk(KERN_INFO "macserial: i2c-modem detected, id: %d\n", | ||
2280 | mid ? (*mid) : 0); | ||
2281 | } else { | ||
2282 | printk(KERN_INFO "macserial: serial modem detected\n"); | ||
2283 | } | ||
2284 | } | ||
2285 | |||
2286 | while (zss->has_dma) { | ||
2287 | zss->dma_priv = NULL; | ||
2288 | /* it seems that the last two addresses are the | ||
2289 | DMA controllers */ | ||
2290 | zss->tx_dma = (volatile struct dbdma_regs *) | ||
2291 | ioremap(ch->addrs[ch->n_addrs - 2].address, 0x100); | ||
2292 | zss->rx = (volatile struct mac_dma *) | ||
2293 | ioremap(ch->addrs[ch->n_addrs - 1].address, 0x100); | ||
2294 | zss->tx_dma_irq = ch->intrs[1].line; | ||
2295 | zss->rx_dma_irq = ch->intrs[2].line; | ||
2296 | spin_lock_init(&zss->rx_dma_lock); | ||
2297 | break; | ||
2298 | } | ||
2299 | |||
2300 | init_timer(&zss->powerup_timer); | ||
2301 | zss->powerup_timer.function = powerup_done; | ||
2302 | zss->powerup_timer.data = (unsigned long) zss; | ||
2303 | return 0; | ||
2304 | } | ||
2305 | |||
2306 | /* | ||
2307 | * /proc fs routines. TODO: Add status lines & error stats | ||
2308 | */ | ||
2309 | static inline int | ||
2310 | line_info(char *buf, struct mac_serial *info) | ||
2311 | { | ||
2312 | int ret=0; | ||
2313 | unsigned char* connector; | ||
2314 | int lenp; | ||
2315 | |||
2316 | ret += sprintf(buf, "%d: port:0x%X irq:%d", info->line, info->port, info->irq); | ||
2317 | |||
2318 | connector = get_property(info->dev_node, "AAPL,connector", &lenp); | ||
2319 | if (connector) | ||
2320 | ret+=sprintf(buf+ret," con:%s ", connector); | ||
2321 | if (info->is_internal_modem) { | ||
2322 | if (!connector) | ||
2323 | ret+=sprintf(buf+ret," con:"); | ||
2324 | ret+=sprintf(buf+ret,"%s", " (internal modem)"); | ||
2325 | } | ||
2326 | if (info->is_irda) { | ||
2327 | if (!connector) | ||
2328 | ret+=sprintf(buf+ret," con:"); | ||
2329 | ret+=sprintf(buf+ret,"%s", " (IrDA)"); | ||
2330 | } | ||
2331 | ret+=sprintf(buf+ret,"\n"); | ||
2332 | |||
2333 | return ret; | ||
2334 | } | ||
2335 | |||
2336 | int macserial_read_proc(char *page, char **start, off_t off, int count, | ||
2337 | int *eof, void *data) | ||
2338 | { | ||
2339 | int l, len = 0; | ||
2340 | off_t begin = 0; | ||
2341 | struct mac_serial *info; | ||
2342 | |||
2343 | len += sprintf(page, "serinfo:1.0 driver:" MACSERIAL_VERSION "\n"); | ||
2344 | for (info = zs_chain; info && len < 4000; info = info->zs_next) { | ||
2345 | l = line_info(page + len, info); | ||
2346 | len += l; | ||
2347 | if (len+begin > off+count) | ||
2348 | goto done; | ||
2349 | if (len+begin < off) { | ||
2350 | begin += len; | ||
2351 | len = 0; | ||
2352 | } | ||
2353 | } | ||
2354 | *eof = 1; | ||
2355 | done: | ||
2356 | if (off >= len+begin) | ||
2357 | return 0; | ||
2358 | *start = page + (off-begin); | ||
2359 | return ((count < begin+len-off) ? count : begin+len-off); | ||
2360 | } | ||
2361 | |||
2362 | /* Ask the PROM how many Z8530s we have and initialize their zs_channels */ | ||
2363 | static void | ||
2364 | probe_sccs(void) | ||
2365 | { | ||
2366 | struct device_node *dev, *ch; | ||
2367 | struct mac_serial **pp; | ||
2368 | int n, chip, nchan; | ||
2369 | struct mac_zschannel *zs_chan; | ||
2370 | int chan_a_index; | ||
2371 | |||
2372 | n = 0; | ||
2373 | pp = &zs_chain; | ||
2374 | zs_chan = zs_channels; | ||
2375 | for (dev = find_devices("escc"); dev != 0; dev = dev->next) { | ||
2376 | nchan = 0; | ||
2377 | chip = n; | ||
2378 | if (n >= NUM_CHANNELS) { | ||
2379 | printk(KERN_WARNING "Sorry, can't use %s: no more " | ||
2380 | "channels\n", dev->full_name); | ||
2381 | continue; | ||
2382 | } | ||
2383 | chan_a_index = 0; | ||
2384 | for (ch = dev->child; ch != 0; ch = ch->sibling) { | ||
2385 | if (nchan >= 2) { | ||
2386 | printk(KERN_WARNING "SCC: Only 2 channels per " | ||
2387 | "chip are supported\n"); | ||
2388 | break; | ||
2389 | } | ||
2390 | if (ch->n_addrs < 1 || (ch ->n_intrs < 1)) { | ||
2391 | printk("Can't use %s: %d addrs %d intrs\n", | ||
2392 | ch->full_name, ch->n_addrs, ch->n_intrs); | ||
2393 | continue; | ||
2394 | } | ||
2395 | |||
2396 | /* The channel with the higher address | ||
2397 | will be the A side. */ | ||
2398 | if (nchan > 0 && | ||
2399 | ch->addrs[0].address | ||
2400 | > zs_soft[n-1].dev_node->addrs[0].address) | ||
2401 | chan_a_index = 1; | ||
2402 | |||
2403 | /* minimal initialization for now */ | ||
2404 | zs_soft[n].dev_node = ch; | ||
2405 | *pp = &zs_soft[n]; | ||
2406 | pp = &zs_soft[n].zs_next; | ||
2407 | ++nchan; | ||
2408 | ++n; | ||
2409 | } | ||
2410 | if (nchan == 0) | ||
2411 | continue; | ||
2412 | |||
2413 | /* set up A side */ | ||
2414 | if (chan_init(&zs_soft[chip + chan_a_index], zs_chan, zs_chan)) | ||
2415 | continue; | ||
2416 | ++zs_chan; | ||
2417 | |||
2418 | /* set up B side, if it exists */ | ||
2419 | if (nchan > 1) | ||
2420 | if (chan_init(&zs_soft[chip + 1 - chan_a_index], | ||
2421 | zs_chan, zs_chan - 1)) | ||
2422 | continue; | ||
2423 | ++zs_chan; | ||
2424 | } | ||
2425 | *pp = 0; | ||
2426 | |||
2427 | zs_channels_found = n; | ||
2428 | #ifdef CONFIG_PMAC_PBOOK | ||
2429 | if (n) | ||
2430 | pmu_register_sleep_notifier(&serial_sleep_notifier); | ||
2431 | #endif /* CONFIG_PMAC_PBOOK */ | ||
2432 | } | ||
2433 | |||
2434 | static struct tty_operations serial_ops = { | ||
2435 | .open = rs_open, | ||
2436 | .close = rs_close, | ||
2437 | .write = rs_write, | ||
2438 | .flush_chars = rs_flush_chars, | ||
2439 | .write_room = rs_write_room, | ||
2440 | .chars_in_buffer = rs_chars_in_buffer, | ||
2441 | .flush_buffer = rs_flush_buffer, | ||
2442 | .ioctl = rs_ioctl, | ||
2443 | .throttle = rs_throttle, | ||
2444 | .unthrottle = rs_unthrottle, | ||
2445 | .set_termios = rs_set_termios, | ||
2446 | .stop = rs_stop, | ||
2447 | .start = rs_start, | ||
2448 | .hangup = rs_hangup, | ||
2449 | .break_ctl = rs_break, | ||
2450 | .wait_until_sent = rs_wait_until_sent, | ||
2451 | .read_proc = macserial_read_proc, | ||
2452 | .tiocmget = rs_tiocmget, | ||
2453 | .tiocmset = rs_tiocmset, | ||
2454 | }; | ||
2455 | |||
2456 | static int macserial_init(void) | ||
2457 | { | ||
2458 | int channel, i; | ||
2459 | struct mac_serial *info; | ||
2460 | |||
2461 | /* Find out how many Z8530 SCCs we have */ | ||
2462 | if (zs_chain == 0) | ||
2463 | probe_sccs(); | ||
2464 | |||
2465 | serial_driver = alloc_tty_driver(zs_channels_found); | ||
2466 | if (!serial_driver) | ||
2467 | return -ENOMEM; | ||
2468 | |||
2469 | /* XXX assume it's a powerbook if we have a via-pmu | ||
2470 | * | ||
2471 | * This is OK for core99 machines as well. | ||
2472 | */ | ||
2473 | is_powerbook = find_devices("via-pmu") != 0; | ||
2474 | |||
2475 | /* Register the interrupt handler for each one | ||
2476 | * We also request the OF resources here as probe_sccs() | ||
2477 | * might be called too early for that | ||
2478 | */ | ||
2479 | for (i = 0; i < zs_channels_found; ++i) { | ||
2480 | struct device_node* ch = zs_soft[i].dev_node; | ||
2481 | if (!request_OF_resource(ch, 0, NULL)) { | ||
2482 | printk(KERN_ERR "macserial: can't request IO resource !\n"); | ||
2483 | put_tty_driver(serial_driver); | ||
2484 | return -ENODEV; | ||
2485 | } | ||
2486 | if (zs_soft[i].has_dma) { | ||
2487 | if (!request_OF_resource(ch, ch->n_addrs - 2, " (tx dma)")) { | ||
2488 | printk(KERN_ERR "macserial: can't request TX DMA resource !\n"); | ||
2489 | zs_soft[i].has_dma = 0; | ||
2490 | goto no_dma; | ||
2491 | } | ||
2492 | if (!request_OF_resource(ch, ch->n_addrs - 1, " (rx dma)")) { | ||
2493 | release_OF_resource(ch, ch->n_addrs - 2); | ||
2494 | printk(KERN_ERR "macserial: can't request RX DMA resource !\n"); | ||
2495 | zs_soft[i].has_dma = 0; | ||
2496 | goto no_dma; | ||
2497 | } | ||
2498 | if (request_irq(zs_soft[i].tx_dma_irq, rs_txdma_irq, 0, | ||
2499 | "SCC-txdma", &zs_soft[i])) | ||
2500 | printk(KERN_ERR "macserial: can't get irq %d\n", | ||
2501 | zs_soft[i].tx_dma_irq); | ||
2502 | disable_irq(zs_soft[i].tx_dma_irq); | ||
2503 | if (request_irq(zs_soft[i].rx_dma_irq, rs_rxdma_irq, 0, | ||
2504 | "SCC-rxdma", &zs_soft[i])) | ||
2505 | printk(KERN_ERR "macserial: can't get irq %d\n", | ||
2506 | zs_soft[i].rx_dma_irq); | ||
2507 | disable_irq(zs_soft[i].rx_dma_irq); | ||
2508 | } | ||
2509 | no_dma: | ||
2510 | if (request_irq(zs_soft[i].irq, rs_interrupt, 0, | ||
2511 | "SCC", &zs_soft[i])) | ||
2512 | printk(KERN_ERR "macserial: can't get irq %d\n", | ||
2513 | zs_soft[i].irq); | ||
2514 | disable_irq(zs_soft[i].irq); | ||
2515 | } | ||
2516 | |||
2517 | show_serial_version(); | ||
2518 | |||
2519 | /* Initialize the tty_driver structure */ | ||
2520 | /* Not all of this is exactly right for us. */ | ||
2521 | |||
2522 | serial_driver->owner = THIS_MODULE; | ||
2523 | serial_driver->driver_name = "macserial"; | ||
2524 | serial_driver->devfs_name = "tts/"; | ||
2525 | serial_driver->name = "ttyS"; | ||
2526 | serial_driver->major = TTY_MAJOR; | ||
2527 | serial_driver->minor_start = 64; | ||
2528 | serial_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2529 | serial_driver->subtype = SERIAL_TYPE_NORMAL; | ||
2530 | serial_driver->init_termios = tty_std_termios; | ||
2531 | serial_driver->init_termios.c_cflag = | ||
2532 | B38400 | CS8 | CREAD | HUPCL | CLOCAL; | ||
2533 | serial_driver->flags = TTY_DRIVER_REAL_RAW; | ||
2534 | tty_set_operations(serial_driver, &serial_ops); | ||
2535 | |||
2536 | if (tty_register_driver(serial_driver)) | ||
2537 | printk(KERN_ERR "Error: couldn't register serial driver\n"); | ||
2538 | |||
2539 | for (channel = 0; channel < zs_channels_found; ++channel) { | ||
2540 | #ifdef CONFIG_KGDB | ||
2541 | if (zs_soft[channel].kgdb_channel) { | ||
2542 | kgdb_interruptible(1); | ||
2543 | continue; | ||
2544 | } | ||
2545 | #endif | ||
2546 | zs_soft[channel].clk_divisor = 16; | ||
2547 | /* -- we are not sure the SCC is powered ON at this point | ||
2548 | zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); | ||
2549 | */ | ||
2550 | zs_soft[channel].zs_baud = 38400; | ||
2551 | |||
2552 | /* If console serial line, then enable interrupts. */ | ||
2553 | if (zs_soft[channel].is_cons) { | ||
2554 | printk(KERN_INFO "macserial: console line, enabling " | ||
2555 | "interrupt %d\n", zs_soft[channel].irq); | ||
2556 | panic("macserial: console not supported yet !"); | ||
2557 | write_zsreg(zs_soft[channel].zs_channel, R1, | ||
2558 | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); | ||
2559 | write_zsreg(zs_soft[channel].zs_channel, R9, | ||
2560 | (NV | MIE)); | ||
2561 | } | ||
2562 | } | ||
2563 | |||
2564 | for (info = zs_chain, i = 0; info; info = info->zs_next, i++) | ||
2565 | { | ||
2566 | unsigned char* connector; | ||
2567 | int lenp; | ||
2568 | |||
2569 | #ifdef CONFIG_KGDB | ||
2570 | if (info->kgdb_channel) { | ||
2571 | continue; | ||
2572 | } | ||
2573 | #endif | ||
2574 | info->magic = SERIAL_MAGIC; | ||
2575 | info->port = (int) info->zs_channel->control; | ||
2576 | info->line = i; | ||
2577 | info->tty = 0; | ||
2578 | info->custom_divisor = 16; | ||
2579 | info->timeout = 0; | ||
2580 | info->close_delay = 50; | ||
2581 | info->closing_wait = 3000; | ||
2582 | info->x_char = 0; | ||
2583 | info->event = 0; | ||
2584 | info->count = 0; | ||
2585 | info->blocked_open = 0; | ||
2586 | INIT_WORK(&info->tqueue, do_softint, info); | ||
2587 | spin_lock_init(&info->lock); | ||
2588 | init_waitqueue_head(&info->open_wait); | ||
2589 | init_waitqueue_head(&info->close_wait); | ||
2590 | info->timeout = HZ; | ||
2591 | printk(KERN_INFO "tty%02d at 0x%08x (irq = %d)", info->line, | ||
2592 | info->port, info->irq); | ||
2593 | printk(" is a Z8530 ESCC"); | ||
2594 | connector = get_property(info->dev_node, "AAPL,connector", &lenp); | ||
2595 | if (connector) | ||
2596 | printk(", port = %s", connector); | ||
2597 | if (info->is_internal_modem) | ||
2598 | printk(" (internal modem)"); | ||
2599 | if (info->is_irda) | ||
2600 | printk(" (IrDA)"); | ||
2601 | printk("\n"); | ||
2602 | } | ||
2603 | tmp_buf = 0; | ||
2604 | |||
2605 | return 0; | ||
2606 | } | ||
2607 | |||
2608 | void macserial_cleanup(void) | ||
2609 | { | ||
2610 | int i; | ||
2611 | unsigned long flags; | ||
2612 | struct mac_serial *info; | ||
2613 | |||
2614 | for (info = zs_chain, i = 0; info; info = info->zs_next, i++) | ||
2615 | set_scc_power(info, 0); | ||
2616 | spin_lock_irqsave(&info->lock, flags); | ||
2617 | for (i = 0; i < zs_channels_found; ++i) { | ||
2618 | free_irq(zs_soft[i].irq, &zs_soft[i]); | ||
2619 | if (zs_soft[i].has_dma) { | ||
2620 | free_irq(zs_soft[i].tx_dma_irq, &zs_soft[i]); | ||
2621 | free_irq(zs_soft[i].rx_dma_irq, &zs_soft[i]); | ||
2622 | } | ||
2623 | release_OF_resource(zs_soft[i].dev_node, 0); | ||
2624 | if (zs_soft[i].has_dma) { | ||
2625 | struct device_node* ch = zs_soft[i].dev_node; | ||
2626 | release_OF_resource(ch, ch->n_addrs - 2); | ||
2627 | release_OF_resource(ch, ch->n_addrs - 1); | ||
2628 | } | ||
2629 | } | ||
2630 | spin_unlock_irqrestore(&info->lock, flags); | ||
2631 | tty_unregister_driver(serial_driver); | ||
2632 | put_tty_driver(serial_driver); | ||
2633 | |||
2634 | if (tmp_buf) { | ||
2635 | free_page((unsigned long) tmp_buf); | ||
2636 | tmp_buf = 0; | ||
2637 | } | ||
2638 | |||
2639 | #ifdef CONFIG_PMAC_PBOOK | ||
2640 | if (zs_channels_found) | ||
2641 | pmu_unregister_sleep_notifier(&serial_sleep_notifier); | ||
2642 | #endif /* CONFIG_PMAC_PBOOK */ | ||
2643 | } | ||
2644 | |||
2645 | module_init(macserial_init); | ||
2646 | module_exit(macserial_cleanup); | ||
2647 | MODULE_LICENSE("GPL"); | ||
2648 | |||
2649 | #if 0 | ||
2650 | /* | ||
2651 | * register_serial and unregister_serial allows for serial ports to be | ||
2652 | * configured at run-time, to support PCMCIA modems. | ||
2653 | */ | ||
2654 | /* PowerMac: Unused at this time, just here to make things link. */ | ||
2655 | int register_serial(struct serial_struct *req) | ||
2656 | { | ||
2657 | return -1; | ||
2658 | } | ||
2659 | |||
2660 | void unregister_serial(int line) | ||
2661 | { | ||
2662 | return; | ||
2663 | } | ||
2664 | #endif | ||
2665 | |||
2666 | /* | ||
2667 | * ------------------------------------------------------------ | ||
2668 | * Serial console driver | ||
2669 | * ------------------------------------------------------------ | ||
2670 | */ | ||
2671 | #ifdef CONFIG_SERIAL_CONSOLE | ||
2672 | |||
2673 | /* | ||
2674 | * Print a string to the serial port trying not to disturb | ||
2675 | * any possible real use of the port... | ||
2676 | */ | ||
2677 | static void serial_console_write(struct console *co, const char *s, | ||
2678 | unsigned count) | ||
2679 | { | ||
2680 | struct mac_serial *info = zs_soft + co->index; | ||
2681 | int i; | ||
2682 | |||
2683 | /* Turn of interrupts and enable the transmitter. */ | ||
2684 | write_zsreg(info->zs_channel, R1, info->curregs[1] & ~TxINT_ENAB); | ||
2685 | write_zsreg(info->zs_channel, R5, info->curregs[5] | TxENAB | RTS | DTR); | ||
2686 | |||
2687 | for (i=0; i<count; i++) { | ||
2688 | /* Wait for the transmit buffer to empty. */ | ||
2689 | while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) { | ||
2690 | eieio(); | ||
2691 | } | ||
2692 | |||
2693 | write_zsdata(info->zs_channel, s[i]); | ||
2694 | if (s[i] == 10) { | ||
2695 | while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) | ||
2696 | == 0) | ||
2697 | eieio(); | ||
2698 | |||
2699 | write_zsdata(info->zs_channel, 13); | ||
2700 | } | ||
2701 | } | ||
2702 | |||
2703 | /* Restore the values in the registers. */ | ||
2704 | write_zsreg(info->zs_channel, R1, info->curregs[1]); | ||
2705 | /* Don't disable the transmitter. */ | ||
2706 | } | ||
2707 | |||
2708 | static struct tty_driver *serial_driver; | ||
2709 | |||
2710 | static struct tty_driver *serial_console_device(struct console *c, int *index) | ||
2711 | { | ||
2712 | *index = c->index; | ||
2713 | return serial_driver; | ||
2714 | } | ||
2715 | |||
2716 | /* | ||
2717 | * Setup initial baud/bits/parity. We do two things here: | ||
2718 | * - construct a cflag setting for the first rs_open() | ||
2719 | * - initialize the serial port | ||
2720 | * Return non-zero if we didn't find a serial port. | ||
2721 | */ | ||
2722 | static int __init serial_console_setup(struct console *co, char *options) | ||
2723 | { | ||
2724 | struct mac_serial *info; | ||
2725 | int baud = 38400; | ||
2726 | int bits = 8; | ||
2727 | int parity = 'n'; | ||
2728 | int cflag = CREAD | HUPCL | CLOCAL; | ||
2729 | int brg; | ||
2730 | char *s; | ||
2731 | long flags; | ||
2732 | |||
2733 | /* Find out how many Z8530 SCCs we have */ | ||
2734 | if (zs_chain == 0) | ||
2735 | probe_sccs(); | ||
2736 | |||
2737 | if (zs_chain == 0) | ||
2738 | return -1; | ||
2739 | |||
2740 | /* Do we have the device asked for? */ | ||
2741 | if (co->index >= zs_channels_found) | ||
2742 | return -1; | ||
2743 | info = zs_soft + co->index; | ||
2744 | |||
2745 | set_scc_power(info, 1); | ||
2746 | |||
2747 | /* Reset the channel */ | ||
2748 | write_zsreg(info->zs_channel, R9, CHRA); | ||
2749 | |||
2750 | if (options) { | ||
2751 | baud = simple_strtoul(options, NULL, 10); | ||
2752 | s = options; | ||
2753 | while(*s >= '0' && *s <= '9') | ||
2754 | s++; | ||
2755 | if (*s) | ||
2756 | parity = *s++; | ||
2757 | if (*s) | ||
2758 | bits = *s - '0'; | ||
2759 | } | ||
2760 | |||
2761 | /* | ||
2762 | * Now construct a cflag setting. | ||
2763 | */ | ||
2764 | switch(baud) { | ||
2765 | case 1200: | ||
2766 | cflag |= B1200; | ||
2767 | break; | ||
2768 | case 2400: | ||
2769 | cflag |= B2400; | ||
2770 | break; | ||
2771 | case 4800: | ||
2772 | cflag |= B4800; | ||
2773 | break; | ||
2774 | case 9600: | ||
2775 | cflag |= B9600; | ||
2776 | break; | ||
2777 | case 19200: | ||
2778 | cflag |= B19200; | ||
2779 | break; | ||
2780 | case 57600: | ||
2781 | cflag |= B57600; | ||
2782 | break; | ||
2783 | case 115200: | ||
2784 | cflag |= B115200; | ||
2785 | break; | ||
2786 | case 38400: | ||
2787 | default: | ||
2788 | cflag |= B38400; | ||
2789 | break; | ||
2790 | } | ||
2791 | switch(bits) { | ||
2792 | case 7: | ||
2793 | cflag |= CS7; | ||
2794 | break; | ||
2795 | default: | ||
2796 | case 8: | ||
2797 | cflag |= CS8; | ||
2798 | break; | ||
2799 | } | ||
2800 | switch(parity) { | ||
2801 | case 'o': case 'O': | ||
2802 | cflag |= PARENB | PARODD; | ||
2803 | break; | ||
2804 | case 'e': case 'E': | ||
2805 | cflag |= PARENB; | ||
2806 | break; | ||
2807 | } | ||
2808 | co->cflag = cflag; | ||
2809 | |||
2810 | spin_lock_irqsave(&info->lock, flags); | ||
2811 | memset(info->curregs, 0, sizeof(info->curregs)); | ||
2812 | |||
2813 | info->zs_baud = baud; | ||
2814 | info->clk_divisor = 16; | ||
2815 | switch (info->zs_baud) { | ||
2816 | case ZS_CLOCK/16: /* 230400 */ | ||
2817 | info->curregs[4] = X16CLK; | ||
2818 | info->curregs[11] = 0; | ||
2819 | break; | ||
2820 | case ZS_CLOCK/32: /* 115200 */ | ||
2821 | info->curregs[4] = X32CLK; | ||
2822 | info->curregs[11] = 0; | ||
2823 | break; | ||
2824 | default: | ||
2825 | info->curregs[4] = X16CLK; | ||
2826 | info->curregs[11] = TCBR | RCBR; | ||
2827 | brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor); | ||
2828 | info->curregs[12] = (brg & 255); | ||
2829 | info->curregs[13] = ((brg >> 8) & 255); | ||
2830 | info->curregs[14] = BRENABL; | ||
2831 | } | ||
2832 | |||
2833 | /* byte size and parity */ | ||
2834 | info->curregs[3] &= ~RxNBITS_MASK; | ||
2835 | info->curregs[5] &= ~TxNBITS_MASK; | ||
2836 | switch (cflag & CSIZE) { | ||
2837 | case CS5: | ||
2838 | info->curregs[3] |= Rx5; | ||
2839 | info->curregs[5] |= Tx5; | ||
2840 | break; | ||
2841 | case CS6: | ||
2842 | info->curregs[3] |= Rx6; | ||
2843 | info->curregs[5] |= Tx6; | ||
2844 | break; | ||
2845 | case CS7: | ||
2846 | info->curregs[3] |= Rx7; | ||
2847 | info->curregs[5] |= Tx7; | ||
2848 | break; | ||
2849 | case CS8: | ||
2850 | default: /* defaults to 8 bits */ | ||
2851 | info->curregs[3] |= Rx8; | ||
2852 | info->curregs[5] |= Tx8; | ||
2853 | break; | ||
2854 | } | ||
2855 | info->curregs[5] |= TxENAB | RTS | DTR; | ||
2856 | info->pendregs[3] = info->curregs[3]; | ||
2857 | info->pendregs[5] = info->curregs[5]; | ||
2858 | |||
2859 | info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); | ||
2860 | if (cflag & CSTOPB) { | ||
2861 | info->curregs[4] |= SB2; | ||
2862 | } else { | ||
2863 | info->curregs[4] |= SB1; | ||
2864 | } | ||
2865 | if (cflag & PARENB) { | ||
2866 | info->curregs[4] |= PAR_ENA; | ||
2867 | if (!(cflag & PARODD)) { | ||
2868 | info->curregs[4] |= PAR_EVEN; | ||
2869 | } | ||
2870 | } | ||
2871 | info->pendregs[4] = info->curregs[4]; | ||
2872 | |||
2873 | if (!(cflag & CLOCAL)) { | ||
2874 | if (!(info->curregs[15] & DCDIE)) | ||
2875 | info->read_reg_zero = read_zsreg(info->zs_channel, 0); | ||
2876 | info->curregs[15] |= DCDIE; | ||
2877 | } else | ||
2878 | info->curregs[15] &= ~DCDIE; | ||
2879 | if (cflag & CRTSCTS) { | ||
2880 | info->curregs[15] |= CTSIE; | ||
2881 | if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) | ||
2882 | info->tx_stopped = 1; | ||
2883 | } else { | ||
2884 | info->curregs[15] &= ~CTSIE; | ||
2885 | info->tx_stopped = 0; | ||
2886 | } | ||
2887 | info->pendregs[15] = info->curregs[15]; | ||
2888 | |||
2889 | /* Load up the new values */ | ||
2890 | load_zsregs(info->zs_channel, info->curregs); | ||
2891 | |||
2892 | spin_unlock_irqrestore(&info->lock, flags); | ||
2893 | |||
2894 | return 0; | ||
2895 | } | ||
2896 | |||
2897 | static struct console sercons = { | ||
2898 | .name = "ttyS", | ||
2899 | .write = serial_console_write, | ||
2900 | .device = serial_console_device, | ||
2901 | .setup = serial_console_setup, | ||
2902 | .flags = CON_PRINTBUFFER, | ||
2903 | .index = -1, | ||
2904 | }; | ||
2905 | |||
2906 | /* | ||
2907 | * Register console. | ||
2908 | */ | ||
2909 | static void __init mac_scc_console_init(void) | ||
2910 | { | ||
2911 | register_console(&sercons); | ||
2912 | } | ||
2913 | console_initcall(mac_scc_console_init); | ||
2914 | |||
2915 | #endif /* ifdef CONFIG_SERIAL_CONSOLE */ | ||
2916 | |||
2917 | #ifdef CONFIG_KGDB | ||
2918 | /* These are for receiving and sending characters under the kgdb | ||
2919 | * source level kernel debugger. | ||
2920 | */ | ||
2921 | void putDebugChar(char kgdb_char) | ||
2922 | { | ||
2923 | struct mac_zschannel *chan = zs_kgdbchan; | ||
2924 | while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0) | ||
2925 | udelay(5); | ||
2926 | write_zsdata(chan, kgdb_char); | ||
2927 | } | ||
2928 | |||
2929 | char getDebugChar(void) | ||
2930 | { | ||
2931 | struct mac_zschannel *chan = zs_kgdbchan; | ||
2932 | while((read_zsreg(chan, 0) & Rx_CH_AV) == 0) | ||
2933 | eieio(); /*barrier();*/ | ||
2934 | return read_zsdata(chan); | ||
2935 | } | ||
2936 | |||
2937 | void kgdb_interruptible(int yes) | ||
2938 | { | ||
2939 | struct mac_zschannel *chan = zs_kgdbchan; | ||
2940 | int one, nine; | ||
2941 | nine = read_zsreg(chan, 9); | ||
2942 | if (yes == 1) { | ||
2943 | one = EXT_INT_ENAB|INT_ALL_Rx; | ||
2944 | nine |= MIE; | ||
2945 | printk("turning serial ints on\n"); | ||
2946 | } else { | ||
2947 | one = RxINT_DISAB; | ||
2948 | nine &= ~MIE; | ||
2949 | printk("turning serial ints off\n"); | ||
2950 | } | ||
2951 | write_zsreg(chan, 1, one); | ||
2952 | write_zsreg(chan, 9, nine); | ||
2953 | } | ||
2954 | |||
2955 | /* This sets up the serial port we're using, and turns on | ||
2956 | * interrupts for that channel, so kgdb is usable once we're done. | ||
2957 | */ | ||
2958 | static inline void kgdb_chaninit(struct mac_zschannel *ms, int intson, int bps) | ||
2959 | { | ||
2960 | int brg; | ||
2961 | int i, x; | ||
2962 | volatile char *sccc = ms->control; | ||
2963 | brg = BPS_TO_BRG(bps, ZS_CLOCK/16); | ||
2964 | printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg); | ||
2965 | for (i = 20000; i != 0; --i) { | ||
2966 | x = *sccc; eieio(); | ||
2967 | } | ||
2968 | for (i = 0; i < sizeof(scc_inittab); ++i) { | ||
2969 | write_zsreg(ms, scc_inittab[i], scc_inittab[i+1]); | ||
2970 | i++; | ||
2971 | } | ||
2972 | } | ||
2973 | |||
2974 | /* This is called at boot time to prime the kgdb serial debugging | ||
2975 | * serial line. The 'tty_num' argument is 0 for /dev/ttya and 1 | ||
2976 | * for /dev/ttyb which is determined in setup_arch() from the | ||
2977 | * boot command line flags. | ||
2978 | * XXX at the moment probably only channel A will work | ||
2979 | */ | ||
2980 | void __init zs_kgdb_hook(int tty_num) | ||
2981 | { | ||
2982 | /* Find out how many Z8530 SCCs we have */ | ||
2983 | if (zs_chain == 0) | ||
2984 | probe_sccs(); | ||
2985 | |||
2986 | set_scc_power(&zs_soft[tty_num], 1); | ||
2987 | |||
2988 | zs_kgdbchan = zs_soft[tty_num].zs_channel; | ||
2989 | zs_soft[tty_num].change_needed = 0; | ||
2990 | zs_soft[tty_num].clk_divisor = 16; | ||
2991 | zs_soft[tty_num].zs_baud = 38400; | ||
2992 | zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */ | ||
2993 | |||
2994 | /* Turn on transmitter/receiver at 8-bits/char */ | ||
2995 | kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400); | ||
2996 | printk("KGDB: on channel %d initialized\n", tty_num); | ||
2997 | set_debug_traps(); /* init stub */ | ||
2998 | } | ||
2999 | #endif /* ifdef CONFIG_KGDB */ | ||
3000 | |||
3001 | #ifdef CONFIG_PMAC_PBOOK | ||
3002 | /* | ||
3003 | * notify clients before sleep and reset bus afterwards | ||
3004 | */ | ||
3005 | int | ||
3006 | serial_notify_sleep(struct pmu_sleep_notifier *self, int when) | ||
3007 | { | ||
3008 | int i; | ||
3009 | |||
3010 | switch (when) { | ||
3011 | case PBOOK_SLEEP_REQUEST: | ||
3012 | case PBOOK_SLEEP_REJECT: | ||
3013 | break; | ||
3014 | |||
3015 | case PBOOK_SLEEP_NOW: | ||
3016 | for (i=0; i<zs_channels_found; i++) { | ||
3017 | struct mac_serial *info = &zs_soft[i]; | ||
3018 | if (info->flags & ZILOG_INITIALIZED) { | ||
3019 | shutdown(info); | ||
3020 | info->flags |= ZILOG_SLEEPING; | ||
3021 | } | ||
3022 | } | ||
3023 | break; | ||
3024 | case PBOOK_WAKE: | ||
3025 | for (i=0; i<zs_channels_found; i++) { | ||
3026 | struct mac_serial *info = &zs_soft[i]; | ||
3027 | if (info->flags & ZILOG_SLEEPING) { | ||
3028 | info->flags &= ~ZILOG_SLEEPING; | ||
3029 | startup(info); | ||
3030 | } | ||
3031 | } | ||
3032 | break; | ||
3033 | } | ||
3034 | return PBOOK_SLEEP_OK; | ||
3035 | } | ||
3036 | #endif /* CONFIG_PMAC_PBOOK */ | ||
diff --git a/drivers/macintosh/macserial.h b/drivers/macintosh/macserial.h deleted file mode 100644 index bade11a7a5c3..000000000000 --- a/drivers/macintosh/macserial.h +++ /dev/null | |||
@@ -1,461 +0,0 @@ | |||
1 | /* | ||
2 | * macserial.h: Definitions for the Macintosh Z8530 serial driver. | ||
3 | * | ||
4 | * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras. | ||
5 | * | ||
6 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) | ||
7 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
8 | */ | ||
9 | #ifndef _MACSERIAL_H | ||
10 | #define _MACSERIAL_H | ||
11 | |||
12 | #include <linux/spinlock.h> | ||
13 | |||
14 | #define NUM_ZSREGS 16 | ||
15 | |||
16 | struct serial_struct { | ||
17 | int type; | ||
18 | int line; | ||
19 | int port; | ||
20 | int irq; | ||
21 | int flags; | ||
22 | int xmit_fifo_size; | ||
23 | int custom_divisor; | ||
24 | int baud_base; | ||
25 | unsigned short close_delay; | ||
26 | char reserved_char[2]; | ||
27 | int hub6; | ||
28 | unsigned short closing_wait; /* time to wait before closing */ | ||
29 | unsigned short closing_wait2; /* no longer used... */ | ||
30 | int reserved[4]; | ||
31 | }; | ||
32 | |||
33 | /* | ||
34 | * For the close wait times, 0 means wait forever for serial port to | ||
35 | * flush its output. 65535 means don't wait at all. | ||
36 | */ | ||
37 | #define ZILOG_CLOSING_WAIT_INF 0 | ||
38 | #define ZILOG_CLOSING_WAIT_NONE 65535 | ||
39 | |||
40 | /* | ||
41 | * Definitions for ZILOG_struct (and serial_struct) flags field | ||
42 | */ | ||
43 | #define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes | ||
44 | * on the callout port */ | ||
45 | #define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ | ||
46 | #define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */ | ||
47 | #define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ | ||
48 | |||
49 | #define ZILOG_SPD_MASK 0x0030 | ||
50 | #define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ | ||
51 | |||
52 | #define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ | ||
53 | #define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */ | ||
54 | |||
55 | #define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ | ||
56 | #define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ | ||
57 | #define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ | ||
58 | #define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ | ||
59 | #define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ | ||
60 | |||
61 | #define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */ | ||
62 | #define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged | ||
63 | * users can set or reset */ | ||
64 | |||
65 | /* Internal flags used only by kernel/chr_drv/serial.c */ | ||
66 | #define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */ | ||
67 | #define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ | ||
68 | #define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ | ||
69 | #define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ | ||
70 | #define ZILOG_CLOSING 0x08000000 /* Serial port is closing */ | ||
71 | #define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */ | ||
72 | #define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */ | ||
73 | #define ZILOG_SLEEPING 0x01000000 /* have shut it down for sleep */ | ||
74 | |||
75 | /* Software state per channel */ | ||
76 | |||
77 | #ifdef __KERNEL__ | ||
78 | /* | ||
79 | * This is our internal structure for each serial port's state. | ||
80 | * | ||
81 | * Many fields are paralleled by the structure used by the serial_struct | ||
82 | * structure. | ||
83 | * | ||
84 | * For definitions of the flags field, see tty.h | ||
85 | */ | ||
86 | |||
87 | struct mac_serial; | ||
88 | |||
89 | struct mac_zschannel { | ||
90 | volatile unsigned char* control; | ||
91 | volatile unsigned char* data; | ||
92 | spinlock_t lock; | ||
93 | /* Used for debugging */ | ||
94 | struct mac_serial* parent; | ||
95 | }; | ||
96 | |||
97 | struct mac_dma { | ||
98 | volatile struct dbdma_regs dma; | ||
99 | volatile unsigned short res_count; | ||
100 | volatile unsigned short command; | ||
101 | volatile unsigned int buf_addr; | ||
102 | }; | ||
103 | |||
104 | struct mac_serial { | ||
105 | struct mac_serial *zs_next; /* For IRQ servicing chain */ | ||
106 | struct mac_zschannel *zs_channel; /* Channel registers */ | ||
107 | struct mac_zschannel *zs_chan_a; /* A side registers */ | ||
108 | unsigned char read_reg_zero; | ||
109 | struct device_node* dev_node; | ||
110 | spinlock_t lock; | ||
111 | |||
112 | char soft_carrier; /* Use soft carrier on this channel */ | ||
113 | char break_abort; /* Is serial console in, so process brk/abrt */ | ||
114 | char kgdb_channel; /* Kgdb is running on this channel */ | ||
115 | char is_cons; /* Is this our console. */ | ||
116 | char is_internal_modem; /* is connected to an internal modem */ | ||
117 | char is_irda; /* is connected to an IrDA codec */ | ||
118 | int port_type; /* Port type for pmac_feature */ | ||
119 | unsigned char tx_active; /* character is being xmitted */ | ||
120 | unsigned char tx_stopped; /* output is suspended */ | ||
121 | unsigned char power_wait; /* waiting for power-up delay to expire */ | ||
122 | |||
123 | /* We need to know the current clock divisor | ||
124 | * to read the bps rate the chip has currently | ||
125 | * loaded. | ||
126 | */ | ||
127 | unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */ | ||
128 | int zs_baud; | ||
129 | |||
130 | /* Current write register values */ | ||
131 | unsigned char curregs[NUM_ZSREGS]; | ||
132 | |||
133 | /* Values we need to set next opportunity */ | ||
134 | unsigned char pendregs[NUM_ZSREGS]; | ||
135 | |||
136 | char change_needed; | ||
137 | |||
138 | int magic; | ||
139 | int baud_base; | ||
140 | int port; | ||
141 | int irq; | ||
142 | int flags; /* defined in tty.h */ | ||
143 | int type; /* UART type */ | ||
144 | struct tty_struct *tty; | ||
145 | int read_status_mask; | ||
146 | int ignore_status_mask; | ||
147 | int timeout; | ||
148 | int xmit_fifo_size; | ||
149 | int custom_divisor; | ||
150 | int x_char; /* xon/xoff character */ | ||
151 | int close_delay; | ||
152 | unsigned short closing_wait; | ||
153 | unsigned short closing_wait2; | ||
154 | unsigned long event; | ||
155 | unsigned long last_active; | ||
156 | int line; | ||
157 | int count; /* # of fd on device */ | ||
158 | int blocked_open; /* # of blocked opens */ | ||
159 | unsigned char *xmit_buf; | ||
160 | int xmit_head; | ||
161 | int xmit_tail; | ||
162 | int xmit_cnt; | ||
163 | struct work_struct tqueue; | ||
164 | wait_queue_head_t open_wait; | ||
165 | wait_queue_head_t close_wait; | ||
166 | |||
167 | volatile struct dbdma_regs *tx_dma; | ||
168 | int tx_dma_irq; | ||
169 | volatile struct dbdma_cmd *tx_cmds; | ||
170 | volatile struct mac_dma *rx; | ||
171 | int rx_dma_irq; | ||
172 | volatile struct dbdma_cmd **rx_cmds; | ||
173 | unsigned char **rx_char_buf; | ||
174 | unsigned char **rx_flag_buf; | ||
175 | #define RX_BUF_SIZE 256 | ||
176 | int rx_nbuf; | ||
177 | int rx_done_bytes; | ||
178 | int rx_ubuf; | ||
179 | int rx_fbuf; | ||
180 | #define RX_NO_FBUF (-1) | ||
181 | int rx_cbuf; | ||
182 | spinlock_t rx_dma_lock; | ||
183 | int has_dma; | ||
184 | int dma_initted; | ||
185 | void *dma_priv; | ||
186 | struct timer_list poll_dma_timer; | ||
187 | #define RX_DMA_TIMER (jiffies + 10*HZ/1000) | ||
188 | |||
189 | struct timer_list powerup_timer; | ||
190 | }; | ||
191 | |||
192 | |||
193 | #define SERIAL_MAGIC 0x5301 | ||
194 | |||
195 | /* | ||
196 | * The size of the serial xmit buffer is 1 page, or 4096 bytes | ||
197 | */ | ||
198 | #define SERIAL_XMIT_SIZE 4096 | ||
199 | |||
200 | /* | ||
201 | * Events are used to schedule things to happen at timer-interrupt | ||
202 | * time, instead of at rs interrupt time. | ||
203 | */ | ||
204 | #define RS_EVENT_WRITE_WAKEUP 0 | ||
205 | |||
206 | #endif /* __KERNEL__ */ | ||
207 | |||
208 | /* Conversion routines to/from brg time constants from/to bits | ||
209 | * per second. | ||
210 | */ | ||
211 | #define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2)) | ||
212 | #define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2) | ||
213 | |||
214 | /* The Zilog register set */ | ||
215 | |||
216 | #define FLAG 0x7e | ||
217 | |||
218 | /* Write Register 0 */ | ||
219 | #define R0 0 /* Register selects */ | ||
220 | #define R1 1 | ||
221 | #define R2 2 | ||
222 | #define R3 3 | ||
223 | #define R4 4 | ||
224 | #define R5 5 | ||
225 | #define R6 6 | ||
226 | #define R7 7 | ||
227 | #define R8 8 | ||
228 | #define R9 9 | ||
229 | #define R10 10 | ||
230 | #define R11 11 | ||
231 | #define R12 12 | ||
232 | #define R13 13 | ||
233 | #define R14 14 | ||
234 | #define R15 15 | ||
235 | |||
236 | #define NULLCODE 0 /* Null Code */ | ||
237 | #define POINT_HIGH 0x8 /* Select upper half of registers */ | ||
238 | #define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */ | ||
239 | #define SEND_ABORT 0x18 /* HDLC Abort */ | ||
240 | #define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */ | ||
241 | #define RES_Tx_P 0x28 /* Reset TxINT Pending */ | ||
242 | #define ERR_RES 0x30 /* Error Reset */ | ||
243 | #define RES_H_IUS 0x38 /* Reset highest IUS */ | ||
244 | |||
245 | #define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */ | ||
246 | #define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */ | ||
247 | #define RES_EOM_L 0xC0 /* Reset EOM latch */ | ||
248 | |||
249 | /* Write Register 1 */ | ||
250 | |||
251 | #define EXT_INT_ENAB 0x1 /* Ext Int Enable */ | ||
252 | #define TxINT_ENAB 0x2 /* Tx Int Enable */ | ||
253 | #define PAR_SPEC 0x4 /* Parity is special condition */ | ||
254 | |||
255 | #define RxINT_DISAB 0 /* Rx Int Disable */ | ||
256 | #define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ | ||
257 | #define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ | ||
258 | #define INT_ERR_Rx 0x18 /* Int on error only */ | ||
259 | |||
260 | #define WT_RDY_RT 0x20 /* W/Req reflects recv if 1, xmit if 0 */ | ||
261 | #define WT_FN_RDYFN 0x40 /* W/Req pin is DMA request if 1, wait if 0 */ | ||
262 | #define WT_RDY_ENAB 0x80 /* Enable W/Req pin */ | ||
263 | |||
264 | /* Write Register #2 (Interrupt Vector) */ | ||
265 | |||
266 | /* Write Register 3 */ | ||
267 | |||
268 | #define RxENABLE 0x1 /* Rx Enable */ | ||
269 | #define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */ | ||
270 | #define ADD_SM 0x4 /* Address Search Mode (SDLC) */ | ||
271 | #define RxCRC_ENAB 0x8 /* Rx CRC Enable */ | ||
272 | #define ENT_HM 0x10 /* Enter Hunt Mode */ | ||
273 | #define AUTO_ENAB 0x20 /* Auto Enables */ | ||
274 | #define Rx5 0x0 /* Rx 5 Bits/Character */ | ||
275 | #define Rx7 0x40 /* Rx 7 Bits/Character */ | ||
276 | #define Rx6 0x80 /* Rx 6 Bits/Character */ | ||
277 | #define Rx8 0xc0 /* Rx 8 Bits/Character */ | ||
278 | #define RxNBITS_MASK 0xc0 | ||
279 | |||
280 | /* Write Register 4 */ | ||
281 | |||
282 | #define PAR_ENA 0x1 /* Parity Enable */ | ||
283 | #define PAR_EVEN 0x2 /* Parity Even/Odd* */ | ||
284 | |||
285 | #define SYNC_ENAB 0 /* Sync Modes Enable */ | ||
286 | #define SB1 0x4 /* 1 stop bit/char */ | ||
287 | #define SB15 0x8 /* 1.5 stop bits/char */ | ||
288 | #define SB2 0xc /* 2 stop bits/char */ | ||
289 | #define SB_MASK 0xc | ||
290 | |||
291 | #define MONSYNC 0 /* 8 Bit Sync character */ | ||
292 | #define BISYNC 0x10 /* 16 bit sync character */ | ||
293 | #define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */ | ||
294 | #define EXTSYNC 0x30 /* External Sync Mode */ | ||
295 | |||
296 | #define X1CLK 0x0 /* x1 clock mode */ | ||
297 | #define X16CLK 0x40 /* x16 clock mode */ | ||
298 | #define X32CLK 0x80 /* x32 clock mode */ | ||
299 | #define X64CLK 0xC0 /* x64 clock mode */ | ||
300 | #define XCLK_MASK 0xC0 | ||
301 | |||
302 | /* Write Register 5 */ | ||
303 | |||
304 | #define TxCRC_ENAB 0x1 /* Tx CRC Enable */ | ||
305 | #define RTS 0x2 /* RTS */ | ||
306 | #define SDLC_CRC 0x4 /* SDLC/CRC-16 */ | ||
307 | #define TxENAB 0x8 /* Tx Enable */ | ||
308 | #define SND_BRK 0x10 /* Send Break */ | ||
309 | #define Tx5 0x0 /* Tx 5 bits (or less)/character */ | ||
310 | #define Tx7 0x20 /* Tx 7 bits/character */ | ||
311 | #define Tx6 0x40 /* Tx 6 bits/character */ | ||
312 | #define Tx8 0x60 /* Tx 8 bits/character */ | ||
313 | #define TxNBITS_MASK 0x60 | ||
314 | #define DTR 0x80 /* DTR */ | ||
315 | |||
316 | /* Write Register 6 (Sync bits 0-7/SDLC Address Field) */ | ||
317 | |||
318 | /* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ | ||
319 | |||
320 | /* Write Register 7' (Some enhanced feature control) */ | ||
321 | #define ENEXREAD 0x40 /* Enable read of some write registers */ | ||
322 | |||
323 | /* Write Register 8 (transmit buffer) */ | ||
324 | |||
325 | /* Write Register 9 (Master interrupt control) */ | ||
326 | #define VIS 1 /* Vector Includes Status */ | ||
327 | #define NV 2 /* No Vector */ | ||
328 | #define DLC 4 /* Disable Lower Chain */ | ||
329 | #define MIE 8 /* Master Interrupt Enable */ | ||
330 | #define STATHI 0x10 /* Status high */ | ||
331 | #define NORESET 0 /* No reset on write to R9 */ | ||
332 | #define CHRB 0x40 /* Reset channel B */ | ||
333 | #define CHRA 0x80 /* Reset channel A */ | ||
334 | #define FHWRES 0xc0 /* Force hardware reset */ | ||
335 | |||
336 | /* Write Register 10 (misc control bits) */ | ||
337 | #define BIT6 1 /* 6 bit/8bit sync */ | ||
338 | #define LOOPMODE 2 /* SDLC Loop mode */ | ||
339 | #define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */ | ||
340 | #define MARKIDLE 8 /* Mark/flag on idle */ | ||
341 | #define GAOP 0x10 /* Go active on poll */ | ||
342 | #define NRZ 0 /* NRZ mode */ | ||
343 | #define NRZI 0x20 /* NRZI mode */ | ||
344 | #define FM1 0x40 /* FM1 (transition = 1) */ | ||
345 | #define FM0 0x60 /* FM0 (transition = 0) */ | ||
346 | #define CRCPS 0x80 /* CRC Preset I/O */ | ||
347 | |||
348 | /* Write Register 11 (Clock Mode control) */ | ||
349 | #define TRxCXT 0 /* TRxC = Xtal output */ | ||
350 | #define TRxCTC 1 /* TRxC = Transmit clock */ | ||
351 | #define TRxCBR 2 /* TRxC = BR Generator Output */ | ||
352 | #define TRxCDP 3 /* TRxC = DPLL output */ | ||
353 | #define TRxCOI 4 /* TRxC O/I */ | ||
354 | #define TCRTxCP 0 /* Transmit clock = RTxC pin */ | ||
355 | #define TCTRxCP 8 /* Transmit clock = TRxC pin */ | ||
356 | #define TCBR 0x10 /* Transmit clock = BR Generator output */ | ||
357 | #define TCDPLL 0x18 /* Transmit clock = DPLL output */ | ||
358 | #define RCRTxCP 0 /* Receive clock = RTxC pin */ | ||
359 | #define RCTRxCP 0x20 /* Receive clock = TRxC pin */ | ||
360 | #define RCBR 0x40 /* Receive clock = BR Generator output */ | ||
361 | #define RCDPLL 0x60 /* Receive clock = DPLL output */ | ||
362 | #define RTxCX 0x80 /* RTxC Xtal/No Xtal */ | ||
363 | |||
364 | /* Write Register 12 (lower byte of baud rate generator time constant) */ | ||
365 | |||
366 | /* Write Register 13 (upper byte of baud rate generator time constant) */ | ||
367 | |||
368 | /* Write Register 14 (Misc control bits) */ | ||
369 | #define BRENABL 1 /* Baud rate generator enable */ | ||
370 | #define BRSRC 2 /* Baud rate generator source */ | ||
371 | #define DTRREQ 4 /* DTR/Request function */ | ||
372 | #define AUTOECHO 8 /* Auto Echo */ | ||
373 | #define LOOPBAK 0x10 /* Local loopback */ | ||
374 | #define SEARCH 0x20 /* Enter search mode */ | ||
375 | #define RMC 0x40 /* Reset missing clock */ | ||
376 | #define DISDPLL 0x60 /* Disable DPLL */ | ||
377 | #define SSBR 0x80 /* Set DPLL source = BR generator */ | ||
378 | #define SSRTxC 0xa0 /* Set DPLL source = RTxC */ | ||
379 | #define SFMM 0xc0 /* Set FM mode */ | ||
380 | #define SNRZI 0xe0 /* Set NRZI mode */ | ||
381 | |||
382 | /* Write Register 15 (external/status interrupt control) */ | ||
383 | #define EN85C30 1 /* Enable some 85c30-enhanced registers */ | ||
384 | #define ZCIE 2 /* Zero count IE */ | ||
385 | #define ENSTFIFO 4 /* Enable status FIFO (SDLC) */ | ||
386 | #define DCDIE 8 /* DCD IE */ | ||
387 | #define SYNCIE 0x10 /* Sync/hunt IE */ | ||
388 | #define CTSIE 0x20 /* CTS IE */ | ||
389 | #define TxUIE 0x40 /* Tx Underrun/EOM IE */ | ||
390 | #define BRKIE 0x80 /* Break/Abort IE */ | ||
391 | |||
392 | |||
393 | /* Read Register 0 */ | ||
394 | #define Rx_CH_AV 0x1 /* Rx Character Available */ | ||
395 | #define ZCOUNT 0x2 /* Zero count */ | ||
396 | #define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ | ||
397 | #define DCD 0x8 /* DCD */ | ||
398 | #define SYNC_HUNT 0x10 /* Sync/hunt */ | ||
399 | #define CTS 0x20 /* CTS */ | ||
400 | #define TxEOM 0x40 /* Tx underrun */ | ||
401 | #define BRK_ABRT 0x80 /* Break/Abort */ | ||
402 | |||
403 | /* Read Register 1 */ | ||
404 | #define ALL_SNT 0x1 /* All sent */ | ||
405 | /* Residue Data for 8 Rx bits/char programmed */ | ||
406 | #define RES3 0x8 /* 0/3 */ | ||
407 | #define RES4 0x4 /* 0/4 */ | ||
408 | #define RES5 0xc /* 0/5 */ | ||
409 | #define RES6 0x2 /* 0/6 */ | ||
410 | #define RES7 0xa /* 0/7 */ | ||
411 | #define RES8 0x6 /* 0/8 */ | ||
412 | #define RES18 0xe /* 1/8 */ | ||
413 | #define RES28 0x0 /* 2/8 */ | ||
414 | /* Special Rx Condition Interrupts */ | ||
415 | #define PAR_ERR 0x10 /* Parity error */ | ||
416 | #define Rx_OVR 0x20 /* Rx Overrun Error */ | ||
417 | #define FRM_ERR 0x40 /* CRC/Framing Error */ | ||
418 | #define END_FR 0x80 /* End of Frame (SDLC) */ | ||
419 | |||
420 | /* Read Register 2 (channel b only) - Interrupt vector */ | ||
421 | #define CHB_Tx_EMPTY 0x00 | ||
422 | #define CHB_EXT_STAT 0x02 | ||
423 | #define CHB_Rx_AVAIL 0x04 | ||
424 | #define CHB_SPECIAL 0x06 | ||
425 | #define CHA_Tx_EMPTY 0x08 | ||
426 | #define CHA_EXT_STAT 0x0a | ||
427 | #define CHA_Rx_AVAIL 0x0c | ||
428 | #define CHA_SPECIAL 0x0e | ||
429 | #define STATUS_MASK 0x06 | ||
430 | |||
431 | /* Read Register 3 (interrupt pending register) ch a only */ | ||
432 | #define CHBEXT 0x1 /* Channel B Ext/Stat IP */ | ||
433 | #define CHBTxIP 0x2 /* Channel B Tx IP */ | ||
434 | #define CHBRxIP 0x4 /* Channel B Rx IP */ | ||
435 | #define CHAEXT 0x8 /* Channel A Ext/Stat IP */ | ||
436 | #define CHATxIP 0x10 /* Channel A Tx IP */ | ||
437 | #define CHARxIP 0x20 /* Channel A Rx IP */ | ||
438 | |||
439 | /* Read Register 8 (receive data register) */ | ||
440 | |||
441 | /* Read Register 10 (misc status bits) */ | ||
442 | #define ONLOOP 2 /* On loop */ | ||
443 | #define LOOPSEND 0x10 /* Loop sending */ | ||
444 | #define CLK2MIS 0x40 /* Two clocks missing */ | ||
445 | #define CLK1MIS 0x80 /* One clock missing */ | ||
446 | |||
447 | /* Read Register 12 (lower byte of baud rate generator constant) */ | ||
448 | |||
449 | /* Read Register 13 (upper byte of baud rate generator constant) */ | ||
450 | |||
451 | /* Read Register 15 (value of WR 15) */ | ||
452 | |||
453 | /* Misc macros */ | ||
454 | #define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) | ||
455 | #define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ | ||
456 | garbage = read_zsdata(channel); \ | ||
457 | garbage = read_zsdata(channel); \ | ||
458 | garbage = read_zsdata(channel); \ | ||
459 | } while(0) | ||
460 | |||
461 | #endif /* !(_MACSERIAL_H) */ | ||
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index b941ee220997..4a0a0ad2d03c 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -63,6 +63,10 @@ | |||
63 | #include <asm/backlight.h> | 63 | #include <asm/backlight.h> |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | #ifdef CONFIG_PPC32 | ||
67 | #include <asm/open_pic.h> | ||
68 | #endif | ||
69 | |||
66 | /* Some compile options */ | 70 | /* Some compile options */ |
67 | #undef SUSPEND_USES_PMU | 71 | #undef SUSPEND_USES_PMU |
68 | #define DEBUG_SLEEP | 72 | #define DEBUG_SLEEP |
@@ -151,10 +155,10 @@ static spinlock_t pmu_lock; | |||
151 | static u8 pmu_intr_mask; | 155 | static u8 pmu_intr_mask; |
152 | static int pmu_version; | 156 | static int pmu_version; |
153 | static int drop_interrupts; | 157 | static int drop_interrupts; |
154 | #ifdef CONFIG_PMAC_PBOOK | 158 | #ifdef CONFIG_PM |
155 | static int option_lid_wakeup = 1; | 159 | static int option_lid_wakeup = 1; |
156 | static int sleep_in_progress; | 160 | static int sleep_in_progress; |
157 | #endif /* CONFIG_PMAC_PBOOK */ | 161 | #endif /* CONFIG_PM */ |
158 | static unsigned long async_req_locks; | 162 | static unsigned long async_req_locks; |
159 | static unsigned int pmu_irq_stats[11]; | 163 | static unsigned int pmu_irq_stats[11]; |
160 | 164 | ||
@@ -164,7 +168,6 @@ static struct proc_dir_entry *proc_pmu_irqstats; | |||
164 | static struct proc_dir_entry *proc_pmu_options; | 168 | static struct proc_dir_entry *proc_pmu_options; |
165 | static int option_server_mode; | 169 | static int option_server_mode; |
166 | 170 | ||
167 | #ifdef CONFIG_PMAC_PBOOK | ||
168 | int pmu_battery_count; | 171 | int pmu_battery_count; |
169 | int pmu_cur_battery; | 172 | int pmu_cur_battery; |
170 | unsigned int pmu_power_flags; | 173 | unsigned int pmu_power_flags; |
@@ -172,7 +175,6 @@ struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES]; | |||
172 | static int query_batt_timer = BATTERY_POLLING_COUNT; | 175 | static int query_batt_timer = BATTERY_POLLING_COUNT; |
173 | static struct adb_request batt_req; | 176 | static struct adb_request batt_req; |
174 | static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES]; | 177 | static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES]; |
175 | #endif /* CONFIG_PMAC_PBOOK */ | ||
176 | 178 | ||
177 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) | 179 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) |
178 | extern int disable_kernel_backlight; | 180 | extern int disable_kernel_backlight; |
@@ -206,11 +208,9 @@ static int proc_get_irqstats(char *page, char **start, off_t off, | |||
206 | static int pmu_set_backlight_level(int level, void* data); | 208 | static int pmu_set_backlight_level(int level, void* data); |
207 | static int pmu_set_backlight_enable(int on, int level, void* data); | 209 | static int pmu_set_backlight_enable(int on, int level, void* data); |
208 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 210 | #endif /* CONFIG_PMAC_BACKLIGHT */ |
209 | #ifdef CONFIG_PMAC_PBOOK | ||
210 | static void pmu_pass_intr(unsigned char *data, int len); | 211 | static void pmu_pass_intr(unsigned char *data, int len); |
211 | static int proc_get_batt(char *page, char **start, off_t off, | 212 | static int proc_get_batt(char *page, char **start, off_t off, |
212 | int count, int *eof, void *data); | 213 | int count, int *eof, void *data); |
213 | #endif /* CONFIG_PMAC_PBOOK */ | ||
214 | static int proc_read_options(char *page, char **start, off_t off, | 214 | static int proc_read_options(char *page, char **start, off_t off, |
215 | int count, int *eof, void *data); | 215 | int count, int *eof, void *data); |
216 | static int proc_write_options(struct file *file, const char __user *buffer, | 216 | static int proc_write_options(struct file *file, const char __user *buffer, |
@@ -403,8 +403,12 @@ static int __init via_pmu_start(void) | |||
403 | 403 | ||
404 | bright_req_1.complete = 1; | 404 | bright_req_1.complete = 1; |
405 | bright_req_2.complete = 1; | 405 | bright_req_2.complete = 1; |
406 | #ifdef CONFIG_PMAC_PBOOK | ||
407 | batt_req.complete = 1; | 406 | batt_req.complete = 1; |
407 | |||
408 | #ifdef CONFIG_PPC32 | ||
409 | if (pmu_kind == PMU_KEYLARGO_BASED) | ||
410 | openpic_set_irq_priority(vias->intrs[0].line, | ||
411 | OPENPIC_PRIORITY_DEFAULT + 1); | ||
408 | #endif | 412 | #endif |
409 | 413 | ||
410 | if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU", | 414 | if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU", |
@@ -458,7 +462,7 @@ static int __init via_pmu_dev_init(void) | |||
458 | register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); | 462 | register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); |
459 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 463 | #endif /* CONFIG_PMAC_BACKLIGHT */ |
460 | 464 | ||
461 | #ifdef CONFIG_PMAC_PBOOK | 465 | #ifdef CONFIG_PPC32 |
462 | if (machine_is_compatible("AAPL,3400/2400") || | 466 | if (machine_is_compatible("AAPL,3400/2400") || |
463 | machine_is_compatible("AAPL,3500")) { | 467 | machine_is_compatible("AAPL,3500")) { |
464 | int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO, | 468 | int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO, |
@@ -486,20 +490,19 @@ static int __init via_pmu_dev_init(void) | |||
486 | pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; | 490 | pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; |
487 | } | 491 | } |
488 | } | 492 | } |
489 | #endif /* CONFIG_PMAC_PBOOK */ | 493 | #endif /* CONFIG_PPC32 */ |
494 | |||
490 | /* Create /proc/pmu */ | 495 | /* Create /proc/pmu */ |
491 | proc_pmu_root = proc_mkdir("pmu", NULL); | 496 | proc_pmu_root = proc_mkdir("pmu", NULL); |
492 | if (proc_pmu_root) { | 497 | if (proc_pmu_root) { |
493 | #ifdef CONFIG_PMAC_PBOOK | 498 | long i; |
494 | int i; | ||
495 | 499 | ||
496 | for (i=0; i<pmu_battery_count; i++) { | 500 | for (i=0; i<pmu_battery_count; i++) { |
497 | char title[16]; | 501 | char title[16]; |
498 | sprintf(title, "battery_%d", i); | 502 | sprintf(title, "battery_%ld", i); |
499 | proc_pmu_batt[i] = create_proc_read_entry(title, 0, proc_pmu_root, | 503 | proc_pmu_batt[i] = create_proc_read_entry(title, 0, proc_pmu_root, |
500 | proc_get_batt, (void *)i); | 504 | proc_get_batt, (void *)i); |
501 | } | 505 | } |
502 | #endif /* CONFIG_PMAC_PBOOK */ | ||
503 | 506 | ||
504 | proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root, | 507 | proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root, |
505 | proc_get_info, NULL); | 508 | proc_get_info, NULL); |
@@ -619,8 +622,6 @@ static void pmu_set_server_mode(int server_mode) | |||
619 | pmu_wait_complete(&req); | 622 | pmu_wait_complete(&req); |
620 | } | 623 | } |
621 | 624 | ||
622 | #ifdef CONFIG_PMAC_PBOOK | ||
623 | |||
624 | /* This new version of the code for 2400/3400/3500 powerbooks | 625 | /* This new version of the code for 2400/3400/3500 powerbooks |
625 | * is inspired from the implementation in gkrellm-pmu | 626 | * is inspired from the implementation in gkrellm-pmu |
626 | */ | 627 | */ |
@@ -803,8 +804,6 @@ query_battery_state(void) | |||
803 | 2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1); | 804 | 2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1); |
804 | } | 805 | } |
805 | 806 | ||
806 | #endif /* CONFIG_PMAC_PBOOK */ | ||
807 | |||
808 | static int __pmac | 807 | static int __pmac |
809 | proc_get_info(char *page, char **start, off_t off, | 808 | proc_get_info(char *page, char **start, off_t off, |
810 | int count, int *eof, void *data) | 809 | int count, int *eof, void *data) |
@@ -813,11 +812,9 @@ proc_get_info(char *page, char **start, off_t off, | |||
813 | 812 | ||
814 | p += sprintf(p, "PMU driver version : %d\n", PMU_DRIVER_VERSION); | 813 | p += sprintf(p, "PMU driver version : %d\n", PMU_DRIVER_VERSION); |
815 | p += sprintf(p, "PMU firmware version : %02x\n", pmu_version); | 814 | p += sprintf(p, "PMU firmware version : %02x\n", pmu_version); |
816 | #ifdef CONFIG_PMAC_PBOOK | ||
817 | p += sprintf(p, "AC Power : %d\n", | 815 | p += sprintf(p, "AC Power : %d\n", |
818 | ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0)); | 816 | ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0)); |
819 | p += sprintf(p, "Battery count : %d\n", pmu_battery_count); | 817 | p += sprintf(p, "Battery count : %d\n", pmu_battery_count); |
820 | #endif /* CONFIG_PMAC_PBOOK */ | ||
821 | 818 | ||
822 | return p - page; | 819 | return p - page; |
823 | } | 820 | } |
@@ -849,12 +846,11 @@ proc_get_irqstats(char *page, char **start, off_t off, | |||
849 | return p - page; | 846 | return p - page; |
850 | } | 847 | } |
851 | 848 | ||
852 | #ifdef CONFIG_PMAC_PBOOK | ||
853 | static int __pmac | 849 | static int __pmac |
854 | proc_get_batt(char *page, char **start, off_t off, | 850 | proc_get_batt(char *page, char **start, off_t off, |
855 | int count, int *eof, void *data) | 851 | int count, int *eof, void *data) |
856 | { | 852 | { |
857 | int batnum = (int)data; | 853 | long batnum = (long)data; |
858 | char *p = page; | 854 | char *p = page; |
859 | 855 | ||
860 | p += sprintf(p, "\n"); | 856 | p += sprintf(p, "\n"); |
@@ -873,7 +869,6 @@ proc_get_batt(char *page, char **start, off_t off, | |||
873 | 869 | ||
874 | return p - page; | 870 | return p - page; |
875 | } | 871 | } |
876 | #endif /* CONFIG_PMAC_PBOOK */ | ||
877 | 872 | ||
878 | static int __pmac | 873 | static int __pmac |
879 | proc_read_options(char *page, char **start, off_t off, | 874 | proc_read_options(char *page, char **start, off_t off, |
@@ -881,11 +876,11 @@ proc_read_options(char *page, char **start, off_t off, | |||
881 | { | 876 | { |
882 | char *p = page; | 877 | char *p = page; |
883 | 878 | ||
884 | #ifdef CONFIG_PMAC_PBOOK | 879 | #ifdef CONFIG_PM |
885 | if (pmu_kind == PMU_KEYLARGO_BASED && | 880 | if (pmu_kind == PMU_KEYLARGO_BASED && |
886 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) | 881 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) |
887 | p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup); | 882 | p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup); |
888 | #endif /* CONFIG_PMAC_PBOOK */ | 883 | #endif |
889 | if (pmu_kind == PMU_KEYLARGO_BASED) | 884 | if (pmu_kind == PMU_KEYLARGO_BASED) |
890 | p += sprintf(p, "server_mode=%d\n", option_server_mode); | 885 | p += sprintf(p, "server_mode=%d\n", option_server_mode); |
891 | 886 | ||
@@ -922,12 +917,12 @@ proc_write_options(struct file *file, const char __user *buffer, | |||
922 | *(val++) = 0; | 917 | *(val++) = 0; |
923 | while(*val == ' ') | 918 | while(*val == ' ') |
924 | val++; | 919 | val++; |
925 | #ifdef CONFIG_PMAC_PBOOK | 920 | #ifdef CONFIG_PM |
926 | if (pmu_kind == PMU_KEYLARGO_BASED && | 921 | if (pmu_kind == PMU_KEYLARGO_BASED && |
927 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) | 922 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) |
928 | if (!strcmp(label, "lid_wakeup")) | 923 | if (!strcmp(label, "lid_wakeup")) |
929 | option_lid_wakeup = ((*val) == '1'); | 924 | option_lid_wakeup = ((*val) == '1'); |
930 | #endif /* CONFIG_PMAC_PBOOK */ | 925 | #endif |
931 | if (pmu_kind == PMU_KEYLARGO_BASED && !strcmp(label, "server_mode")) { | 926 | if (pmu_kind == PMU_KEYLARGO_BASED && !strcmp(label, "server_mode")) { |
932 | int new_value; | 927 | int new_value; |
933 | new_value = ((*val) == '1'); | 928 | new_value = ((*val) == '1'); |
@@ -1422,7 +1417,6 @@ next: | |||
1422 | } | 1417 | } |
1423 | /* Tick interrupt */ | 1418 | /* Tick interrupt */ |
1424 | else if ((1 << pirq) & PMU_INT_TICK) { | 1419 | else if ((1 << pirq) & PMU_INT_TICK) { |
1425 | #ifdef CONFIG_PMAC_PBOOK | ||
1426 | /* Environement or tick interrupt, query batteries */ | 1420 | /* Environement or tick interrupt, query batteries */ |
1427 | if (pmu_battery_count) { | 1421 | if (pmu_battery_count) { |
1428 | if ((--query_batt_timer) == 0) { | 1422 | if ((--query_batt_timer) == 0) { |
@@ -1437,7 +1431,6 @@ next: | |||
1437 | pmu_pass_intr(data, len); | 1431 | pmu_pass_intr(data, len); |
1438 | } else { | 1432 | } else { |
1439 | pmu_pass_intr(data, len); | 1433 | pmu_pass_intr(data, len); |
1440 | #endif /* CONFIG_PMAC_PBOOK */ | ||
1441 | } | 1434 | } |
1442 | goto next; | 1435 | goto next; |
1443 | } | 1436 | } |
@@ -2052,7 +2045,7 @@ pmu_i2c_simple_write(int bus, int addr, u8* data, int len) | |||
2052 | return -1; | 2045 | return -1; |
2053 | } | 2046 | } |
2054 | 2047 | ||
2055 | #ifdef CONFIG_PMAC_PBOOK | 2048 | #ifdef CONFIG_PM |
2056 | 2049 | ||
2057 | static LIST_HEAD(sleep_notifiers); | 2050 | static LIST_HEAD(sleep_notifiers); |
2058 | 2051 | ||
@@ -2705,6 +2698,8 @@ powerbook_sleep_3400(void) | |||
2705 | return 0; | 2698 | return 0; |
2706 | } | 2699 | } |
2707 | 2700 | ||
2701 | #endif /* CONFIG_PM */ | ||
2702 | |||
2708 | /* | 2703 | /* |
2709 | * Support for /dev/pmu device | 2704 | * Support for /dev/pmu device |
2710 | */ | 2705 | */ |
@@ -2884,11 +2879,11 @@ static int __pmac | |||
2884 | pmu_ioctl(struct inode * inode, struct file *filp, | 2879 | pmu_ioctl(struct inode * inode, struct file *filp, |
2885 | u_int cmd, u_long arg) | 2880 | u_int cmd, u_long arg) |
2886 | { | 2881 | { |
2887 | struct pmu_private *pp = filp->private_data; | ||
2888 | __u32 __user *argp = (__u32 __user *)arg; | 2882 | __u32 __user *argp = (__u32 __user *)arg; |
2889 | int error; | 2883 | int error = -EINVAL; |
2890 | 2884 | ||
2891 | switch (cmd) { | 2885 | switch (cmd) { |
2886 | #ifdef CONFIG_PM | ||
2892 | case PMU_IOC_SLEEP: | 2887 | case PMU_IOC_SLEEP: |
2893 | if (!capable(CAP_SYS_ADMIN)) | 2888 | if (!capable(CAP_SYS_ADMIN)) |
2894 | return -EACCES; | 2889 | return -EACCES; |
@@ -2910,12 +2905,13 @@ pmu_ioctl(struct inode * inode, struct file *filp, | |||
2910 | error = -ENOSYS; | 2905 | error = -ENOSYS; |
2911 | } | 2906 | } |
2912 | sleep_in_progress = 0; | 2907 | sleep_in_progress = 0; |
2913 | return error; | 2908 | break; |
2914 | case PMU_IOC_CAN_SLEEP: | 2909 | case PMU_IOC_CAN_SLEEP: |
2915 | if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) | 2910 | if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) |
2916 | return put_user(0, argp); | 2911 | return put_user(0, argp); |
2917 | else | 2912 | else |
2918 | return put_user(1, argp); | 2913 | return put_user(1, argp); |
2914 | #endif /* CONFIG_PM */ | ||
2919 | 2915 | ||
2920 | #ifdef CONFIG_PMAC_BACKLIGHT | 2916 | #ifdef CONFIG_PMAC_BACKLIGHT |
2921 | /* Backlight should have its own device or go via | 2917 | /* Backlight should have its own device or go via |
@@ -2936,11 +2932,13 @@ pmu_ioctl(struct inode * inode, struct file *filp, | |||
2936 | error = get_user(value, argp); | 2932 | error = get_user(value, argp); |
2937 | if (!error) | 2933 | if (!error) |
2938 | error = set_backlight_level(value); | 2934 | error = set_backlight_level(value); |
2939 | return error; | 2935 | break; |
2940 | } | 2936 | } |
2941 | #ifdef CONFIG_INPUT_ADBHID | 2937 | #ifdef CONFIG_INPUT_ADBHID |
2942 | case PMU_IOC_GRAB_BACKLIGHT: { | 2938 | case PMU_IOC_GRAB_BACKLIGHT: { |
2939 | struct pmu_private *pp = filp->private_data; | ||
2943 | unsigned long flags; | 2940 | unsigned long flags; |
2941 | |||
2944 | if (pp->backlight_locker) | 2942 | if (pp->backlight_locker) |
2945 | return 0; | 2943 | return 0; |
2946 | pp->backlight_locker = 1; | 2944 | pp->backlight_locker = 1; |
@@ -2956,7 +2954,7 @@ pmu_ioctl(struct inode * inode, struct file *filp, | |||
2956 | case PMU_IOC_HAS_ADB: | 2954 | case PMU_IOC_HAS_ADB: |
2957 | return put_user(pmu_has_adb, argp); | 2955 | return put_user(pmu_has_adb, argp); |
2958 | } | 2956 | } |
2959 | return -EINVAL; | 2957 | return error; |
2960 | } | 2958 | } |
2961 | 2959 | ||
2962 | static struct file_operations pmu_device_fops __pmacdata = { | 2960 | static struct file_operations pmu_device_fops __pmacdata = { |
@@ -2972,14 +2970,16 @@ static struct miscdevice pmu_device __pmacdata = { | |||
2972 | PMU_MINOR, "pmu", &pmu_device_fops | 2970 | PMU_MINOR, "pmu", &pmu_device_fops |
2973 | }; | 2971 | }; |
2974 | 2972 | ||
2975 | void pmu_device_init(void) | 2973 | static int pmu_device_init(void) |
2976 | { | 2974 | { |
2977 | if (!via) | 2975 | if (!via) |
2978 | return; | 2976 | return 0; |
2979 | if (misc_register(&pmu_device) < 0) | 2977 | if (misc_register(&pmu_device) < 0) |
2980 | printk(KERN_ERR "via-pmu: cannot register misc device.\n"); | 2978 | printk(KERN_ERR "via-pmu: cannot register misc device.\n"); |
2979 | return 0; | ||
2981 | } | 2980 | } |
2982 | #endif /* CONFIG_PMAC_PBOOK */ | 2981 | device_initcall(pmu_device_init); |
2982 | |||
2983 | 2983 | ||
2984 | #ifdef DEBUG_SLEEP | 2984 | #ifdef DEBUG_SLEEP |
2985 | static inline void __pmac | 2985 | static inline void __pmac |
@@ -3147,12 +3147,12 @@ EXPORT_SYMBOL(pmu_i2c_combined_read); | |||
3147 | EXPORT_SYMBOL(pmu_i2c_stdsub_write); | 3147 | EXPORT_SYMBOL(pmu_i2c_stdsub_write); |
3148 | EXPORT_SYMBOL(pmu_i2c_simple_read); | 3148 | EXPORT_SYMBOL(pmu_i2c_simple_read); |
3149 | EXPORT_SYMBOL(pmu_i2c_simple_write); | 3149 | EXPORT_SYMBOL(pmu_i2c_simple_write); |
3150 | #ifdef CONFIG_PMAC_PBOOK | 3150 | #ifdef CONFIG_PM |
3151 | EXPORT_SYMBOL(pmu_register_sleep_notifier); | 3151 | EXPORT_SYMBOL(pmu_register_sleep_notifier); |
3152 | EXPORT_SYMBOL(pmu_unregister_sleep_notifier); | 3152 | EXPORT_SYMBOL(pmu_unregister_sleep_notifier); |
3153 | EXPORT_SYMBOL(pmu_enable_irled); | 3153 | EXPORT_SYMBOL(pmu_enable_irled); |
3154 | EXPORT_SYMBOL(pmu_battery_count); | 3154 | EXPORT_SYMBOL(pmu_battery_count); |
3155 | EXPORT_SYMBOL(pmu_batteries); | 3155 | EXPORT_SYMBOL(pmu_batteries); |
3156 | EXPORT_SYMBOL(pmu_power_flags); | 3156 | EXPORT_SYMBOL(pmu_power_flags); |
3157 | #endif /* CONFIG_PMAC_PBOOK */ | 3157 | #endif /* CONFIG_PM */ |
3158 | 3158 | ||
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f9383e7f34ff..1b70f8b0feb9 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -7,7 +7,7 @@ menu "Video For Linux" | |||
7 | 7 | ||
8 | comment "Video Adapters" | 8 | comment "Video Adapters" |
9 | 9 | ||
10 | config CONFIG_TUNER_MULTI_I2C | 10 | config TUNER_MULTI_I2C |
11 | bool "Enable support for multiple I2C devices on Video Adapters (EXPERIMENTAL)" | 11 | bool "Enable support for multiple I2C devices on Video Adapters (EXPERIMENTAL)" |
12 | depends on VIDEO_DEV && EXPERIMENTAL | 12 | depends on VIDEO_DEV && EXPERIMENTAL |
13 | ---help--- | 13 | ---help--- |
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 1247a25f1093..9e1fe2e0478c 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c | |||
@@ -1274,6 +1274,7 @@ module_param_array(irq, int, NULL, 0); | |||
1274 | module_param_array(io, int, NULL, 0); | 1274 | module_param_array(io, int, NULL, 0); |
1275 | MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)"); | 1275 | MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)"); |
1276 | MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)"); | 1276 | MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)"); |
1277 | MODULE_LICENSE("GPL"); | ||
1277 | 1278 | ||
1278 | int init_module(void) | 1279 | int init_module(void) |
1279 | { | 1280 | { |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 47e158fa5aac..2b55687f6ee9 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1320,7 +1320,7 @@ config FORCEDETH | |||
1320 | 1320 | ||
1321 | config CS89x0 | 1321 | config CS89x0 |
1322 | tristate "CS89x0 support" | 1322 | tristate "CS89x0 support" |
1323 | depends on NET_PCI && (ISA || ARCH_IXDP2X01) | 1323 | depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105 |
1324 | ---help--- | 1324 | ---help--- |
1325 | Support for CS89x0 chipset based Ethernet cards. If you have a | 1325 | Support for CS89x0 chipset based Ethernet cards. If you have a |
1326 | network (Ethernet) card of this type, say Y and read the | 1326 | network (Ethernet) card of this type, say Y and read the |
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 3fe8ba992c38..f1bd45e3da31 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -1285,6 +1285,9 @@ static int b44_open(struct net_device *dev) | |||
1285 | b44_init_hw(bp); | 1285 | b44_init_hw(bp); |
1286 | bp->flags |= B44_FLAG_INIT_COMPLETE; | 1286 | bp->flags |= B44_FLAG_INIT_COMPLETE; |
1287 | 1287 | ||
1288 | netif_carrier_off(dev); | ||
1289 | b44_check_phy(bp); | ||
1290 | |||
1288 | spin_unlock_irq(&bp->lock); | 1291 | spin_unlock_irq(&bp->lock); |
1289 | 1292 | ||
1290 | init_timer(&bp->timer); | 1293 | init_timer(&bp->timer); |
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 25e4495de79e..b96d6fb1929e 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c | |||
@@ -174,6 +174,13 @@ static unsigned int cs8900_irq_map[] = {1,0,0,0}; | |||
174 | #include <asm/irq.h> | 174 | #include <asm/irq.h> |
175 | static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; | 175 | static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; |
176 | static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; | 176 | static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; |
177 | #elif defined(CONFIG_ARCH_PNX0105) | ||
178 | #include <asm/irq.h> | ||
179 | #include <asm/arch/gpio.h> | ||
180 | #define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */ | ||
181 | #define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */ | ||
182 | static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0}; | ||
183 | static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0}; | ||
177 | #else | 184 | #else |
178 | static unsigned int netcard_portlist[] __initdata = | 185 | static unsigned int netcard_portlist[] __initdata = |
179 | { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; | 186 | { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; |
@@ -431,6 +438,30 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
431 | #endif | 438 | #endif |
432 | } | 439 | } |
433 | 440 | ||
441 | #ifdef CONFIG_ARCH_PNX0105 | ||
442 | initialize_ebi(); | ||
443 | |||
444 | /* Map GPIO registers for the pins connected to the CS8900a. */ | ||
445 | if (map_cirrus_gpio() < 0) | ||
446 | return -ENODEV; | ||
447 | |||
448 | reset_cirrus(); | ||
449 | |||
450 | /* Map event-router registers. */ | ||
451 | if (map_event_router() < 0) | ||
452 | return -ENODEV; | ||
453 | |||
454 | enable_cirrus_irq(); | ||
455 | |||
456 | unmap_cirrus_gpio(); | ||
457 | unmap_event_router(); | ||
458 | |||
459 | dev->base_addr = ioaddr; | ||
460 | |||
461 | for (i = 0 ; i < 3 ; i++) | ||
462 | readreg(dev, 0); | ||
463 | #endif | ||
464 | |||
434 | /* Grab the region so we can find another board if autoIRQ fails. */ | 465 | /* Grab the region so we can find another board if autoIRQ fails. */ |
435 | /* WTF is going on here? */ | 466 | /* WTF is going on here? */ |
436 | if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { | 467 | if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { |
@@ -672,7 +703,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); | |||
672 | } else { | 703 | } else { |
673 | i = lp->isa_config & INT_NO_MASK; | 704 | i = lp->isa_config & INT_NO_MASK; |
674 | if (lp->chip_type == CS8900) { | 705 | if (lp->chip_type == CS8900) { |
675 | #ifdef CONFIG_ARCH_IXDP2X01 | 706 | #if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) |
676 | i = cs8900_irq_map[0]; | 707 | i = cs8900_irq_map[0]; |
677 | #else | 708 | #else |
678 | /* Translate the IRQ using the IRQ mapping table. */ | 709 | /* Translate the IRQ using the IRQ mapping table. */ |
@@ -1145,7 +1176,7 @@ net_open(struct net_device *dev) | |||
1145 | int i; | 1176 | int i; |
1146 | int ret; | 1177 | int ret; |
1147 | 1178 | ||
1148 | #ifndef CONFIG_SH_HICOSH4 /* uses irq#1, so this won't work */ | 1179 | #if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX0105) /* uses irq#1, so this won't work */ |
1149 | if (dev->irq < 2) { | 1180 | if (dev->irq < 2) { |
1150 | /* Allow interrupts to be generated by the chip */ | 1181 | /* Allow interrupts to be generated by the chip */ |
1151 | /* Cirrus' release had this: */ | 1182 | /* Cirrus' release had this: */ |
@@ -1176,7 +1207,7 @@ net_open(struct net_device *dev) | |||
1176 | else | 1207 | else |
1177 | #endif | 1208 | #endif |
1178 | { | 1209 | { |
1179 | #ifndef CONFIG_ARCH_IXDP2X01 | 1210 | #if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105) |
1180 | if (((1 << dev->irq) & lp->irq_map) == 0) { | 1211 | if (((1 << dev->irq) & lp->irq_map) == 0) { |
1181 | printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", | 1212 | printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", |
1182 | dev->name, dev->irq, lp->irq_map); | 1213 | dev->name, dev->irq, lp->irq_map); |
@@ -1261,6 +1292,9 @@ net_open(struct net_device *dev) | |||
1261 | case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; | 1292 | case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; |
1262 | default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); | 1293 | default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); |
1263 | } | 1294 | } |
1295 | #ifdef CONFIG_ARCH_PNX0105 | ||
1296 | result = A_CNF_10B_T; | ||
1297 | #endif | ||
1264 | if (!result) { | 1298 | if (!result) { |
1265 | printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name); | 1299 | printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name); |
1266 | release_irq: | 1300 | release_irq: |
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h index b0ef7ad2baad..bd3ad8e6cce9 100644 --- a/drivers/net/cs89x0.h +++ b/drivers/net/cs89x0.h | |||
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/config.h> | 17 | #include <linux/config.h> |
18 | 18 | ||
19 | #ifdef CONFIG_ARCH_IXDP2X01 | 19 | #if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) |
20 | /* IXDP2401/IXDP2801 uses dword-aligned register addressing */ | 20 | /* IXDP2401/IXDP2801 uses dword-aligned register addressing */ |
21 | #define CS89x0_PORT(reg) ((reg) * 2) | 21 | #define CS89x0_PORT(reg) ((reg) * 2) |
22 | #else | 22 | #else |
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index cfaa6b2bf345..1e56c8eea35f 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -1093,11 +1093,16 @@ static int e100_phy_init(struct nic *nic) | |||
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && | 1095 | if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && |
1096 | (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && | 1096 | (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) { |
1097 | (nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) | 1097 | /* enable/disable MDI/MDI-X auto-switching. |
1098 | /* enable/disable MDI/MDI-X auto-switching */ | 1098 | MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */ |
1099 | mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, | 1099 | if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) || |
1100 | nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); | 1100 | (nic->mac == mac_82551_10) || (nic->mii.force_media) || |
1101 | !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled)) | ||
1102 | mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0); | ||
1103 | else | ||
1104 | mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH); | ||
1105 | } | ||
1101 | 1106 | ||
1102 | return 0; | 1107 | return 0; |
1103 | } | 1108 | } |
@@ -1666,8 +1671,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
1666 | if(stat_ack & stat_ack_rnr) | 1671 | if(stat_ack & stat_ack_rnr) |
1667 | nic->ru_running = RU_SUSPENDED; | 1672 | nic->ru_running = RU_SUSPENDED; |
1668 | 1673 | ||
1669 | e100_disable_irq(nic); | 1674 | if(likely(netif_rx_schedule_prep(netdev))) { |
1670 | netif_rx_schedule(netdev); | 1675 | e100_disable_irq(nic); |
1676 | __netif_rx_schedule(netdev); | ||
1677 | } | ||
1671 | 1678 | ||
1672 | return IRQ_HANDLED; | 1679 | return IRQ_HANDLED; |
1673 | } | 1680 | } |
@@ -2335,11 +2342,11 @@ static int __devinit e100_probe(struct pci_dev *pdev, | |||
2335 | goto err_out_iounmap; | 2342 | goto err_out_iounmap; |
2336 | } | 2343 | } |
2337 | 2344 | ||
2338 | e100_phy_init(nic); | ||
2339 | |||
2340 | if((err = e100_eeprom_load(nic))) | 2345 | if((err = e100_eeprom_load(nic))) |
2341 | goto err_out_free; | 2346 | goto err_out_free; |
2342 | 2347 | ||
2348 | e100_phy_init(nic); | ||
2349 | |||
2343 | memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); | 2350 | memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); |
2344 | if(!is_valid_ether_addr(netdev->dev_addr)) { | 2351 | if(!is_valid_ether_addr(netdev->dev_addr)) { |
2345 | DPRINTK(PROBE, ERR, "Invalid MAC address from " | 2352 | DPRINTK(PROBE, ERR, "Invalid MAC address from " |
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index af1e82c5b808..092757bc721f 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h | |||
@@ -140,7 +140,7 @@ struct e1000_adapter; | |||
140 | #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ | 140 | #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ |
141 | 141 | ||
142 | #define AUTO_ALL_MODES 0 | 142 | #define AUTO_ALL_MODES 0 |
143 | #define E1000_EEPROM_82544_APM 0x0400 | 143 | #define E1000_EEPROM_82544_APM 0x0004 |
144 | #define E1000_EEPROM_APME 0x0400 | 144 | #define E1000_EEPROM_APME 0x0400 |
145 | 145 | ||
146 | #ifndef E1000_MASTER_SLAVE | 146 | #ifndef E1000_MASTER_SLAVE |
@@ -159,7 +159,7 @@ struct e1000_adapter; | |||
159 | * so a DMA handle can be stored along with the buffer */ | 159 | * so a DMA handle can be stored along with the buffer */ |
160 | struct e1000_buffer { | 160 | struct e1000_buffer { |
161 | struct sk_buff *skb; | 161 | struct sk_buff *skb; |
162 | uint64_t dma; | 162 | dma_addr_t dma; |
163 | unsigned long time_stamp; | 163 | unsigned long time_stamp; |
164 | uint16_t length; | 164 | uint16_t length; |
165 | uint16_t next_to_watch; | 165 | uint16_t next_to_watch; |
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 237247f74df4..f133ff0b0b94 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c | |||
@@ -105,7 +105,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { | |||
105 | static int | 105 | static int |
106 | e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | 106 | e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) |
107 | { | 107 | { |
108 | struct e1000_adapter *adapter = netdev->priv; | 108 | struct e1000_adapter *adapter = netdev_priv(netdev); |
109 | struct e1000_hw *hw = &adapter->hw; | 109 | struct e1000_hw *hw = &adapter->hw; |
110 | 110 | ||
111 | if(hw->media_type == e1000_media_type_copper) { | 111 | if(hw->media_type == e1000_media_type_copper) { |
@@ -141,9 +141,9 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | |||
141 | SUPPORTED_FIBRE | | 141 | SUPPORTED_FIBRE | |
142 | SUPPORTED_Autoneg); | 142 | SUPPORTED_Autoneg); |
143 | 143 | ||
144 | ecmd->advertising = (SUPPORTED_1000baseT_Full | | 144 | ecmd->advertising = (ADVERTISED_1000baseT_Full | |
145 | SUPPORTED_FIBRE | | 145 | ADVERTISED_FIBRE | |
146 | SUPPORTED_Autoneg); | 146 | ADVERTISED_Autoneg); |
147 | 147 | ||
148 | ecmd->port = PORT_FIBRE; | 148 | ecmd->port = PORT_FIBRE; |
149 | 149 | ||
@@ -179,13 +179,24 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | |||
179 | static int | 179 | static int |
180 | e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | 180 | e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) |
181 | { | 181 | { |
182 | struct e1000_adapter *adapter = netdev->priv; | 182 | struct e1000_adapter *adapter = netdev_priv(netdev); |
183 | struct e1000_hw *hw = &adapter->hw; | 183 | struct e1000_hw *hw = &adapter->hw; |
184 | 184 | ||
185 | if(ecmd->autoneg == AUTONEG_ENABLE) { | 185 | if(ecmd->autoneg == AUTONEG_ENABLE) { |
186 | hw->autoneg = 1; | 186 | hw->autoneg = 1; |
187 | hw->autoneg_advertised = 0x002F; | 187 | if(hw->media_type == e1000_media_type_fiber) |
188 | ecmd->advertising = 0x002F; | 188 | hw->autoneg_advertised = ADVERTISED_1000baseT_Full | |
189 | ADVERTISED_FIBRE | | ||
190 | ADVERTISED_Autoneg; | ||
191 | else | ||
192 | hw->autoneg_advertised = ADVERTISED_10baseT_Half | | ||
193 | ADVERTISED_10baseT_Full | | ||
194 | ADVERTISED_100baseT_Half | | ||
195 | ADVERTISED_100baseT_Full | | ||
196 | ADVERTISED_1000baseT_Full| | ||
197 | ADVERTISED_Autoneg | | ||
198 | ADVERTISED_TP; | ||
199 | ecmd->advertising = hw->autoneg_advertised; | ||
189 | } else | 200 | } else |
190 | if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) | 201 | if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) |
191 | return -EINVAL; | 202 | return -EINVAL; |
@@ -206,7 +217,7 @@ static void | |||
206 | e1000_get_pauseparam(struct net_device *netdev, | 217 | e1000_get_pauseparam(struct net_device *netdev, |
207 | struct ethtool_pauseparam *pause) | 218 | struct ethtool_pauseparam *pause) |
208 | { | 219 | { |
209 | struct e1000_adapter *adapter = netdev->priv; | 220 | struct e1000_adapter *adapter = netdev_priv(netdev); |
210 | struct e1000_hw *hw = &adapter->hw; | 221 | struct e1000_hw *hw = &adapter->hw; |
211 | 222 | ||
212 | pause->autoneg = | 223 | pause->autoneg = |
@@ -226,7 +237,7 @@ static int | |||
226 | e1000_set_pauseparam(struct net_device *netdev, | 237 | e1000_set_pauseparam(struct net_device *netdev, |
227 | struct ethtool_pauseparam *pause) | 238 | struct ethtool_pauseparam *pause) |
228 | { | 239 | { |
229 | struct e1000_adapter *adapter = netdev->priv; | 240 | struct e1000_adapter *adapter = netdev_priv(netdev); |
230 | struct e1000_hw *hw = &adapter->hw; | 241 | struct e1000_hw *hw = &adapter->hw; |
231 | 242 | ||
232 | adapter->fc_autoneg = pause->autoneg; | 243 | adapter->fc_autoneg = pause->autoneg; |
@@ -259,14 +270,14 @@ e1000_set_pauseparam(struct net_device *netdev, | |||
259 | static uint32_t | 270 | static uint32_t |
260 | e1000_get_rx_csum(struct net_device *netdev) | 271 | e1000_get_rx_csum(struct net_device *netdev) |
261 | { | 272 | { |
262 | struct e1000_adapter *adapter = netdev->priv; | 273 | struct e1000_adapter *adapter = netdev_priv(netdev); |
263 | return adapter->rx_csum; | 274 | return adapter->rx_csum; |
264 | } | 275 | } |
265 | 276 | ||
266 | static int | 277 | static int |
267 | e1000_set_rx_csum(struct net_device *netdev, uint32_t data) | 278 | e1000_set_rx_csum(struct net_device *netdev, uint32_t data) |
268 | { | 279 | { |
269 | struct e1000_adapter *adapter = netdev->priv; | 280 | struct e1000_adapter *adapter = netdev_priv(netdev); |
270 | adapter->rx_csum = data; | 281 | adapter->rx_csum = data; |
271 | 282 | ||
272 | if(netif_running(netdev)) { | 283 | if(netif_running(netdev)) { |
@@ -286,7 +297,7 @@ e1000_get_tx_csum(struct net_device *netdev) | |||
286 | static int | 297 | static int |
287 | e1000_set_tx_csum(struct net_device *netdev, uint32_t data) | 298 | e1000_set_tx_csum(struct net_device *netdev, uint32_t data) |
288 | { | 299 | { |
289 | struct e1000_adapter *adapter = netdev->priv; | 300 | struct e1000_adapter *adapter = netdev_priv(netdev); |
290 | 301 | ||
291 | if(adapter->hw.mac_type < e1000_82543) { | 302 | if(adapter->hw.mac_type < e1000_82543) { |
292 | if (!data) | 303 | if (!data) |
@@ -306,8 +317,8 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data) | |||
306 | static int | 317 | static int |
307 | e1000_set_tso(struct net_device *netdev, uint32_t data) | 318 | e1000_set_tso(struct net_device *netdev, uint32_t data) |
308 | { | 319 | { |
309 | struct e1000_adapter *adapter = netdev->priv; | 320 | struct e1000_adapter *adapter = netdev_priv(netdev); |
310 | if ((adapter->hw.mac_type < e1000_82544) || | 321 | if((adapter->hw.mac_type < e1000_82544) || |
311 | (adapter->hw.mac_type == e1000_82547)) | 322 | (adapter->hw.mac_type == e1000_82547)) |
312 | return data ? -EINVAL : 0; | 323 | return data ? -EINVAL : 0; |
313 | 324 | ||
@@ -322,14 +333,14 @@ e1000_set_tso(struct net_device *netdev, uint32_t data) | |||
322 | static uint32_t | 333 | static uint32_t |
323 | e1000_get_msglevel(struct net_device *netdev) | 334 | e1000_get_msglevel(struct net_device *netdev) |
324 | { | 335 | { |
325 | struct e1000_adapter *adapter = netdev->priv; | 336 | struct e1000_adapter *adapter = netdev_priv(netdev); |
326 | return adapter->msg_enable; | 337 | return adapter->msg_enable; |
327 | } | 338 | } |
328 | 339 | ||
329 | static void | 340 | static void |
330 | e1000_set_msglevel(struct net_device *netdev, uint32_t data) | 341 | e1000_set_msglevel(struct net_device *netdev, uint32_t data) |
331 | { | 342 | { |
332 | struct e1000_adapter *adapter = netdev->priv; | 343 | struct e1000_adapter *adapter = netdev_priv(netdev); |
333 | adapter->msg_enable = data; | 344 | adapter->msg_enable = data; |
334 | } | 345 | } |
335 | 346 | ||
@@ -344,7 +355,7 @@ static void | |||
344 | e1000_get_regs(struct net_device *netdev, | 355 | e1000_get_regs(struct net_device *netdev, |
345 | struct ethtool_regs *regs, void *p) | 356 | struct ethtool_regs *regs, void *p) |
346 | { | 357 | { |
347 | struct e1000_adapter *adapter = netdev->priv; | 358 | struct e1000_adapter *adapter = netdev_priv(netdev); |
348 | struct e1000_hw *hw = &adapter->hw; | 359 | struct e1000_hw *hw = &adapter->hw; |
349 | uint32_t *regs_buff = p; | 360 | uint32_t *regs_buff = p; |
350 | uint16_t phy_data; | 361 | uint16_t phy_data; |
@@ -432,7 +443,7 @@ e1000_get_regs(struct net_device *netdev, | |||
432 | static int | 443 | static int |
433 | e1000_get_eeprom_len(struct net_device *netdev) | 444 | e1000_get_eeprom_len(struct net_device *netdev) |
434 | { | 445 | { |
435 | struct e1000_adapter *adapter = netdev->priv; | 446 | struct e1000_adapter *adapter = netdev_priv(netdev); |
436 | return adapter->hw.eeprom.word_size * 2; | 447 | return adapter->hw.eeprom.word_size * 2; |
437 | } | 448 | } |
438 | 449 | ||
@@ -440,7 +451,7 @@ static int | |||
440 | e1000_get_eeprom(struct net_device *netdev, | 451 | e1000_get_eeprom(struct net_device *netdev, |
441 | struct ethtool_eeprom *eeprom, uint8_t *bytes) | 452 | struct ethtool_eeprom *eeprom, uint8_t *bytes) |
442 | { | 453 | { |
443 | struct e1000_adapter *adapter = netdev->priv; | 454 | struct e1000_adapter *adapter = netdev_priv(netdev); |
444 | struct e1000_hw *hw = &adapter->hw; | 455 | struct e1000_hw *hw = &adapter->hw; |
445 | uint16_t *eeprom_buff; | 456 | uint16_t *eeprom_buff; |
446 | int first_word, last_word; | 457 | int first_word, last_word; |
@@ -486,7 +497,7 @@ static int | |||
486 | e1000_set_eeprom(struct net_device *netdev, | 497 | e1000_set_eeprom(struct net_device *netdev, |
487 | struct ethtool_eeprom *eeprom, uint8_t *bytes) | 498 | struct ethtool_eeprom *eeprom, uint8_t *bytes) |
488 | { | 499 | { |
489 | struct e1000_adapter *adapter = netdev->priv; | 500 | struct e1000_adapter *adapter = netdev_priv(netdev); |
490 | struct e1000_hw *hw = &adapter->hw; | 501 | struct e1000_hw *hw = &adapter->hw; |
491 | uint16_t *eeprom_buff; | 502 | uint16_t *eeprom_buff; |
492 | void *ptr; | 503 | void *ptr; |
@@ -547,7 +558,7 @@ static void | |||
547 | e1000_get_drvinfo(struct net_device *netdev, | 558 | e1000_get_drvinfo(struct net_device *netdev, |
548 | struct ethtool_drvinfo *drvinfo) | 559 | struct ethtool_drvinfo *drvinfo) |
549 | { | 560 | { |
550 | struct e1000_adapter *adapter = netdev->priv; | 561 | struct e1000_adapter *adapter = netdev_priv(netdev); |
551 | 562 | ||
552 | strncpy(drvinfo->driver, e1000_driver_name, 32); | 563 | strncpy(drvinfo->driver, e1000_driver_name, 32); |
553 | strncpy(drvinfo->version, e1000_driver_version, 32); | 564 | strncpy(drvinfo->version, e1000_driver_version, 32); |
@@ -563,7 +574,7 @@ static void | |||
563 | e1000_get_ringparam(struct net_device *netdev, | 574 | e1000_get_ringparam(struct net_device *netdev, |
564 | struct ethtool_ringparam *ring) | 575 | struct ethtool_ringparam *ring) |
565 | { | 576 | { |
566 | struct e1000_adapter *adapter = netdev->priv; | 577 | struct e1000_adapter *adapter = netdev_priv(netdev); |
567 | e1000_mac_type mac_type = adapter->hw.mac_type; | 578 | e1000_mac_type mac_type = adapter->hw.mac_type; |
568 | struct e1000_desc_ring *txdr = &adapter->tx_ring; | 579 | struct e1000_desc_ring *txdr = &adapter->tx_ring; |
569 | struct e1000_desc_ring *rxdr = &adapter->rx_ring; | 580 | struct e1000_desc_ring *rxdr = &adapter->rx_ring; |
@@ -584,7 +595,7 @@ static int | |||
584 | e1000_set_ringparam(struct net_device *netdev, | 595 | e1000_set_ringparam(struct net_device *netdev, |
585 | struct ethtool_ringparam *ring) | 596 | struct ethtool_ringparam *ring) |
586 | { | 597 | { |
587 | struct e1000_adapter *adapter = netdev->priv; | 598 | struct e1000_adapter *adapter = netdev_priv(netdev); |
588 | e1000_mac_type mac_type = adapter->hw.mac_type; | 599 | e1000_mac_type mac_type = adapter->hw.mac_type; |
589 | struct e1000_desc_ring *txdr = &adapter->tx_ring; | 600 | struct e1000_desc_ring *txdr = &adapter->tx_ring; |
590 | struct e1000_desc_ring *rxdr = &adapter->rx_ring; | 601 | struct e1000_desc_ring *rxdr = &adapter->rx_ring; |
@@ -651,6 +662,9 @@ err_setup_rx: | |||
651 | E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ | 662 | E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ |
652 | value = E1000_READ_REG(&adapter->hw, R); \ | 663 | value = E1000_READ_REG(&adapter->hw, R); \ |
653 | if(value != (test[pat] & W & M)) { \ | 664 | if(value != (test[pat] & W & M)) { \ |
665 | DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \ | ||
666 | "0x%08X expected 0x%08X\n", \ | ||
667 | E1000_##R, value, (test[pat] & W & M)); \ | ||
654 | *data = (adapter->hw.mac_type < e1000_82543) ? \ | 668 | *data = (adapter->hw.mac_type < e1000_82543) ? \ |
655 | E1000_82542_##R : E1000_##R; \ | 669 | E1000_82542_##R : E1000_##R; \ |
656 | return 1; \ | 670 | return 1; \ |
@@ -663,7 +677,9 @@ err_setup_rx: | |||
663 | uint32_t value; \ | 677 | uint32_t value; \ |
664 | E1000_WRITE_REG(&adapter->hw, R, W & M); \ | 678 | E1000_WRITE_REG(&adapter->hw, R, W & M); \ |
665 | value = E1000_READ_REG(&adapter->hw, R); \ | 679 | value = E1000_READ_REG(&adapter->hw, R); \ |
666 | if ((W & M) != (value & M)) { \ | 680 | if((W & M) != (value & M)) { \ |
681 | DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ | ||
682 | "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \ | ||
667 | *data = (adapter->hw.mac_type < e1000_82543) ? \ | 683 | *data = (adapter->hw.mac_type < e1000_82543) ? \ |
668 | E1000_82542_##R : E1000_##R; \ | 684 | E1000_82542_##R : E1000_##R; \ |
669 | return 1; \ | 685 | return 1; \ |
@@ -673,18 +689,33 @@ err_setup_rx: | |||
673 | static int | 689 | static int |
674 | e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) | 690 | e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) |
675 | { | 691 | { |
676 | uint32_t value; | 692 | uint32_t value, before, after; |
677 | uint32_t i; | 693 | uint32_t i, toggle; |
678 | 694 | ||
679 | /* The status register is Read Only, so a write should fail. | 695 | /* The status register is Read Only, so a write should fail. |
680 | * Some bits that get toggled are ignored. | 696 | * Some bits that get toggled are ignored. |
681 | */ | 697 | */ |
682 | value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833)); | 698 | switch (adapter->hw.mac_type) { |
683 | E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF)); | 699 | case e1000_82573: |
684 | if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) { | 700 | toggle = 0x7FFFF033; |
701 | break; | ||
702 | default: | ||
703 | toggle = 0xFFFFF833; | ||
704 | break; | ||
705 | } | ||
706 | |||
707 | before = E1000_READ_REG(&adapter->hw, STATUS); | ||
708 | value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle); | ||
709 | E1000_WRITE_REG(&adapter->hw, STATUS, toggle); | ||
710 | after = E1000_READ_REG(&adapter->hw, STATUS) & toggle; | ||
711 | if(value != after) { | ||
712 | DPRINTK(DRV, ERR, "failed STATUS register test got: " | ||
713 | "0x%08X expected: 0x%08X\n", after, value); | ||
685 | *data = 1; | 714 | *data = 1; |
686 | return 1; | 715 | return 1; |
687 | } | 716 | } |
717 | /* restore previous status */ | ||
718 | E1000_WRITE_REG(&adapter->hw, STATUS, before); | ||
688 | 719 | ||
689 | REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF); | 720 | REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF); |
690 | REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF); | 721 | REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF); |
@@ -766,7 +797,7 @@ e1000_test_intr(int irq, | |||
766 | struct pt_regs *regs) | 797 | struct pt_regs *regs) |
767 | { | 798 | { |
768 | struct net_device *netdev = (struct net_device *) data; | 799 | struct net_device *netdev = (struct net_device *) data; |
769 | struct e1000_adapter *adapter = netdev->priv; | 800 | struct e1000_adapter *adapter = netdev_priv(netdev); |
770 | 801 | ||
771 | adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR); | 802 | adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR); |
772 | 803 | ||
@@ -1214,6 +1245,7 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter) | |||
1214 | case e1000_82541_rev_2: | 1245 | case e1000_82541_rev_2: |
1215 | case e1000_82547: | 1246 | case e1000_82547: |
1216 | case e1000_82547_rev_2: | 1247 | case e1000_82547_rev_2: |
1248 | case e1000_82573: | ||
1217 | return e1000_integrated_phy_loopback(adapter); | 1249 | return e1000_integrated_phy_loopback(adapter); |
1218 | break; | 1250 | break; |
1219 | 1251 | ||
@@ -1422,7 +1454,7 @@ static void | |||
1422 | e1000_diag_test(struct net_device *netdev, | 1454 | e1000_diag_test(struct net_device *netdev, |
1423 | struct ethtool_test *eth_test, uint64_t *data) | 1455 | struct ethtool_test *eth_test, uint64_t *data) |
1424 | { | 1456 | { |
1425 | struct e1000_adapter *adapter = netdev->priv; | 1457 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1426 | boolean_t if_running = netif_running(netdev); | 1458 | boolean_t if_running = netif_running(netdev); |
1427 | 1459 | ||
1428 | if(eth_test->flags == ETH_TEST_FL_OFFLINE) { | 1460 | if(eth_test->flags == ETH_TEST_FL_OFFLINE) { |
@@ -1482,7 +1514,7 @@ e1000_diag_test(struct net_device *netdev, | |||
1482 | static void | 1514 | static void |
1483 | e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | 1515 | e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) |
1484 | { | 1516 | { |
1485 | struct e1000_adapter *adapter = netdev->priv; | 1517 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1486 | struct e1000_hw *hw = &adapter->hw; | 1518 | struct e1000_hw *hw = &adapter->hw; |
1487 | 1519 | ||
1488 | switch(adapter->hw.device_id) { | 1520 | switch(adapter->hw.device_id) { |
@@ -1527,7 +1559,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
1527 | static int | 1559 | static int |
1528 | e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | 1560 | e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) |
1529 | { | 1561 | { |
1530 | struct e1000_adapter *adapter = netdev->priv; | 1562 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1531 | struct e1000_hw *hw = &adapter->hw; | 1563 | struct e1000_hw *hw = &adapter->hw; |
1532 | 1564 | ||
1533 | switch(adapter->hw.device_id) { | 1565 | switch(adapter->hw.device_id) { |
@@ -1588,22 +1620,31 @@ e1000_led_blink_callback(unsigned long data) | |||
1588 | static int | 1620 | static int |
1589 | e1000_phys_id(struct net_device *netdev, uint32_t data) | 1621 | e1000_phys_id(struct net_device *netdev, uint32_t data) |
1590 | { | 1622 | { |
1591 | struct e1000_adapter *adapter = netdev->priv; | 1623 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1592 | 1624 | ||
1593 | if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) | 1625 | if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) |
1594 | data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); | 1626 | data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); |
1595 | 1627 | ||
1596 | if(!adapter->blink_timer.function) { | 1628 | if(adapter->hw.mac_type < e1000_82573) { |
1597 | init_timer(&adapter->blink_timer); | 1629 | if(!adapter->blink_timer.function) { |
1598 | adapter->blink_timer.function = e1000_led_blink_callback; | 1630 | init_timer(&adapter->blink_timer); |
1599 | adapter->blink_timer.data = (unsigned long) adapter; | 1631 | adapter->blink_timer.function = e1000_led_blink_callback; |
1632 | adapter->blink_timer.data = (unsigned long) adapter; | ||
1633 | } | ||
1634 | e1000_setup_led(&adapter->hw); | ||
1635 | mod_timer(&adapter->blink_timer, jiffies); | ||
1636 | msleep_interruptible(data * 1000); | ||
1637 | del_timer_sync(&adapter->blink_timer); | ||
1638 | } | ||
1639 | else { | ||
1640 | E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE | | ||
1641 | E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK | | ||
1642 | (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) | | ||
1643 | (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) | | ||
1644 | (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT))); | ||
1645 | msleep_interruptible(data * 1000); | ||
1600 | } | 1646 | } |
1601 | 1647 | ||
1602 | e1000_setup_led(&adapter->hw); | ||
1603 | mod_timer(&adapter->blink_timer, jiffies); | ||
1604 | |||
1605 | msleep_interruptible(data * 1000); | ||
1606 | del_timer_sync(&adapter->blink_timer); | ||
1607 | e1000_led_off(&adapter->hw); | 1648 | e1000_led_off(&adapter->hw); |
1608 | clear_bit(E1000_LED_ON, &adapter->led_status); | 1649 | clear_bit(E1000_LED_ON, &adapter->led_status); |
1609 | e1000_cleanup_led(&adapter->hw); | 1650 | e1000_cleanup_led(&adapter->hw); |
@@ -1614,7 +1655,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data) | |||
1614 | static int | 1655 | static int |
1615 | e1000_nway_reset(struct net_device *netdev) | 1656 | e1000_nway_reset(struct net_device *netdev) |
1616 | { | 1657 | { |
1617 | struct e1000_adapter *adapter = netdev->priv; | 1658 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1618 | if(netif_running(netdev)) { | 1659 | if(netif_running(netdev)) { |
1619 | e1000_down(adapter); | 1660 | e1000_down(adapter); |
1620 | e1000_up(adapter); | 1661 | e1000_up(adapter); |
@@ -1632,7 +1673,7 @@ static void | |||
1632 | e1000_get_ethtool_stats(struct net_device *netdev, | 1673 | e1000_get_ethtool_stats(struct net_device *netdev, |
1633 | struct ethtool_stats *stats, uint64_t *data) | 1674 | struct ethtool_stats *stats, uint64_t *data) |
1634 | { | 1675 | { |
1635 | struct e1000_adapter *adapter = netdev->priv; | 1676 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1636 | int i; | 1677 | int i; |
1637 | 1678 | ||
1638 | e1000_update_stats(adapter); | 1679 | e1000_update_stats(adapter); |
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 723589b28be5..045f5426ab9a 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c | |||
@@ -354,18 +354,27 @@ e1000_set_media_type(struct e1000_hw *hw) | |||
354 | hw->media_type = e1000_media_type_internal_serdes; | 354 | hw->media_type = e1000_media_type_internal_serdes; |
355 | break; | 355 | break; |
356 | default: | 356 | default: |
357 | if(hw->mac_type >= e1000_82543) { | 357 | switch (hw->mac_type) { |
358 | case e1000_82542_rev2_0: | ||
359 | case e1000_82542_rev2_1: | ||
360 | hw->media_type = e1000_media_type_fiber; | ||
361 | break; | ||
362 | case e1000_82573: | ||
363 | /* The STATUS_TBIMODE bit is reserved or reused for the this | ||
364 | * device. | ||
365 | */ | ||
366 | hw->media_type = e1000_media_type_copper; | ||
367 | break; | ||
368 | default: | ||
358 | status = E1000_READ_REG(hw, STATUS); | 369 | status = E1000_READ_REG(hw, STATUS); |
359 | if(status & E1000_STATUS_TBIMODE) { | 370 | if (status & E1000_STATUS_TBIMODE) { |
360 | hw->media_type = e1000_media_type_fiber; | 371 | hw->media_type = e1000_media_type_fiber; |
361 | /* tbi_compatibility not valid on fiber */ | 372 | /* tbi_compatibility not valid on fiber */ |
362 | hw->tbi_compatibility_en = FALSE; | 373 | hw->tbi_compatibility_en = FALSE; |
363 | } else { | 374 | } else { |
364 | hw->media_type = e1000_media_type_copper; | 375 | hw->media_type = e1000_media_type_copper; |
365 | } | 376 | } |
366 | } else { | 377 | break; |
367 | /* This is an 82542 (fiber only) */ | ||
368 | hw->media_type = e1000_media_type_fiber; | ||
369 | } | 378 | } |
370 | } | 379 | } |
371 | } | 380 | } |
@@ -1189,9 +1198,9 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw) | |||
1189 | ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); | 1198 | ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); |
1190 | if(ret_val) | 1199 | if(ret_val) |
1191 | return ret_val; | 1200 | return ret_val; |
1192 | } | 1201 | } |
1193 | 1202 | ||
1194 | return E1000_SUCCESS; | 1203 | return E1000_SUCCESS; |
1195 | } | 1204 | } |
1196 | 1205 | ||
1197 | 1206 | ||
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index a0263ee96c6b..93e9f8788751 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h | |||
@@ -66,6 +66,7 @@ typedef enum { | |||
66 | e1000_eeprom_spi, | 66 | e1000_eeprom_spi, |
67 | e1000_eeprom_microwire, | 67 | e1000_eeprom_microwire, |
68 | e1000_eeprom_flash, | 68 | e1000_eeprom_flash, |
69 | e1000_eeprom_none, /* No NVM support */ | ||
69 | e1000_num_eeprom_types | 70 | e1000_num_eeprom_types |
70 | } e1000_eeprom_type; | 71 | } e1000_eeprom_type; |
71 | 72 | ||
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 137226d98d47..cb7f051a60ad 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include "e1000.h" | 29 | #include "e1000.h" |
30 | 30 | ||
31 | /* Change Log | 31 | /* Change Log |
32 | * 6.0.58 4/20/05 | ||
33 | * o Accepted ethtool cleanup patch from Stephen Hemminger | ||
32 | * 6.0.44+ 2/15/05 | 34 | * 6.0.44+ 2/15/05 |
33 | * o applied Anton's patch to resolve tx hang in hardware | 35 | * o applied Anton's patch to resolve tx hang in hardware |
34 | * o Applied Andrew Mortons patch - e1000 stops working after resume | 36 | * o Applied Andrew Mortons patch - e1000 stops working after resume |
@@ -41,9 +43,9 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; | |||
41 | #else | 43 | #else |
42 | #define DRIVERNAPI "-NAPI" | 44 | #define DRIVERNAPI "-NAPI" |
43 | #endif | 45 | #endif |
44 | #define DRV_VERSION "6.0.54-k2"DRIVERNAPI | 46 | #define DRV_VERSION "6.0.60-k2"DRIVERNAPI |
45 | char e1000_driver_version[] = DRV_VERSION; | 47 | char e1000_driver_version[] = DRV_VERSION; |
46 | char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation."; | 48 | char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; |
47 | 49 | ||
48 | /* e1000_pci_tbl - PCI Device ID Table | 50 | /* e1000_pci_tbl - PCI Device ID Table |
49 | * | 51 | * |
@@ -517,7 +519,7 @@ e1000_probe(struct pci_dev *pdev, | |||
517 | SET_NETDEV_DEV(netdev, &pdev->dev); | 519 | SET_NETDEV_DEV(netdev, &pdev->dev); |
518 | 520 | ||
519 | pci_set_drvdata(pdev, netdev); | 521 | pci_set_drvdata(pdev, netdev); |
520 | adapter = netdev->priv; | 522 | adapter = netdev_priv(netdev); |
521 | adapter->netdev = netdev; | 523 | adapter->netdev = netdev; |
522 | adapter->pdev = pdev; | 524 | adapter->pdev = pdev; |
523 | adapter->hw.back = adapter; | 525 | adapter->hw.back = adapter; |
@@ -738,7 +740,7 @@ static void __devexit | |||
738 | e1000_remove(struct pci_dev *pdev) | 740 | e1000_remove(struct pci_dev *pdev) |
739 | { | 741 | { |
740 | struct net_device *netdev = pci_get_drvdata(pdev); | 742 | struct net_device *netdev = pci_get_drvdata(pdev); |
741 | struct e1000_adapter *adapter = netdev->priv; | 743 | struct e1000_adapter *adapter = netdev_priv(netdev); |
742 | uint32_t manc, swsm; | 744 | uint32_t manc, swsm; |
743 | 745 | ||
744 | flush_scheduled_work(); | 746 | flush_scheduled_work(); |
@@ -871,7 +873,7 @@ e1000_sw_init(struct e1000_adapter *adapter) | |||
871 | static int | 873 | static int |
872 | e1000_open(struct net_device *netdev) | 874 | e1000_open(struct net_device *netdev) |
873 | { | 875 | { |
874 | struct e1000_adapter *adapter = netdev->priv; | 876 | struct e1000_adapter *adapter = netdev_priv(netdev); |
875 | int err; | 877 | int err; |
876 | 878 | ||
877 | /* allocate transmit descriptors */ | 879 | /* allocate transmit descriptors */ |
@@ -919,7 +921,7 @@ err_setup_tx: | |||
919 | static int | 921 | static int |
920 | e1000_close(struct net_device *netdev) | 922 | e1000_close(struct net_device *netdev) |
921 | { | 923 | { |
922 | struct e1000_adapter *adapter = netdev->priv; | 924 | struct e1000_adapter *adapter = netdev_priv(netdev); |
923 | 925 | ||
924 | e1000_down(adapter); | 926 | e1000_down(adapter); |
925 | 927 | ||
@@ -1599,7 +1601,7 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter) | |||
1599 | static int | 1601 | static int |
1600 | e1000_set_mac(struct net_device *netdev, void *p) | 1602 | e1000_set_mac(struct net_device *netdev, void *p) |
1601 | { | 1603 | { |
1602 | struct e1000_adapter *adapter = netdev->priv; | 1604 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1603 | struct sockaddr *addr = p; | 1605 | struct sockaddr *addr = p; |
1604 | 1606 | ||
1605 | if(!is_valid_ether_addr(addr->sa_data)) | 1607 | if(!is_valid_ether_addr(addr->sa_data)) |
@@ -1634,7 +1636,7 @@ e1000_set_mac(struct net_device *netdev, void *p) | |||
1634 | static void | 1636 | static void |
1635 | e1000_set_multi(struct net_device *netdev) | 1637 | e1000_set_multi(struct net_device *netdev) |
1636 | { | 1638 | { |
1637 | struct e1000_adapter *adapter = netdev->priv; | 1639 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1638 | struct e1000_hw *hw = &adapter->hw; | 1640 | struct e1000_hw *hw = &adapter->hw; |
1639 | struct dev_mc_list *mc_ptr; | 1641 | struct dev_mc_list *mc_ptr; |
1640 | unsigned long flags; | 1642 | unsigned long flags; |
@@ -2213,7 +2215,7 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb) | |||
2213 | static int | 2215 | static int |
2214 | e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | 2216 | e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) |
2215 | { | 2217 | { |
2216 | struct e1000_adapter *adapter = netdev->priv; | 2218 | struct e1000_adapter *adapter = netdev_priv(netdev); |
2217 | unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; | 2219 | unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; |
2218 | unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; | 2220 | unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; |
2219 | unsigned int tx_flags = 0; | 2221 | unsigned int tx_flags = 0; |
@@ -2344,7 +2346,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
2344 | static void | 2346 | static void |
2345 | e1000_tx_timeout(struct net_device *netdev) | 2347 | e1000_tx_timeout(struct net_device *netdev) |
2346 | { | 2348 | { |
2347 | struct e1000_adapter *adapter = netdev->priv; | 2349 | struct e1000_adapter *adapter = netdev_priv(netdev); |
2348 | 2350 | ||
2349 | /* Do the reset outside of interrupt context */ | 2351 | /* Do the reset outside of interrupt context */ |
2350 | schedule_work(&adapter->tx_timeout_task); | 2352 | schedule_work(&adapter->tx_timeout_task); |
@@ -2353,7 +2355,7 @@ e1000_tx_timeout(struct net_device *netdev) | |||
2353 | static void | 2355 | static void |
2354 | e1000_tx_timeout_task(struct net_device *netdev) | 2356 | e1000_tx_timeout_task(struct net_device *netdev) |
2355 | { | 2357 | { |
2356 | struct e1000_adapter *adapter = netdev->priv; | 2358 | struct e1000_adapter *adapter = netdev_priv(netdev); |
2357 | 2359 | ||
2358 | e1000_down(adapter); | 2360 | e1000_down(adapter); |
2359 | e1000_up(adapter); | 2361 | e1000_up(adapter); |
@@ -2370,7 +2372,7 @@ e1000_tx_timeout_task(struct net_device *netdev) | |||
2370 | static struct net_device_stats * | 2372 | static struct net_device_stats * |
2371 | e1000_get_stats(struct net_device *netdev) | 2373 | e1000_get_stats(struct net_device *netdev) |
2372 | { | 2374 | { |
2373 | struct e1000_adapter *adapter = netdev->priv; | 2375 | struct e1000_adapter *adapter = netdev_priv(netdev); |
2374 | 2376 | ||
2375 | e1000_update_stats(adapter); | 2377 | e1000_update_stats(adapter); |
2376 | return &adapter->net_stats; | 2378 | return &adapter->net_stats; |
@@ -2387,7 +2389,7 @@ e1000_get_stats(struct net_device *netdev) | |||
2387 | static int | 2389 | static int |
2388 | e1000_change_mtu(struct net_device *netdev, int new_mtu) | 2390 | e1000_change_mtu(struct net_device *netdev, int new_mtu) |
2389 | { | 2391 | { |
2390 | struct e1000_adapter *adapter = netdev->priv; | 2392 | struct e1000_adapter *adapter = netdev_priv(netdev); |
2391 | int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; | 2393 | int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; |
2392 | 2394 | ||
2393 | if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || | 2395 | if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || |
@@ -2598,7 +2600,7 @@ static irqreturn_t | |||
2598 | e1000_intr(int irq, void *data, struct pt_regs *regs) | 2600 | e1000_intr(int irq, void *data, struct pt_regs *regs) |
2599 | { | 2601 | { |
2600 | struct net_device *netdev = data; | 2602 | struct net_device *netdev = data; |
2601 | struct e1000_adapter *adapter = netdev->priv; | 2603 | struct e1000_adapter *adapter = netdev_priv(netdev); |
2602 | struct e1000_hw *hw = &adapter->hw; | 2604 | struct e1000_hw *hw = &adapter->hw; |
2603 | uint32_t icr = E1000_READ_REG(hw, ICR); | 2605 | uint32_t icr = E1000_READ_REG(hw, ICR); |
2604 | #ifndef CONFIG_E1000_NAPI | 2606 | #ifndef CONFIG_E1000_NAPI |
@@ -2661,7 +2663,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) | |||
2661 | static int | 2663 | static int |
2662 | e1000_clean(struct net_device *netdev, int *budget) | 2664 | e1000_clean(struct net_device *netdev, int *budget) |
2663 | { | 2665 | { |
2664 | struct e1000_adapter *adapter = netdev->priv; | 2666 | struct e1000_adapter *adapter = netdev_priv(netdev); |
2665 | int work_to_do = min(*budget, netdev->quota); | 2667 | int work_to_do = min(*budget, netdev->quota); |
2666 | int tx_cleaned; | 2668 | int tx_cleaned; |
2667 | int work_done = 0; | 2669 | int work_done = 0; |
@@ -2672,8 +2674,8 @@ e1000_clean(struct net_device *netdev, int *budget) | |||
2672 | *budget -= work_done; | 2674 | *budget -= work_done; |
2673 | netdev->quota -= work_done; | 2675 | netdev->quota -= work_done; |
2674 | 2676 | ||
2675 | /* If no Tx and no Rx work done, exit the polling mode */ | ||
2676 | if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { | 2677 | if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { |
2678 | /* If no Tx and not enough Rx work done, exit the polling mode */ | ||
2677 | netif_rx_complete(netdev); | 2679 | netif_rx_complete(netdev); |
2678 | e1000_irq_enable(adapter); | 2680 | e1000_irq_enable(adapter); |
2679 | return 0; | 2681 | return 0; |
@@ -2769,13 +2771,13 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||
2769 | i = tx_ring->next_to_clean; | 2771 | i = tx_ring->next_to_clean; |
2770 | eop = tx_ring->buffer_info[i].next_to_watch; | 2772 | eop = tx_ring->buffer_info[i].next_to_watch; |
2771 | eop_desc = E1000_TX_DESC(*tx_ring, eop); | 2773 | eop_desc = E1000_TX_DESC(*tx_ring, eop); |
2772 | DPRINTK(TX_ERR, ERR, "Detected Tx Unit Hang\n" | 2774 | DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" |
2773 | " TDH <%x>\n" | 2775 | " TDH <%x>\n" |
2774 | " TDT <%x>\n" | 2776 | " TDT <%x>\n" |
2775 | " next_to_use <%x>\n" | 2777 | " next_to_use <%x>\n" |
2776 | " next_to_clean <%x>\n" | 2778 | " next_to_clean <%x>\n" |
2777 | "buffer_info[next_to_clean]\n" | 2779 | "buffer_info[next_to_clean]\n" |
2778 | " dma <%llx>\n" | 2780 | " dma <%zx>\n" |
2779 | " time_stamp <%lx>\n" | 2781 | " time_stamp <%lx>\n" |
2780 | " next_to_watch <%x>\n" | 2782 | " next_to_watch <%x>\n" |
2781 | " jiffies <%lx>\n" | 2783 | " jiffies <%lx>\n" |
@@ -2994,7 +2996,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) | |||
2994 | 2996 | ||
2995 | i = rx_ring->next_to_clean; | 2997 | i = rx_ring->next_to_clean; |
2996 | rx_desc = E1000_RX_DESC_PS(*rx_ring, i); | 2998 | rx_desc = E1000_RX_DESC_PS(*rx_ring, i); |
2997 | staterr = rx_desc->wb.middle.status_error; | 2999 | staterr = le32_to_cpu(rx_desc->wb.middle.status_error); |
2998 | 3000 | ||
2999 | while(staterr & E1000_RXD_STAT_DD) { | 3001 | while(staterr & E1000_RXD_STAT_DD) { |
3000 | buffer_info = &rx_ring->buffer_info[i]; | 3002 | buffer_info = &rx_ring->buffer_info[i]; |
@@ -3065,16 +3067,16 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) | |||
3065 | #ifdef CONFIG_E1000_NAPI | 3067 | #ifdef CONFIG_E1000_NAPI |
3066 | if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { | 3068 | if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { |
3067 | vlan_hwaccel_receive_skb(skb, adapter->vlgrp, | 3069 | vlan_hwaccel_receive_skb(skb, adapter->vlgrp, |
3068 | le16_to_cpu(rx_desc->wb.middle.vlan & | 3070 | le16_to_cpu(rx_desc->wb.middle.vlan) & |
3069 | E1000_RXD_SPC_VLAN_MASK)); | 3071 | E1000_RXD_SPC_VLAN_MASK); |
3070 | } else { | 3072 | } else { |
3071 | netif_receive_skb(skb); | 3073 | netif_receive_skb(skb); |
3072 | } | 3074 | } |
3073 | #else /* CONFIG_E1000_NAPI */ | 3075 | #else /* CONFIG_E1000_NAPI */ |
3074 | if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { | 3076 | if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { |
3075 | vlan_hwaccel_rx(skb, adapter->vlgrp, | 3077 | vlan_hwaccel_rx(skb, adapter->vlgrp, |
3076 | le16_to_cpu(rx_desc->wb.middle.vlan & | 3078 | le16_to_cpu(rx_desc->wb.middle.vlan) & |
3077 | E1000_RXD_SPC_VLAN_MASK)); | 3079 | E1000_RXD_SPC_VLAN_MASK); |
3078 | } else { | 3080 | } else { |
3079 | netif_rx(skb); | 3081 | netif_rx(skb); |
3080 | } | 3082 | } |
@@ -3087,7 +3089,7 @@ next_desc: | |||
3087 | if(unlikely(++i == rx_ring->count)) i = 0; | 3089 | if(unlikely(++i == rx_ring->count)) i = 0; |
3088 | 3090 | ||
3089 | rx_desc = E1000_RX_DESC_PS(*rx_ring, i); | 3091 | rx_desc = E1000_RX_DESC_PS(*rx_ring, i); |
3090 | staterr = rx_desc->wb.middle.status_error; | 3092 | staterr = le32_to_cpu(rx_desc->wb.middle.status_error); |
3091 | } | 3093 | } |
3092 | rx_ring->next_to_clean = i; | 3094 | rx_ring->next_to_clean = i; |
3093 | adapter->alloc_rx_buf(adapter); | 3095 | adapter->alloc_rx_buf(adapter); |
@@ -3371,11 +3373,12 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
3371 | static int | 3373 | static int |
3372 | e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | 3374 | e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) |
3373 | { | 3375 | { |
3374 | struct e1000_adapter *adapter = netdev->priv; | 3376 | struct e1000_adapter *adapter = netdev_priv(netdev); |
3375 | struct mii_ioctl_data *data = if_mii(ifr); | 3377 | struct mii_ioctl_data *data = if_mii(ifr); |
3376 | int retval; | 3378 | int retval; |
3377 | uint16_t mii_reg; | 3379 | uint16_t mii_reg; |
3378 | uint16_t spddplx; | 3380 | uint16_t spddplx; |
3381 | unsigned long flags; | ||
3379 | 3382 | ||
3380 | if(adapter->hw.media_type != e1000_media_type_copper) | 3383 | if(adapter->hw.media_type != e1000_media_type_copper) |
3381 | return -EOPNOTSUPP; | 3384 | return -EOPNOTSUPP; |
@@ -3385,22 +3388,29 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
3385 | data->phy_id = adapter->hw.phy_addr; | 3388 | data->phy_id = adapter->hw.phy_addr; |
3386 | break; | 3389 | break; |
3387 | case SIOCGMIIREG: | 3390 | case SIOCGMIIREG: |
3388 | if (!capable(CAP_NET_ADMIN)) | 3391 | if(!capable(CAP_NET_ADMIN)) |
3389 | return -EPERM; | 3392 | return -EPERM; |
3390 | if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, | 3393 | spin_lock_irqsave(&adapter->stats_lock, flags); |
3391 | &data->val_out)) | 3394 | if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, |
3395 | &data->val_out)) { | ||
3396 | spin_unlock_irqrestore(&adapter->stats_lock, flags); | ||
3392 | return -EIO; | 3397 | return -EIO; |
3398 | } | ||
3399 | spin_unlock_irqrestore(&adapter->stats_lock, flags); | ||
3393 | break; | 3400 | break; |
3394 | case SIOCSMIIREG: | 3401 | case SIOCSMIIREG: |
3395 | if (!capable(CAP_NET_ADMIN)) | 3402 | if(!capable(CAP_NET_ADMIN)) |
3396 | return -EPERM; | 3403 | return -EPERM; |
3397 | if (data->reg_num & ~(0x1F)) | 3404 | if(data->reg_num & ~(0x1F)) |
3398 | return -EFAULT; | 3405 | return -EFAULT; |
3399 | mii_reg = data->val_in; | 3406 | mii_reg = data->val_in; |
3400 | if (e1000_write_phy_reg(&adapter->hw, data->reg_num, | 3407 | spin_lock_irqsave(&adapter->stats_lock, flags); |
3401 | mii_reg)) | 3408 | if(e1000_write_phy_reg(&adapter->hw, data->reg_num, |
3409 | mii_reg)) { | ||
3410 | spin_unlock_irqrestore(&adapter->stats_lock, flags); | ||
3402 | return -EIO; | 3411 | return -EIO; |
3403 | if (adapter->hw.phy_type == e1000_phy_m88) { | 3412 | } |
3413 | if(adapter->hw.phy_type == e1000_phy_m88) { | ||
3404 | switch (data->reg_num) { | 3414 | switch (data->reg_num) { |
3405 | case PHY_CTRL: | 3415 | case PHY_CTRL: |
3406 | if(mii_reg & MII_CR_POWER_DOWN) | 3416 | if(mii_reg & MII_CR_POWER_DOWN) |
@@ -3420,8 +3430,12 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
3420 | HALF_DUPLEX; | 3430 | HALF_DUPLEX; |
3421 | retval = e1000_set_spd_dplx(adapter, | 3431 | retval = e1000_set_spd_dplx(adapter, |
3422 | spddplx); | 3432 | spddplx); |
3423 | if(retval) | 3433 | if(retval) { |
3434 | spin_unlock_irqrestore( | ||
3435 | &adapter->stats_lock, | ||
3436 | flags); | ||
3424 | return retval; | 3437 | return retval; |
3438 | } | ||
3425 | } | 3439 | } |
3426 | if(netif_running(adapter->netdev)) { | 3440 | if(netif_running(adapter->netdev)) { |
3427 | e1000_down(adapter); | 3441 | e1000_down(adapter); |
@@ -3431,8 +3445,11 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
3431 | break; | 3445 | break; |
3432 | case M88E1000_PHY_SPEC_CTRL: | 3446 | case M88E1000_PHY_SPEC_CTRL: |
3433 | case M88E1000_EXT_PHY_SPEC_CTRL: | 3447 | case M88E1000_EXT_PHY_SPEC_CTRL: |
3434 | if (e1000_phy_reset(&adapter->hw)) | 3448 | if(e1000_phy_reset(&adapter->hw)) { |
3449 | spin_unlock_irqrestore( | ||
3450 | &adapter->stats_lock, flags); | ||
3435 | return -EIO; | 3451 | return -EIO; |
3452 | } | ||
3436 | break; | 3453 | break; |
3437 | } | 3454 | } |
3438 | } else { | 3455 | } else { |
@@ -3448,6 +3465,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
3448 | break; | 3465 | break; |
3449 | } | 3466 | } |
3450 | } | 3467 | } |
3468 | spin_unlock_irqrestore(&adapter->stats_lock, flags); | ||
3451 | break; | 3469 | break; |
3452 | default: | 3470 | default: |
3453 | return -EOPNOTSUPP; | 3471 | return -EOPNOTSUPP; |
@@ -3504,7 +3522,7 @@ e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value) | |||
3504 | static void | 3522 | static void |
3505 | e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) | 3523 | e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) |
3506 | { | 3524 | { |
3507 | struct e1000_adapter *adapter = netdev->priv; | 3525 | struct e1000_adapter *adapter = netdev_priv(netdev); |
3508 | uint32_t ctrl, rctl; | 3526 | uint32_t ctrl, rctl; |
3509 | 3527 | ||
3510 | e1000_irq_disable(adapter); | 3528 | e1000_irq_disable(adapter); |
@@ -3544,7 +3562,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) | |||
3544 | static void | 3562 | static void |
3545 | e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) | 3563 | e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) |
3546 | { | 3564 | { |
3547 | struct e1000_adapter *adapter = netdev->priv; | 3565 | struct e1000_adapter *adapter = netdev_priv(netdev); |
3548 | uint32_t vfta, index; | 3566 | uint32_t vfta, index; |
3549 | if((adapter->hw.mng_cookie.status & | 3567 | if((adapter->hw.mng_cookie.status & |
3550 | E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && | 3568 | E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && |
@@ -3560,7 +3578,7 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) | |||
3560 | static void | 3578 | static void |
3561 | e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) | 3579 | e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) |
3562 | { | 3580 | { |
3563 | struct e1000_adapter *adapter = netdev->priv; | 3581 | struct e1000_adapter *adapter = netdev_priv(netdev); |
3564 | uint32_t vfta, index; | 3582 | uint32_t vfta, index; |
3565 | 3583 | ||
3566 | e1000_irq_disable(adapter); | 3584 | e1000_irq_disable(adapter); |
@@ -3601,6 +3619,13 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) | |||
3601 | { | 3619 | { |
3602 | adapter->hw.autoneg = 0; | 3620 | adapter->hw.autoneg = 0; |
3603 | 3621 | ||
3622 | /* Fiber NICs only allow 1000 gbps Full duplex */ | ||
3623 | if((adapter->hw.media_type == e1000_media_type_fiber) && | ||
3624 | spddplx != (SPEED_1000 + DUPLEX_FULL)) { | ||
3625 | DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); | ||
3626 | return -EINVAL; | ||
3627 | } | ||
3628 | |||
3604 | switch(spddplx) { | 3629 | switch(spddplx) { |
3605 | case SPEED_10 + DUPLEX_HALF: | 3630 | case SPEED_10 + DUPLEX_HALF: |
3606 | adapter->hw.forced_speed_duplex = e1000_10_half; | 3631 | adapter->hw.forced_speed_duplex = e1000_10_half; |
@@ -3647,7 +3672,7 @@ static int | |||
3647 | e1000_suspend(struct pci_dev *pdev, uint32_t state) | 3672 | e1000_suspend(struct pci_dev *pdev, uint32_t state) |
3648 | { | 3673 | { |
3649 | struct net_device *netdev = pci_get_drvdata(pdev); | 3674 | struct net_device *netdev = pci_get_drvdata(pdev); |
3650 | struct e1000_adapter *adapter = netdev->priv; | 3675 | struct e1000_adapter *adapter = netdev_priv(netdev); |
3651 | uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; | 3676 | uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; |
3652 | uint32_t wufc = adapter->wol; | 3677 | uint32_t wufc = adapter->wol; |
3653 | 3678 | ||
@@ -3740,12 +3765,12 @@ static int | |||
3740 | e1000_resume(struct pci_dev *pdev) | 3765 | e1000_resume(struct pci_dev *pdev) |
3741 | { | 3766 | { |
3742 | struct net_device *netdev = pci_get_drvdata(pdev); | 3767 | struct net_device *netdev = pci_get_drvdata(pdev); |
3743 | struct e1000_adapter *adapter = netdev->priv; | 3768 | struct e1000_adapter *adapter = netdev_priv(netdev); |
3744 | uint32_t manc, ret, swsm; | 3769 | uint32_t manc, ret_val, swsm; |
3745 | 3770 | ||
3746 | pci_set_power_state(pdev, 0); | 3771 | pci_set_power_state(pdev, 0); |
3747 | pci_restore_state(pdev); | 3772 | pci_restore_state(pdev); |
3748 | ret = pci_enable_device(pdev); | 3773 | ret_val = pci_enable_device(pdev); |
3749 | pci_set_master(pdev); | 3774 | pci_set_master(pdev); |
3750 | 3775 | ||
3751 | pci_enable_wake(pdev, 3, 0); | 3776 | pci_enable_wake(pdev, 3, 0); |
@@ -3788,7 +3813,7 @@ e1000_resume(struct pci_dev *pdev) | |||
3788 | static void | 3813 | static void |
3789 | e1000_netpoll(struct net_device *netdev) | 3814 | e1000_netpoll(struct net_device *netdev) |
3790 | { | 3815 | { |
3791 | struct e1000_adapter *adapter = netdev->priv; | 3816 | struct e1000_adapter *adapter = netdev_priv(netdev); |
3792 | disable_irq(adapter->pdev->irq); | 3817 | disable_irq(adapter->pdev->irq); |
3793 | e1000_intr(adapter->pdev->irq, netdev, NULL); | 3818 | e1000_intr(adapter->pdev->irq, netdev, NULL); |
3794 | enable_irq(adapter->pdev->irq); | 3819 | enable_irq(adapter->pdev->irq); |
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 4ebcd052e150..64f0f697c958 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -82,6 +82,9 @@ | |||
82 | * 0.31: 14 Nov 2004: ethtool support for getting/setting link | 82 | * 0.31: 14 Nov 2004: ethtool support for getting/setting link |
83 | * capabilities. | 83 | * capabilities. |
84 | * 0.32: 16 Apr 2005: RX_ERROR4 handling added. | 84 | * 0.32: 16 Apr 2005: RX_ERROR4 handling added. |
85 | * 0.33: 16 May 2005: Support for MCP51 added. | ||
86 | * 0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics. | ||
87 | * 0.35: 26 Jun 2005: Support for MCP55 added. | ||
85 | * | 88 | * |
86 | * Known bugs: | 89 | * Known bugs: |
87 | * We suspect that on some hardware no TX done interrupts are generated. | 90 | * We suspect that on some hardware no TX done interrupts are generated. |
@@ -93,7 +96,7 @@ | |||
93 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few | 96 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few |
94 | * superfluous timer interrupts from the nic. | 97 | * superfluous timer interrupts from the nic. |
95 | */ | 98 | */ |
96 | #define FORCEDETH_VERSION "0.32" | 99 | #define FORCEDETH_VERSION "0.35" |
97 | #define DRV_NAME "forcedeth" | 100 | #define DRV_NAME "forcedeth" |
98 | 101 | ||
99 | #include <linux/module.h> | 102 | #include <linux/module.h> |
@@ -2005,7 +2008,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2005 | /* handle different descriptor versions */ | 2008 | /* handle different descriptor versions */ |
2006 | if (pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 || | 2009 | if (pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 || |
2007 | pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 || | 2010 | pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 || |
2008 | pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3) | 2011 | pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3 || |
2012 | pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || | ||
2013 | pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) | ||
2009 | np->desc_ver = DESC_VER_1; | 2014 | np->desc_ver = DESC_VER_1; |
2010 | else | 2015 | else |
2011 | np->desc_ver = DESC_VER_2; | 2016 | np->desc_ver = DESC_VER_2; |
@@ -2215,56 +2220,84 @@ static struct pci_device_id pci_tbl[] = { | |||
2215 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_4, | 2220 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_4, |
2216 | .subvendor = PCI_ANY_ID, | 2221 | .subvendor = PCI_ANY_ID, |
2217 | .subdevice = PCI_ANY_ID, | 2222 | .subdevice = PCI_ANY_ID, |
2218 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, | 2223 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, |
2219 | }, | 2224 | }, |
2220 | { /* nForce3 Ethernet Controller */ | 2225 | { /* nForce3 Ethernet Controller */ |
2221 | .vendor = PCI_VENDOR_ID_NVIDIA, | 2226 | .vendor = PCI_VENDOR_ID_NVIDIA, |
2222 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_5, | 2227 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_5, |
2223 | .subvendor = PCI_ANY_ID, | 2228 | .subvendor = PCI_ANY_ID, |
2224 | .subdevice = PCI_ANY_ID, | 2229 | .subdevice = PCI_ANY_ID, |
2225 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, | 2230 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, |
2226 | }, | 2231 | }, |
2227 | { /* nForce3 Ethernet Controller */ | 2232 | { /* nForce3 Ethernet Controller */ |
2228 | .vendor = PCI_VENDOR_ID_NVIDIA, | 2233 | .vendor = PCI_VENDOR_ID_NVIDIA, |
2229 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_6, | 2234 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_6, |
2230 | .subvendor = PCI_ANY_ID, | 2235 | .subvendor = PCI_ANY_ID, |
2231 | .subdevice = PCI_ANY_ID, | 2236 | .subdevice = PCI_ANY_ID, |
2232 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, | 2237 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, |
2233 | }, | 2238 | }, |
2234 | { /* nForce3 Ethernet Controller */ | 2239 | { /* nForce3 Ethernet Controller */ |
2235 | .vendor = PCI_VENDOR_ID_NVIDIA, | 2240 | .vendor = PCI_VENDOR_ID_NVIDIA, |
2236 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_7, | 2241 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_7, |
2237 | .subvendor = PCI_ANY_ID, | 2242 | .subvendor = PCI_ANY_ID, |
2238 | .subdevice = PCI_ANY_ID, | 2243 | .subdevice = PCI_ANY_ID, |
2239 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, | 2244 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, |
2240 | }, | 2245 | }, |
2241 | { /* CK804 Ethernet Controller */ | 2246 | { /* CK804 Ethernet Controller */ |
2242 | .vendor = PCI_VENDOR_ID_NVIDIA, | 2247 | .vendor = PCI_VENDOR_ID_NVIDIA, |
2243 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_8, | 2248 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_8, |
2244 | .subvendor = PCI_ANY_ID, | 2249 | .subvendor = PCI_ANY_ID, |
2245 | .subdevice = PCI_ANY_ID, | 2250 | .subdevice = PCI_ANY_ID, |
2246 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, | 2251 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, |
2247 | }, | 2252 | }, |
2248 | { /* CK804 Ethernet Controller */ | 2253 | { /* CK804 Ethernet Controller */ |
2249 | .vendor = PCI_VENDOR_ID_NVIDIA, | 2254 | .vendor = PCI_VENDOR_ID_NVIDIA, |
2250 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_9, | 2255 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_9, |
2251 | .subvendor = PCI_ANY_ID, | 2256 | .subvendor = PCI_ANY_ID, |
2252 | .subdevice = PCI_ANY_ID, | 2257 | .subdevice = PCI_ANY_ID, |
2253 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, | 2258 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, |
2254 | }, | 2259 | }, |
2255 | { /* MCP04 Ethernet Controller */ | 2260 | { /* MCP04 Ethernet Controller */ |
2256 | .vendor = PCI_VENDOR_ID_NVIDIA, | 2261 | .vendor = PCI_VENDOR_ID_NVIDIA, |
2257 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_10, | 2262 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_10, |
2258 | .subvendor = PCI_ANY_ID, | 2263 | .subvendor = PCI_ANY_ID, |
2259 | .subdevice = PCI_ANY_ID, | 2264 | .subdevice = PCI_ANY_ID, |
2260 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, | 2265 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, |
2261 | }, | 2266 | }, |
2262 | { /* MCP04 Ethernet Controller */ | 2267 | { /* MCP04 Ethernet Controller */ |
2263 | .vendor = PCI_VENDOR_ID_NVIDIA, | 2268 | .vendor = PCI_VENDOR_ID_NVIDIA, |
2264 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_11, | 2269 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_11, |
2265 | .subvendor = PCI_ANY_ID, | 2270 | .subvendor = PCI_ANY_ID, |
2266 | .subdevice = PCI_ANY_ID, | 2271 | .subdevice = PCI_ANY_ID, |
2267 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, | 2272 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, |
2273 | }, | ||
2274 | { /* MCP51 Ethernet Controller */ | ||
2275 | .vendor = PCI_VENDOR_ID_NVIDIA, | ||
2276 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_12, | ||
2277 | .subvendor = PCI_ANY_ID, | ||
2278 | .subdevice = PCI_ANY_ID, | ||
2279 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, | ||
2280 | }, | ||
2281 | { /* MCP51 Ethernet Controller */ | ||
2282 | .vendor = PCI_VENDOR_ID_NVIDIA, | ||
2283 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_13, | ||
2284 | .subvendor = PCI_ANY_ID, | ||
2285 | .subdevice = PCI_ANY_ID, | ||
2286 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, | ||
2287 | }, | ||
2288 | { /* MCP55 Ethernet Controller */ | ||
2289 | .vendor = PCI_VENDOR_ID_NVIDIA, | ||
2290 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_14, | ||
2291 | .subvendor = PCI_ANY_ID, | ||
2292 | .subdevice = PCI_ANY_ID, | ||
2293 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, | ||
2294 | }, | ||
2295 | { /* MCP55 Ethernet Controller */ | ||
2296 | .vendor = PCI_VENDOR_ID_NVIDIA, | ||
2297 | .device = PCI_DEVICE_ID_NVIDIA_NVENET_15, | ||
2298 | .subvendor = PCI_ANY_ID, | ||
2299 | .subdevice = PCI_ANY_ID, | ||
2300 | .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, | ||
2268 | }, | 2301 | }, |
2269 | {0,}, | 2302 | {0,}, |
2270 | }; | 2303 | }; |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index b43b2b11aacd..6518334b9280 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/net/gianfar.c | 2 | * drivers/net/gianfar.c |
3 | * | 3 | * |
4 | * Gianfar Ethernet Driver | 4 | * Gianfar Ethernet Driver |
@@ -22,10 +22,9 @@ | |||
22 | * B-V +1.62 | 22 | * B-V +1.62 |
23 | * | 23 | * |
24 | * Theory of operation | 24 | * Theory of operation |
25 | * This driver is designed for the Triple-speed Ethernet | 25 | * This driver is designed for the non-CPM ethernet controllers |
26 | * controllers on the Freescale 8540/8560 integrated processors, | 26 | * on the 85xx and 83xx family of integrated processors |
27 | * as well as the Fast Ethernet Controller on the 8540. | 27 | * |
28 | * | ||
29 | * The driver is initialized through platform_device. Structures which | 28 | * The driver is initialized through platform_device. Structures which |
30 | * define the configuration needed by the board are defined in a | 29 | * define the configuration needed by the board are defined in a |
31 | * board structure in arch/ppc/platforms (though I do not | 30 | * board structure in arch/ppc/platforms (though I do not |
@@ -39,12 +38,12 @@ | |||
39 | * | 38 | * |
40 | * The Gianfar Ethernet Controller uses a ring of buffer | 39 | * The Gianfar Ethernet Controller uses a ring of buffer |
41 | * descriptors. The beginning is indicated by a register | 40 | * descriptors. The beginning is indicated by a register |
42 | * pointing to the physical address of the start of the ring. | 41 | * pointing to the physical address of the start of the ring. |
43 | * The end is determined by a "wrap" bit being set in the | 42 | * The end is determined by a "wrap" bit being set in the |
44 | * last descriptor of the ring. | 43 | * last descriptor of the ring. |
45 | * | 44 | * |
46 | * When a packet is received, the RXF bit in the | 45 | * When a packet is received, the RXF bit in the |
47 | * IEVENT register is set, triggering an interrupt when the | 46 | * IEVENT register is set, triggering an interrupt when the |
48 | * corresponding bit in the IMASK register is also set (if | 47 | * corresponding bit in the IMASK register is also set (if |
49 | * interrupt coalescing is active, then the interrupt may not | 48 | * interrupt coalescing is active, then the interrupt may not |
50 | * happen immediately, but will wait until either a set number | 49 | * happen immediately, but will wait until either a set number |
@@ -52,7 +51,7 @@ | |||
52 | * interrupt handler will signal there is work to be done, and | 51 | * interrupt handler will signal there is work to be done, and |
53 | * exit. Without NAPI, the packet(s) will be handled | 52 | * exit. Without NAPI, the packet(s) will be handled |
54 | * immediately. Both methods will start at the last known empty | 53 | * immediately. Both methods will start at the last known empty |
55 | * descriptor, and process every subsequent descriptor until there | 54 | * descriptor, and process every subsequent descriptor until there |
56 | * are none left with data (NAPI will stop after a set number of | 55 | * are none left with data (NAPI will stop after a set number of |
57 | * packets to give time to other tasks, but will eventually | 56 | * packets to give time to other tasks, but will eventually |
58 | * process all the packets). The data arrives inside a | 57 | * process all the packets). The data arrives inside a |
@@ -83,9 +82,13 @@ | |||
83 | #include <linux/netdevice.h> | 82 | #include <linux/netdevice.h> |
84 | #include <linux/etherdevice.h> | 83 | #include <linux/etherdevice.h> |
85 | #include <linux/skbuff.h> | 84 | #include <linux/skbuff.h> |
85 | #include <linux/if_vlan.h> | ||
86 | #include <linux/spinlock.h> | 86 | #include <linux/spinlock.h> |
87 | #include <linux/mm.h> | 87 | #include <linux/mm.h> |
88 | #include <linux/device.h> | 88 | #include <linux/device.h> |
89 | #include <linux/ip.h> | ||
90 | #include <linux/tcp.h> | ||
91 | #include <linux/udp.h> | ||
89 | 92 | ||
90 | #include <asm/io.h> | 93 | #include <asm/io.h> |
91 | #include <asm/irq.h> | 94 | #include <asm/irq.h> |
@@ -123,7 +126,7 @@ static int gfar_set_mac_address(struct net_device *dev); | |||
123 | static int gfar_change_mtu(struct net_device *dev, int new_mtu); | 126 | static int gfar_change_mtu(struct net_device *dev, int new_mtu); |
124 | static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs); | 127 | static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs); |
125 | static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs); | 128 | static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs); |
126 | irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs); | 129 | static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs); |
127 | static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 130 | static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
128 | static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 131 | static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
129 | static void gfar_phy_change(void *data); | 132 | static void gfar_phy_change(void *data); |
@@ -139,9 +142,12 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); | |||
139 | #ifdef CONFIG_GFAR_NAPI | 142 | #ifdef CONFIG_GFAR_NAPI |
140 | static int gfar_poll(struct net_device *dev, int *budget); | 143 | static int gfar_poll(struct net_device *dev, int *budget); |
141 | #endif | 144 | #endif |
142 | static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); | 145 | int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); |
143 | static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); | 146 | static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); |
144 | static void gfar_phy_startup_timer(unsigned long data); | 147 | static void gfar_phy_startup_timer(unsigned long data); |
148 | static void gfar_vlan_rx_register(struct net_device *netdev, | ||
149 | struct vlan_group *grp); | ||
150 | static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); | ||
145 | 151 | ||
146 | extern struct ethtool_ops gfar_ethtool_ops; | 152 | extern struct ethtool_ops gfar_ethtool_ops; |
147 | 153 | ||
@@ -149,6 +155,13 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc"); | |||
149 | MODULE_DESCRIPTION("Gianfar Ethernet Driver"); | 155 | MODULE_DESCRIPTION("Gianfar Ethernet Driver"); |
150 | MODULE_LICENSE("GPL"); | 156 | MODULE_LICENSE("GPL"); |
151 | 157 | ||
158 | int gfar_uses_fcb(struct gfar_private *priv) | ||
159 | { | ||
160 | if (priv->vlan_enable || priv->rx_csum_enable) | ||
161 | return 1; | ||
162 | else | ||
163 | return 0; | ||
164 | } | ||
152 | static int gfar_probe(struct device *device) | 165 | static int gfar_probe(struct device *device) |
153 | { | 166 | { |
154 | u32 tempval; | 167 | u32 tempval; |
@@ -159,7 +172,6 @@ static int gfar_probe(struct device *device) | |||
159 | struct resource *r; | 172 | struct resource *r; |
160 | int idx; | 173 | int idx; |
161 | int err = 0; | 174 | int err = 0; |
162 | int dev_ethtool_ops = 0; | ||
163 | 175 | ||
164 | einfo = (struct gianfar_platform_data *) pdev->dev.platform_data; | 176 | einfo = (struct gianfar_platform_data *) pdev->dev.platform_data; |
165 | 177 | ||
@@ -265,15 +277,69 @@ static int gfar_probe(struct device *device) | |||
265 | dev->mtu = 1500; | 277 | dev->mtu = 1500; |
266 | dev->set_multicast_list = gfar_set_multi; | 278 | dev->set_multicast_list = gfar_set_multi; |
267 | 279 | ||
268 | /* Index into the array of possible ethtool | 280 | dev->ethtool_ops = &gfar_ethtool_ops; |
269 | * ops to catch all 4 possibilities */ | 281 | |
270 | if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) == 0) | 282 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { |
271 | dev_ethtool_ops += 1; | 283 | priv->rx_csum_enable = 1; |
284 | dev->features |= NETIF_F_IP_CSUM; | ||
285 | } else | ||
286 | priv->rx_csum_enable = 0; | ||
287 | |||
288 | priv->vlgrp = NULL; | ||
272 | 289 | ||
273 | if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE) == 0) | 290 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { |
274 | dev_ethtool_ops += 2; | 291 | dev->vlan_rx_register = gfar_vlan_rx_register; |
292 | dev->vlan_rx_kill_vid = gfar_vlan_rx_kill_vid; | ||
275 | 293 | ||
276 | dev->ethtool_ops = gfar_op_array[dev_ethtool_ops]; | 294 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; |
295 | |||
296 | priv->vlan_enable = 1; | ||
297 | } | ||
298 | |||
299 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { | ||
300 | priv->extended_hash = 1; | ||
301 | priv->hash_width = 9; | ||
302 | |||
303 | priv->hash_regs[0] = &priv->regs->igaddr0; | ||
304 | priv->hash_regs[1] = &priv->regs->igaddr1; | ||
305 | priv->hash_regs[2] = &priv->regs->igaddr2; | ||
306 | priv->hash_regs[3] = &priv->regs->igaddr3; | ||
307 | priv->hash_regs[4] = &priv->regs->igaddr4; | ||
308 | priv->hash_regs[5] = &priv->regs->igaddr5; | ||
309 | priv->hash_regs[6] = &priv->regs->igaddr6; | ||
310 | priv->hash_regs[7] = &priv->regs->igaddr7; | ||
311 | priv->hash_regs[8] = &priv->regs->gaddr0; | ||
312 | priv->hash_regs[9] = &priv->regs->gaddr1; | ||
313 | priv->hash_regs[10] = &priv->regs->gaddr2; | ||
314 | priv->hash_regs[11] = &priv->regs->gaddr3; | ||
315 | priv->hash_regs[12] = &priv->regs->gaddr4; | ||
316 | priv->hash_regs[13] = &priv->regs->gaddr5; | ||
317 | priv->hash_regs[14] = &priv->regs->gaddr6; | ||
318 | priv->hash_regs[15] = &priv->regs->gaddr7; | ||
319 | |||
320 | } else { | ||
321 | priv->extended_hash = 0; | ||
322 | priv->hash_width = 8; | ||
323 | |||
324 | priv->hash_regs[0] = &priv->regs->gaddr0; | ||
325 | priv->hash_regs[1] = &priv->regs->gaddr1; | ||
326 | priv->hash_regs[2] = &priv->regs->gaddr2; | ||
327 | priv->hash_regs[3] = &priv->regs->gaddr3; | ||
328 | priv->hash_regs[4] = &priv->regs->gaddr4; | ||
329 | priv->hash_regs[5] = &priv->regs->gaddr5; | ||
330 | priv->hash_regs[6] = &priv->regs->gaddr6; | ||
331 | priv->hash_regs[7] = &priv->regs->gaddr7; | ||
332 | } | ||
333 | |||
334 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_PADDING) | ||
335 | priv->padding = DEFAULT_PADDING; | ||
336 | else | ||
337 | priv->padding = 0; | ||
338 | |||
339 | dev->hard_header_len += priv->padding; | ||
340 | |||
341 | if (dev->features & NETIF_F_IP_CSUM) | ||
342 | dev->hard_header_len += GMAC_FCB_LEN; | ||
277 | 343 | ||
278 | priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; | 344 | priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; |
279 | #ifdef CONFIG_GFAR_BUFSTASH | 345 | #ifdef CONFIG_GFAR_BUFSTASH |
@@ -289,6 +355,9 @@ static int gfar_probe(struct device *device) | |||
289 | priv->rxcount = DEFAULT_RXCOUNT; | 355 | priv->rxcount = DEFAULT_RXCOUNT; |
290 | priv->rxtime = DEFAULT_RXTIME; | 356 | priv->rxtime = DEFAULT_RXTIME; |
291 | 357 | ||
358 | /* Enable most messages by default */ | ||
359 | priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; | ||
360 | |||
292 | err = register_netdev(dev); | 361 | err = register_netdev(dev); |
293 | 362 | ||
294 | if (err) { | 363 | if (err) { |
@@ -360,8 +429,9 @@ static int init_phy(struct net_device *dev) | |||
360 | GFP_KERNEL); | 429 | GFP_KERNEL); |
361 | 430 | ||
362 | if(NULL == mii_info) { | 431 | if(NULL == mii_info) { |
363 | printk(KERN_ERR "%s: Could not allocate mii_info\n", | 432 | if (netif_msg_ifup(priv)) |
364 | dev->name); | 433 | printk(KERN_ERR "%s: Could not allocate mii_info\n", |
434 | dev->name); | ||
365 | return -ENOMEM; | 435 | return -ENOMEM; |
366 | } | 436 | } |
367 | 437 | ||
@@ -410,7 +480,8 @@ static int init_phy(struct net_device *dev) | |||
410 | curphy = get_phy_info(priv->mii_info); | 480 | curphy = get_phy_info(priv->mii_info); |
411 | 481 | ||
412 | if (curphy == NULL) { | 482 | if (curphy == NULL) { |
413 | printk(KERN_ERR "%s: No PHY found\n", dev->name); | 483 | if (netif_msg_ifup(priv)) |
484 | printk(KERN_ERR "%s: No PHY found\n", dev->name); | ||
414 | err = -1; | 485 | err = -1; |
415 | goto no_phy; | 486 | goto no_phy; |
416 | } | 487 | } |
@@ -421,7 +492,7 @@ static int init_phy(struct net_device *dev) | |||
421 | if(curphy->init) { | 492 | if(curphy->init) { |
422 | err = curphy->init(priv->mii_info); | 493 | err = curphy->init(priv->mii_info); |
423 | 494 | ||
424 | if (err) | 495 | if (err) |
425 | goto phy_init_fail; | 496 | goto phy_init_fail; |
426 | } | 497 | } |
427 | 498 | ||
@@ -446,14 +517,14 @@ static void init_registers(struct net_device *dev) | |||
446 | gfar_write(&priv->regs->imask, IMASK_INIT_CLEAR); | 517 | gfar_write(&priv->regs->imask, IMASK_INIT_CLEAR); |
447 | 518 | ||
448 | /* Init hash registers to zero */ | 519 | /* Init hash registers to zero */ |
449 | gfar_write(&priv->regs->iaddr0, 0); | 520 | gfar_write(&priv->regs->igaddr0, 0); |
450 | gfar_write(&priv->regs->iaddr1, 0); | 521 | gfar_write(&priv->regs->igaddr1, 0); |
451 | gfar_write(&priv->regs->iaddr2, 0); | 522 | gfar_write(&priv->regs->igaddr2, 0); |
452 | gfar_write(&priv->regs->iaddr3, 0); | 523 | gfar_write(&priv->regs->igaddr3, 0); |
453 | gfar_write(&priv->regs->iaddr4, 0); | 524 | gfar_write(&priv->regs->igaddr4, 0); |
454 | gfar_write(&priv->regs->iaddr5, 0); | 525 | gfar_write(&priv->regs->igaddr5, 0); |
455 | gfar_write(&priv->regs->iaddr6, 0); | 526 | gfar_write(&priv->regs->igaddr6, 0); |
456 | gfar_write(&priv->regs->iaddr7, 0); | 527 | gfar_write(&priv->regs->igaddr7, 0); |
457 | 528 | ||
458 | gfar_write(&priv->regs->gaddr0, 0); | 529 | gfar_write(&priv->regs->gaddr0, 0); |
459 | gfar_write(&priv->regs->gaddr1, 0); | 530 | gfar_write(&priv->regs->gaddr1, 0); |
@@ -464,9 +535,6 @@ static void init_registers(struct net_device *dev) | |||
464 | gfar_write(&priv->regs->gaddr6, 0); | 535 | gfar_write(&priv->regs->gaddr6, 0); |
465 | gfar_write(&priv->regs->gaddr7, 0); | 536 | gfar_write(&priv->regs->gaddr7, 0); |
466 | 537 | ||
467 | /* Zero out rctrl */ | ||
468 | gfar_write(&priv->regs->rctrl, 0x00000000); | ||
469 | |||
470 | /* Zero out the rmon mib registers if it has them */ | 538 | /* Zero out the rmon mib registers if it has them */ |
471 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { | 539 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { |
472 | memset((void *) &(priv->regs->rmon), 0, | 540 | memset((void *) &(priv->regs->rmon), 0, |
@@ -497,20 +565,14 @@ static void init_registers(struct net_device *dev) | |||
497 | gfar_write(&priv->regs->tbipa, TBIPA_VALUE); | 565 | gfar_write(&priv->regs->tbipa, TBIPA_VALUE); |
498 | } | 566 | } |
499 | 567 | ||
500 | void stop_gfar(struct net_device *dev) | 568 | |
569 | /* Halt the receive and transmit queues */ | ||
570 | void gfar_halt(struct net_device *dev) | ||
501 | { | 571 | { |
502 | struct gfar_private *priv = netdev_priv(dev); | 572 | struct gfar_private *priv = netdev_priv(dev); |
503 | struct gfar *regs = priv->regs; | 573 | struct gfar *regs = priv->regs; |
504 | unsigned long flags; | ||
505 | u32 tempval; | 574 | u32 tempval; |
506 | 575 | ||
507 | /* Lock it down */ | ||
508 | spin_lock_irqsave(&priv->lock, flags); | ||
509 | |||
510 | /* Tell the kernel the link is down */ | ||
511 | priv->mii_info->link = 0; | ||
512 | adjust_link(dev); | ||
513 | |||
514 | /* Mask all interrupts */ | 576 | /* Mask all interrupts */ |
515 | gfar_write(®s->imask, IMASK_INIT_CLEAR); | 577 | gfar_write(®s->imask, IMASK_INIT_CLEAR); |
516 | 578 | ||
@@ -533,13 +595,29 @@ void stop_gfar(struct net_device *dev) | |||
533 | tempval = gfar_read(®s->maccfg1); | 595 | tempval = gfar_read(®s->maccfg1); |
534 | tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); | 596 | tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); |
535 | gfar_write(®s->maccfg1, tempval); | 597 | gfar_write(®s->maccfg1, tempval); |
598 | } | ||
599 | |||
600 | void stop_gfar(struct net_device *dev) | ||
601 | { | ||
602 | struct gfar_private *priv = netdev_priv(dev); | ||
603 | struct gfar *regs = priv->regs; | ||
604 | unsigned long flags; | ||
605 | |||
606 | /* Lock it down */ | ||
607 | spin_lock_irqsave(&priv->lock, flags); | ||
608 | |||
609 | /* Tell the kernel the link is down */ | ||
610 | priv->mii_info->link = 0; | ||
611 | adjust_link(dev); | ||
612 | |||
613 | gfar_halt(dev); | ||
536 | 614 | ||
537 | if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { | 615 | if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { |
538 | /* Clear any pending interrupts */ | 616 | /* Clear any pending interrupts */ |
539 | mii_clear_phy_interrupt(priv->mii_info); | 617 | mii_clear_phy_interrupt(priv->mii_info); |
540 | 618 | ||
541 | /* Disable PHY Interrupts */ | 619 | /* Disable PHY Interrupts */ |
542 | mii_configure_phy_interrupt(priv->mii_info, | 620 | mii_configure_phy_interrupt(priv->mii_info, |
543 | MII_INTERRUPT_DISABLED); | 621 | MII_INTERRUPT_DISABLED); |
544 | } | 622 | } |
545 | 623 | ||
@@ -566,7 +644,7 @@ void stop_gfar(struct net_device *dev) | |||
566 | sizeof(struct txbd8)*priv->tx_ring_size | 644 | sizeof(struct txbd8)*priv->tx_ring_size |
567 | + sizeof(struct rxbd8)*priv->rx_ring_size, | 645 | + sizeof(struct rxbd8)*priv->rx_ring_size, |
568 | priv->tx_bd_base, | 646 | priv->tx_bd_base, |
569 | gfar_read(®s->tbase)); | 647 | gfar_read(®s->tbase0)); |
570 | } | 648 | } |
571 | 649 | ||
572 | /* If there are any tx skbs or rx skbs still around, free them. | 650 | /* If there are any tx skbs or rx skbs still around, free them. |
@@ -620,6 +698,34 @@ void free_skb_resources(struct gfar_private *priv) | |||
620 | } | 698 | } |
621 | } | 699 | } |
622 | 700 | ||
701 | void gfar_start(struct net_device *dev) | ||
702 | { | ||
703 | struct gfar_private *priv = netdev_priv(dev); | ||
704 | struct gfar *regs = priv->regs; | ||
705 | u32 tempval; | ||
706 | |||
707 | /* Enable Rx and Tx in MACCFG1 */ | ||
708 | tempval = gfar_read(®s->maccfg1); | ||
709 | tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); | ||
710 | gfar_write(®s->maccfg1, tempval); | ||
711 | |||
712 | /* Initialize DMACTRL to have WWR and WOP */ | ||
713 | tempval = gfar_read(&priv->regs->dmactrl); | ||
714 | tempval |= DMACTRL_INIT_SETTINGS; | ||
715 | gfar_write(&priv->regs->dmactrl, tempval); | ||
716 | |||
717 | /* Clear THLT, so that the DMA starts polling now */ | ||
718 | gfar_write(®s->tstat, TSTAT_CLEAR_THALT); | ||
719 | |||
720 | /* Make sure we aren't stopped */ | ||
721 | tempval = gfar_read(&priv->regs->dmactrl); | ||
722 | tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); | ||
723 | gfar_write(&priv->regs->dmactrl, tempval); | ||
724 | |||
725 | /* Unmask the interrupts we look for */ | ||
726 | gfar_write(®s->imask, IMASK_DEFAULT); | ||
727 | } | ||
728 | |||
623 | /* Bring the controller up and running */ | 729 | /* Bring the controller up and running */ |
624 | int startup_gfar(struct net_device *dev) | 730 | int startup_gfar(struct net_device *dev) |
625 | { | 731 | { |
@@ -630,33 +736,34 @@ int startup_gfar(struct net_device *dev) | |||
630 | int i; | 736 | int i; |
631 | struct gfar_private *priv = netdev_priv(dev); | 737 | struct gfar_private *priv = netdev_priv(dev); |
632 | struct gfar *regs = priv->regs; | 738 | struct gfar *regs = priv->regs; |
633 | u32 tempval; | ||
634 | int err = 0; | 739 | int err = 0; |
740 | u32 rctrl = 0; | ||
635 | 741 | ||
636 | gfar_write(®s->imask, IMASK_INIT_CLEAR); | 742 | gfar_write(®s->imask, IMASK_INIT_CLEAR); |
637 | 743 | ||
638 | /* Allocate memory for the buffer descriptors */ | 744 | /* Allocate memory for the buffer descriptors */ |
639 | vaddr = (unsigned long) dma_alloc_coherent(NULL, | 745 | vaddr = (unsigned long) dma_alloc_coherent(NULL, |
640 | sizeof (struct txbd8) * priv->tx_ring_size + | 746 | sizeof (struct txbd8) * priv->tx_ring_size + |
641 | sizeof (struct rxbd8) * priv->rx_ring_size, | 747 | sizeof (struct rxbd8) * priv->rx_ring_size, |
642 | &addr, GFP_KERNEL); | 748 | &addr, GFP_KERNEL); |
643 | 749 | ||
644 | if (vaddr == 0) { | 750 | if (vaddr == 0) { |
645 | printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n", | 751 | if (netif_msg_ifup(priv)) |
646 | dev->name); | 752 | printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n", |
753 | dev->name); | ||
647 | return -ENOMEM; | 754 | return -ENOMEM; |
648 | } | 755 | } |
649 | 756 | ||
650 | priv->tx_bd_base = (struct txbd8 *) vaddr; | 757 | priv->tx_bd_base = (struct txbd8 *) vaddr; |
651 | 758 | ||
652 | /* enet DMA only understands physical addresses */ | 759 | /* enet DMA only understands physical addresses */ |
653 | gfar_write(®s->tbase, addr); | 760 | gfar_write(®s->tbase0, addr); |
654 | 761 | ||
655 | /* Start the rx descriptor ring where the tx ring leaves off */ | 762 | /* Start the rx descriptor ring where the tx ring leaves off */ |
656 | addr = addr + sizeof (struct txbd8) * priv->tx_ring_size; | 763 | addr = addr + sizeof (struct txbd8) * priv->tx_ring_size; |
657 | vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size; | 764 | vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size; |
658 | priv->rx_bd_base = (struct rxbd8 *) vaddr; | 765 | priv->rx_bd_base = (struct rxbd8 *) vaddr; |
659 | gfar_write(®s->rbase, addr); | 766 | gfar_write(®s->rbase0, addr); |
660 | 767 | ||
661 | /* Setup the skbuff rings */ | 768 | /* Setup the skbuff rings */ |
662 | priv->tx_skbuff = | 769 | priv->tx_skbuff = |
@@ -664,8 +771,9 @@ int startup_gfar(struct net_device *dev) | |||
664 | priv->tx_ring_size, GFP_KERNEL); | 771 | priv->tx_ring_size, GFP_KERNEL); |
665 | 772 | ||
666 | if (priv->tx_skbuff == NULL) { | 773 | if (priv->tx_skbuff == NULL) { |
667 | printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", | 774 | if (netif_msg_ifup(priv)) |
668 | dev->name); | 775 | printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", |
776 | dev->name); | ||
669 | err = -ENOMEM; | 777 | err = -ENOMEM; |
670 | goto tx_skb_fail; | 778 | goto tx_skb_fail; |
671 | } | 779 | } |
@@ -678,8 +786,9 @@ int startup_gfar(struct net_device *dev) | |||
678 | priv->rx_ring_size, GFP_KERNEL); | 786 | priv->rx_ring_size, GFP_KERNEL); |
679 | 787 | ||
680 | if (priv->rx_skbuff == NULL) { | 788 | if (priv->rx_skbuff == NULL) { |
681 | printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", | 789 | if (netif_msg_ifup(priv)) |
682 | dev->name); | 790 | printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", |
791 | dev->name); | ||
683 | err = -ENOMEM; | 792 | err = -ENOMEM; |
684 | goto rx_skb_fail; | 793 | goto rx_skb_fail; |
685 | } | 794 | } |
@@ -726,12 +835,13 @@ int startup_gfar(struct net_device *dev) | |||
726 | /* If the device has multiple interrupts, register for | 835 | /* If the device has multiple interrupts, register for |
727 | * them. Otherwise, only register for the one */ | 836 | * them. Otherwise, only register for the one */ |
728 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { | 837 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { |
729 | /* Install our interrupt handlers for Error, | 838 | /* Install our interrupt handlers for Error, |
730 | * Transmit, and Receive */ | 839 | * Transmit, and Receive */ |
731 | if (request_irq(priv->interruptError, gfar_error, | 840 | if (request_irq(priv->interruptError, gfar_error, |
732 | 0, "enet_error", dev) < 0) { | 841 | 0, "enet_error", dev) < 0) { |
733 | printk(KERN_ERR "%s: Can't get IRQ %d\n", | 842 | if (netif_msg_intr(priv)) |
734 | dev->name, priv->interruptError); | 843 | printk(KERN_ERR "%s: Can't get IRQ %d\n", |
844 | dev->name, priv->interruptError); | ||
735 | 845 | ||
736 | err = -1; | 846 | err = -1; |
737 | goto err_irq_fail; | 847 | goto err_irq_fail; |
@@ -739,8 +849,9 @@ int startup_gfar(struct net_device *dev) | |||
739 | 849 | ||
740 | if (request_irq(priv->interruptTransmit, gfar_transmit, | 850 | if (request_irq(priv->interruptTransmit, gfar_transmit, |
741 | 0, "enet_tx", dev) < 0) { | 851 | 0, "enet_tx", dev) < 0) { |
742 | printk(KERN_ERR "%s: Can't get IRQ %d\n", | 852 | if (netif_msg_intr(priv)) |
743 | dev->name, priv->interruptTransmit); | 853 | printk(KERN_ERR "%s: Can't get IRQ %d\n", |
854 | dev->name, priv->interruptTransmit); | ||
744 | 855 | ||
745 | err = -1; | 856 | err = -1; |
746 | 857 | ||
@@ -749,8 +860,9 @@ int startup_gfar(struct net_device *dev) | |||
749 | 860 | ||
750 | if (request_irq(priv->interruptReceive, gfar_receive, | 861 | if (request_irq(priv->interruptReceive, gfar_receive, |
751 | 0, "enet_rx", dev) < 0) { | 862 | 0, "enet_rx", dev) < 0) { |
752 | printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n", | 863 | if (netif_msg_intr(priv)) |
753 | dev->name, priv->interruptReceive); | 864 | printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n", |
865 | dev->name, priv->interruptReceive); | ||
754 | 866 | ||
755 | err = -1; | 867 | err = -1; |
756 | goto rx_irq_fail; | 868 | goto rx_irq_fail; |
@@ -758,8 +870,9 @@ int startup_gfar(struct net_device *dev) | |||
758 | } else { | 870 | } else { |
759 | if (request_irq(priv->interruptTransmit, gfar_interrupt, | 871 | if (request_irq(priv->interruptTransmit, gfar_interrupt, |
760 | 0, "gfar_interrupt", dev) < 0) { | 872 | 0, "gfar_interrupt", dev) < 0) { |
761 | printk(KERN_ERR "%s: Can't get IRQ %d\n", | 873 | if (netif_msg_intr(priv)) |
762 | dev->name, priv->interruptError); | 874 | printk(KERN_ERR "%s: Can't get IRQ %d\n", |
875 | dev->name, priv->interruptError); | ||
763 | 876 | ||
764 | err = -1; | 877 | err = -1; |
765 | goto err_irq_fail; | 878 | goto err_irq_fail; |
@@ -787,28 +900,22 @@ int startup_gfar(struct net_device *dev) | |||
787 | else | 900 | else |
788 | gfar_write(®s->rxic, 0); | 901 | gfar_write(®s->rxic, 0); |
789 | 902 | ||
790 | init_waitqueue_head(&priv->rxcleanupq); | 903 | if (priv->rx_csum_enable) |
904 | rctrl |= RCTRL_CHECKSUMMING; | ||
791 | 905 | ||
792 | /* Enable Rx and Tx in MACCFG1 */ | 906 | if (priv->extended_hash) |
793 | tempval = gfar_read(®s->maccfg1); | 907 | rctrl |= RCTRL_EXTHASH; |
794 | tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); | ||
795 | gfar_write(®s->maccfg1, tempval); | ||
796 | 908 | ||
797 | /* Initialize DMACTRL to have WWR and WOP */ | 909 | if (priv->vlan_enable) |
798 | tempval = gfar_read(&priv->regs->dmactrl); | 910 | rctrl |= RCTRL_VLAN; |
799 | tempval |= DMACTRL_INIT_SETTINGS; | ||
800 | gfar_write(&priv->regs->dmactrl, tempval); | ||
801 | 911 | ||
802 | /* Clear THLT, so that the DMA starts polling now */ | 912 | /* Init rctrl based on our settings */ |
803 | gfar_write(®s->tstat, TSTAT_CLEAR_THALT); | 913 | gfar_write(&priv->regs->rctrl, rctrl); |
804 | 914 | ||
805 | /* Make sure we aren't stopped */ | 915 | if (dev->features & NETIF_F_IP_CSUM) |
806 | tempval = gfar_read(&priv->regs->dmactrl); | 916 | gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM); |
807 | tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); | ||
808 | gfar_write(&priv->regs->dmactrl, tempval); | ||
809 | 917 | ||
810 | /* Unmask the interrupts we look for */ | 918 | gfar_start(dev); |
811 | gfar_write(®s->imask, IMASK_DEFAULT); | ||
812 | 919 | ||
813 | return 0; | 920 | return 0; |
814 | 921 | ||
@@ -824,7 +931,7 @@ tx_skb_fail: | |||
824 | sizeof(struct txbd8)*priv->tx_ring_size | 931 | sizeof(struct txbd8)*priv->tx_ring_size |
825 | + sizeof(struct rxbd8)*priv->rx_ring_size, | 932 | + sizeof(struct rxbd8)*priv->rx_ring_size, |
826 | priv->tx_bd_base, | 933 | priv->tx_bd_base, |
827 | gfar_read(®s->tbase)); | 934 | gfar_read(®s->tbase0)); |
828 | 935 | ||
829 | if (priv->mii_info->phyinfo->close) | 936 | if (priv->mii_info->phyinfo->close) |
830 | priv->mii_info->phyinfo->close(priv->mii_info); | 937 | priv->mii_info->phyinfo->close(priv->mii_info); |
@@ -857,11 +964,62 @@ static int gfar_enet_open(struct net_device *dev) | |||
857 | return err; | 964 | return err; |
858 | } | 965 | } |
859 | 966 | ||
967 | static struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp) | ||
968 | { | ||
969 | struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN); | ||
970 | |||
971 | memset(fcb, 0, GMAC_FCB_LEN); | ||
972 | |||
973 | /* Flag the bd so the controller looks for the FCB */ | ||
974 | bdp->status |= TXBD_TOE; | ||
975 | |||
976 | return fcb; | ||
977 | } | ||
978 | |||
979 | static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) | ||
980 | { | ||
981 | int len; | ||
982 | |||
983 | /* If we're here, it's a IP packet with a TCP or UDP | ||
984 | * payload. We set it to checksum, using a pseudo-header | ||
985 | * we provide | ||
986 | */ | ||
987 | fcb->ip = 1; | ||
988 | fcb->tup = 1; | ||
989 | fcb->ctu = 1; | ||
990 | fcb->nph = 1; | ||
991 | |||
992 | /* Notify the controller what the protocol is */ | ||
993 | if (skb->nh.iph->protocol == IPPROTO_UDP) | ||
994 | fcb->udp = 1; | ||
995 | |||
996 | /* l3os is the distance between the start of the | ||
997 | * frame (skb->data) and the start of the IP hdr. | ||
998 | * l4os is the distance between the start of the | ||
999 | * l3 hdr and the l4 hdr */ | ||
1000 | fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN); | ||
1001 | fcb->l4os = (u16)(skb->h.raw - skb->nh.raw); | ||
1002 | |||
1003 | len = skb->nh.iph->tot_len - fcb->l4os; | ||
1004 | |||
1005 | /* Provide the pseudoheader csum */ | ||
1006 | fcb->phcs = ~csum_tcpudp_magic(skb->nh.iph->saddr, | ||
1007 | skb->nh.iph->daddr, len, | ||
1008 | skb->nh.iph->protocol, 0); | ||
1009 | } | ||
1010 | |||
1011 | void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb) | ||
1012 | { | ||
1013 | fcb->vln = 1; | ||
1014 | fcb->vlctl = vlan_tx_tag_get(skb); | ||
1015 | } | ||
1016 | |||
860 | /* This is called by the kernel when a frame is ready for transmission. */ | 1017 | /* This is called by the kernel when a frame is ready for transmission. */ |
861 | /* It is pointed to by the dev->hard_start_xmit function pointer */ | 1018 | /* It is pointed to by the dev->hard_start_xmit function pointer */ |
862 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | 1019 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) |
863 | { | 1020 | { |
864 | struct gfar_private *priv = netdev_priv(dev); | 1021 | struct gfar_private *priv = netdev_priv(dev); |
1022 | struct txfcb *fcb = NULL; | ||
865 | struct txbd8 *txbdp; | 1023 | struct txbd8 *txbdp; |
866 | 1024 | ||
867 | /* Update transmit stats */ | 1025 | /* Update transmit stats */ |
@@ -876,9 +1034,24 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
876 | /* Clear all but the WRAP status flags */ | 1034 | /* Clear all but the WRAP status flags */ |
877 | txbdp->status &= TXBD_WRAP; | 1035 | txbdp->status &= TXBD_WRAP; |
878 | 1036 | ||
1037 | /* Set up checksumming */ | ||
1038 | if ((dev->features & NETIF_F_IP_CSUM) | ||
1039 | && (CHECKSUM_HW == skb->ip_summed)) { | ||
1040 | fcb = gfar_add_fcb(skb, txbdp); | ||
1041 | gfar_tx_checksum(skb, fcb); | ||
1042 | } | ||
1043 | |||
1044 | if (priv->vlan_enable && | ||
1045 | unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) { | ||
1046 | if (NULL == fcb) | ||
1047 | fcb = gfar_add_fcb(skb, txbdp); | ||
1048 | |||
1049 | gfar_tx_vlan(skb, fcb); | ||
1050 | } | ||
1051 | |||
879 | /* Set buffer length and pointer */ | 1052 | /* Set buffer length and pointer */ |
880 | txbdp->length = skb->len; | 1053 | txbdp->length = skb->len; |
881 | txbdp->bufPtr = dma_map_single(NULL, skb->data, | 1054 | txbdp->bufPtr = dma_map_single(NULL, skb->data, |
882 | skb->len, DMA_TO_DEVICE); | 1055 | skb->len, DMA_TO_DEVICE); |
883 | 1056 | ||
884 | /* Save the skb pointer so we can free it later */ | 1057 | /* Save the skb pointer so we can free it later */ |
@@ -972,15 +1145,78 @@ int gfar_set_mac_address(struct net_device *dev) | |||
972 | } | 1145 | } |
973 | 1146 | ||
974 | 1147 | ||
1148 | /* Enables and disables VLAN insertion/extraction */ | ||
1149 | static void gfar_vlan_rx_register(struct net_device *dev, | ||
1150 | struct vlan_group *grp) | ||
1151 | { | ||
1152 | struct gfar_private *priv = netdev_priv(dev); | ||
1153 | unsigned long flags; | ||
1154 | u32 tempval; | ||
1155 | |||
1156 | spin_lock_irqsave(&priv->lock, flags); | ||
1157 | |||
1158 | priv->vlgrp = grp; | ||
1159 | |||
1160 | if (grp) { | ||
1161 | /* Enable VLAN tag insertion */ | ||
1162 | tempval = gfar_read(&priv->regs->tctrl); | ||
1163 | tempval |= TCTRL_VLINS; | ||
1164 | |||
1165 | gfar_write(&priv->regs->tctrl, tempval); | ||
1166 | |||
1167 | /* Enable VLAN tag extraction */ | ||
1168 | tempval = gfar_read(&priv->regs->rctrl); | ||
1169 | tempval |= RCTRL_VLEX; | ||
1170 | gfar_write(&priv->regs->rctrl, tempval); | ||
1171 | } else { | ||
1172 | /* Disable VLAN tag insertion */ | ||
1173 | tempval = gfar_read(&priv->regs->tctrl); | ||
1174 | tempval &= ~TCTRL_VLINS; | ||
1175 | gfar_write(&priv->regs->tctrl, tempval); | ||
1176 | |||
1177 | /* Disable VLAN tag extraction */ | ||
1178 | tempval = gfar_read(&priv->regs->rctrl); | ||
1179 | tempval &= ~RCTRL_VLEX; | ||
1180 | gfar_write(&priv->regs->rctrl, tempval); | ||
1181 | } | ||
1182 | |||
1183 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1184 | } | ||
1185 | |||
1186 | |||
1187 | static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) | ||
1188 | { | ||
1189 | struct gfar_private *priv = netdev_priv(dev); | ||
1190 | unsigned long flags; | ||
1191 | |||
1192 | spin_lock_irqsave(&priv->lock, flags); | ||
1193 | |||
1194 | if (priv->vlgrp) | ||
1195 | priv->vlgrp->vlan_devices[vid] = NULL; | ||
1196 | |||
1197 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1198 | } | ||
1199 | |||
1200 | |||
975 | static int gfar_change_mtu(struct net_device *dev, int new_mtu) | 1201 | static int gfar_change_mtu(struct net_device *dev, int new_mtu) |
976 | { | 1202 | { |
977 | int tempsize, tempval; | 1203 | int tempsize, tempval; |
978 | struct gfar_private *priv = netdev_priv(dev); | 1204 | struct gfar_private *priv = netdev_priv(dev); |
979 | int oldsize = priv->rx_buffer_size; | 1205 | int oldsize = priv->rx_buffer_size; |
980 | int frame_size = new_mtu + 18; | 1206 | int frame_size = new_mtu + ETH_HLEN; |
1207 | |||
1208 | if (priv->vlan_enable) | ||
1209 | frame_size += VLAN_ETH_HLEN; | ||
1210 | |||
1211 | if (gfar_uses_fcb(priv)) | ||
1212 | frame_size += GMAC_FCB_LEN; | ||
1213 | |||
1214 | frame_size += priv->padding; | ||
981 | 1215 | ||
982 | if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) { | 1216 | if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) { |
983 | printk(KERN_ERR "%s: Invalid MTU setting\n", dev->name); | 1217 | if (netif_msg_drv(priv)) |
1218 | printk(KERN_ERR "%s: Invalid MTU setting\n", | ||
1219 | dev->name); | ||
984 | return -EINVAL; | 1220 | return -EINVAL; |
985 | } | 1221 | } |
986 | 1222 | ||
@@ -1120,7 +1356,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) | |||
1120 | skb->dev = dev; | 1356 | skb->dev = dev; |
1121 | 1357 | ||
1122 | bdp->bufPtr = dma_map_single(NULL, skb->data, | 1358 | bdp->bufPtr = dma_map_single(NULL, skb->data, |
1123 | priv->rx_buffer_size + RXBUF_ALIGNMENT, | 1359 | priv->rx_buffer_size + RXBUF_ALIGNMENT, |
1124 | DMA_FROM_DEVICE); | 1360 | DMA_FROM_DEVICE); |
1125 | 1361 | ||
1126 | bdp->length = 0; | 1362 | bdp->length = 0; |
@@ -1190,11 +1426,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
1190 | 1426 | ||
1191 | __netif_rx_schedule(dev); | 1427 | __netif_rx_schedule(dev); |
1192 | } else { | 1428 | } else { |
1193 | #ifdef VERBOSE_GFAR_ERRORS | 1429 | if (netif_msg_rx_err(priv)) |
1194 | printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n", | 1430 | printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n", |
1195 | dev->name, gfar_read(&priv->regs->ievent), | 1431 | dev->name, gfar_read(&priv->regs->ievent), |
1196 | gfar_read(&priv->regs->imask)); | 1432 | gfar_read(&priv->regs->imask)); |
1197 | #endif | ||
1198 | } | 1433 | } |
1199 | #else | 1434 | #else |
1200 | 1435 | ||
@@ -1209,15 +1444,43 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
1209 | else | 1444 | else |
1210 | gfar_write(&priv->regs->rxic, 0); | 1445 | gfar_write(&priv->regs->rxic, 0); |
1211 | 1446 | ||
1212 | /* Just in case we need to wake the ring param changer */ | ||
1213 | priv->rxclean = 1; | ||
1214 | |||
1215 | spin_unlock(&priv->lock); | 1447 | spin_unlock(&priv->lock); |
1216 | #endif | 1448 | #endif |
1217 | 1449 | ||
1218 | return IRQ_HANDLED; | 1450 | return IRQ_HANDLED; |
1219 | } | 1451 | } |
1220 | 1452 | ||
1453 | static inline int gfar_rx_vlan(struct sk_buff *skb, | ||
1454 | struct vlan_group *vlgrp, unsigned short vlctl) | ||
1455 | { | ||
1456 | #ifdef CONFIG_GFAR_NAPI | ||
1457 | return vlan_hwaccel_receive_skb(skb, vlgrp, vlctl); | ||
1458 | #else | ||
1459 | return vlan_hwaccel_rx(skb, vlgrp, vlctl); | ||
1460 | #endif | ||
1461 | } | ||
1462 | |||
1463 | static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb) | ||
1464 | { | ||
1465 | /* If valid headers were found, and valid sums | ||
1466 | * were verified, then we tell the kernel that no | ||
1467 | * checksumming is necessary. Otherwise, it is */ | ||
1468 | if (fcb->cip && !fcb->eip && fcb->ctu && !fcb->etu) | ||
1469 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1470 | else | ||
1471 | skb->ip_summed = CHECKSUM_NONE; | ||
1472 | } | ||
1473 | |||
1474 | |||
1475 | static inline struct rxfcb *gfar_get_fcb(struct sk_buff *skb) | ||
1476 | { | ||
1477 | struct rxfcb *fcb = (struct rxfcb *)skb->data; | ||
1478 | |||
1479 | /* Remove the FCB from the skb */ | ||
1480 | skb_pull(skb, GMAC_FCB_LEN); | ||
1481 | |||
1482 | return fcb; | ||
1483 | } | ||
1221 | 1484 | ||
1222 | /* gfar_process_frame() -- handle one incoming packet if skb | 1485 | /* gfar_process_frame() -- handle one incoming packet if skb |
1223 | * isn't NULL. */ | 1486 | * isn't NULL. */ |
@@ -1225,35 +1488,51 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, | |||
1225 | int length) | 1488 | int length) |
1226 | { | 1489 | { |
1227 | struct gfar_private *priv = netdev_priv(dev); | 1490 | struct gfar_private *priv = netdev_priv(dev); |
1491 | struct rxfcb *fcb = NULL; | ||
1228 | 1492 | ||
1229 | if (skb == NULL) { | 1493 | if (skb == NULL) { |
1230 | #ifdef BRIEF_GFAR_ERRORS | 1494 | if (netif_msg_rx_err(priv)) |
1231 | printk(KERN_WARNING "%s: Missing skb!!.\n", | 1495 | printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name); |
1232 | dev->name); | ||
1233 | #endif | ||
1234 | priv->stats.rx_dropped++; | 1496 | priv->stats.rx_dropped++; |
1235 | priv->extra_stats.rx_skbmissing++; | 1497 | priv->extra_stats.rx_skbmissing++; |
1236 | } else { | 1498 | } else { |
1499 | int ret; | ||
1500 | |||
1237 | /* Prep the skb for the packet */ | 1501 | /* Prep the skb for the packet */ |
1238 | skb_put(skb, length); | 1502 | skb_put(skb, length); |
1239 | 1503 | ||
1504 | /* Grab the FCB if there is one */ | ||
1505 | if (gfar_uses_fcb(priv)) | ||
1506 | fcb = gfar_get_fcb(skb); | ||
1507 | |||
1508 | /* Remove the padded bytes, if there are any */ | ||
1509 | if (priv->padding) | ||
1510 | skb_pull(skb, priv->padding); | ||
1511 | |||
1512 | if (priv->rx_csum_enable) | ||
1513 | gfar_rx_checksum(skb, fcb); | ||
1514 | |||
1240 | /* Tell the skb what kind of packet this is */ | 1515 | /* Tell the skb what kind of packet this is */ |
1241 | skb->protocol = eth_type_trans(skb, dev); | 1516 | skb->protocol = eth_type_trans(skb, dev); |
1242 | 1517 | ||
1243 | /* Send the packet up the stack */ | 1518 | /* Send the packet up the stack */ |
1244 | if (RECEIVE(skb) == NET_RX_DROP) { | 1519 | if (unlikely(priv->vlgrp && fcb->vln)) |
1520 | ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl); | ||
1521 | else | ||
1522 | ret = RECEIVE(skb); | ||
1523 | |||
1524 | if (NET_RX_DROP == ret) | ||
1245 | priv->extra_stats.kernel_dropped++; | 1525 | priv->extra_stats.kernel_dropped++; |
1246 | } | ||
1247 | } | 1526 | } |
1248 | 1527 | ||
1249 | return 0; | 1528 | return 0; |
1250 | } | 1529 | } |
1251 | 1530 | ||
1252 | /* gfar_clean_rx_ring() -- Processes each frame in the rx ring | 1531 | /* gfar_clean_rx_ring() -- Processes each frame in the rx ring |
1253 | * until the budget/quota has been reached. Returns the number | 1532 | * until the budget/quota has been reached. Returns the number |
1254 | * of frames handled | 1533 | * of frames handled |
1255 | */ | 1534 | */ |
1256 | static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | 1535 | int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) |
1257 | { | 1536 | { |
1258 | struct rxbd8 *bdp; | 1537 | struct rxbd8 *bdp; |
1259 | struct sk_buff *skb; | 1538 | struct sk_buff *skb; |
@@ -1355,9 +1634,6 @@ static int gfar_poll(struct net_device *dev, int *budget) | |||
1355 | mk_ic_value(priv->rxcount, priv->rxtime)); | 1634 | mk_ic_value(priv->rxcount, priv->rxtime)); |
1356 | else | 1635 | else |
1357 | gfar_write(&priv->regs->rxic, 0); | 1636 | gfar_write(&priv->regs->rxic, 0); |
1358 | |||
1359 | /* Signal to the ring size changer that it's safe to go */ | ||
1360 | priv->rxclean = 1; | ||
1361 | } | 1637 | } |
1362 | 1638 | ||
1363 | return (rx_work_limit < 0) ? 1 : 0; | 1639 | return (rx_work_limit < 0) ? 1 : 0; |
@@ -1393,10 +1669,8 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1393 | if (events & IEVENT_CRL) | 1669 | if (events & IEVENT_CRL) |
1394 | priv->stats.tx_aborted_errors++; | 1670 | priv->stats.tx_aborted_errors++; |
1395 | if (events & IEVENT_XFUN) { | 1671 | if (events & IEVENT_XFUN) { |
1396 | #ifdef VERBOSE_GFAR_ERRORS | 1672 | if (netif_msg_tx_err(priv)) |
1397 | printk(KERN_WARNING "%s: tx underrun. dropped packet\n", | 1673 | printk(KERN_WARNING "%s: tx underrun. dropped packet\n", dev->name); |
1398 | dev->name); | ||
1399 | #endif | ||
1400 | priv->stats.tx_dropped++; | 1674 | priv->stats.tx_dropped++; |
1401 | priv->extra_stats.tx_underrun++; | 1675 | priv->extra_stats.tx_underrun++; |
1402 | 1676 | ||
@@ -1415,36 +1689,30 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1415 | gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); | 1689 | gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); |
1416 | #endif | 1690 | #endif |
1417 | 1691 | ||
1418 | #ifdef VERBOSE_GFAR_ERRORS | 1692 | if (netif_msg_rx_err(priv)) |
1419 | printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name, | 1693 | printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", |
1420 | gfar_read(&priv->regs->rstat)); | 1694 | dev->name, |
1421 | #endif | 1695 | gfar_read(&priv->regs->rstat)); |
1422 | } | 1696 | } |
1423 | if (events & IEVENT_BABR) { | 1697 | if (events & IEVENT_BABR) { |
1424 | priv->stats.rx_errors++; | 1698 | priv->stats.rx_errors++; |
1425 | priv->extra_stats.rx_babr++; | 1699 | priv->extra_stats.rx_babr++; |
1426 | 1700 | ||
1427 | #ifdef VERBOSE_GFAR_ERRORS | 1701 | if (netif_msg_rx_err(priv)) |
1428 | printk(KERN_DEBUG "%s: babbling error\n", dev->name); | 1702 | printk(KERN_DEBUG "%s: babbling error\n", dev->name); |
1429 | #endif | ||
1430 | } | 1703 | } |
1431 | if (events & IEVENT_EBERR) { | 1704 | if (events & IEVENT_EBERR) { |
1432 | priv->extra_stats.eberr++; | 1705 | priv->extra_stats.eberr++; |
1433 | #ifdef VERBOSE_GFAR_ERRORS | 1706 | if (netif_msg_rx_err(priv)) |
1434 | printk(KERN_DEBUG "%s: EBERR\n", dev->name); | 1707 | printk(KERN_DEBUG "%s: EBERR\n", dev->name); |
1435 | #endif | ||
1436 | } | ||
1437 | if (events & IEVENT_RXC) { | ||
1438 | #ifdef VERBOSE_GFAR_ERRORS | ||
1439 | printk(KERN_DEBUG "%s: control frame\n", dev->name); | ||
1440 | #endif | ||
1441 | } | 1708 | } |
1709 | if ((events & IEVENT_RXC) && (netif_msg_rx_err(priv))) | ||
1710 | printk(KERN_DEBUG "%s: control frame\n", dev->name); | ||
1442 | 1711 | ||
1443 | if (events & IEVENT_BABT) { | 1712 | if (events & IEVENT_BABT) { |
1444 | priv->extra_stats.tx_babt++; | 1713 | priv->extra_stats.tx_babt++; |
1445 | #ifdef VERBOSE_GFAR_ERRORS | 1714 | if (netif_msg_rx_err(priv)) |
1446 | printk(KERN_DEBUG "%s: babt error\n", dev->name); | 1715 | printk(KERN_DEBUG "%s: babt error\n", dev->name); |
1447 | #endif | ||
1448 | } | 1716 | } |
1449 | 1717 | ||
1450 | return IRQ_HANDLED; | 1718 | return IRQ_HANDLED; |
@@ -1510,7 +1778,7 @@ static void gfar_phy_timer(unsigned long data) | |||
1510 | * If, after GFAR_AN_TIMEOUT seconds, it has not | 1778 | * If, after GFAR_AN_TIMEOUT seconds, it has not |
1511 | * finished, we switch to forced. | 1779 | * finished, we switch to forced. |
1512 | * Either way, once the process has completed, we either | 1780 | * Either way, once the process has completed, we either |
1513 | * request the interrupt, or switch the timer over to | 1781 | * request the interrupt, or switch the timer over to |
1514 | * using gfar_phy_timer to check status */ | 1782 | * using gfar_phy_timer to check status */ |
1515 | static void gfar_phy_startup_timer(unsigned long data) | 1783 | static void gfar_phy_startup_timer(unsigned long data) |
1516 | { | 1784 | { |
@@ -1535,8 +1803,9 @@ static void gfar_phy_startup_timer(unsigned long data) | |||
1535 | 1803 | ||
1536 | /* Forcing failed! Give up */ | 1804 | /* Forcing failed! Give up */ |
1537 | if(result) { | 1805 | if(result) { |
1538 | printk(KERN_ERR "%s: Forcing failed!\n", | 1806 | if (netif_msg_link(priv)) |
1539 | mii_info->dev->name); | 1807 | printk(KERN_ERR "%s: Forcing failed!\n", |
1808 | mii_info->dev->name); | ||
1540 | return; | 1809 | return; |
1541 | } | 1810 | } |
1542 | } | 1811 | } |
@@ -1546,16 +1815,17 @@ static void gfar_phy_startup_timer(unsigned long data) | |||
1546 | 1815 | ||
1547 | /* Grab the PHY interrupt, if necessary/possible */ | 1816 | /* Grab the PHY interrupt, if necessary/possible */ |
1548 | if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { | 1817 | if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { |
1549 | if (request_irq(priv->einfo->interruptPHY, | 1818 | if (request_irq(priv->einfo->interruptPHY, |
1550 | phy_interrupt, | 1819 | phy_interrupt, |
1551 | SA_SHIRQ, | 1820 | SA_SHIRQ, |
1552 | "phy_interrupt", | 1821 | "phy_interrupt", |
1553 | mii_info->dev) < 0) { | 1822 | mii_info->dev) < 0) { |
1554 | printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", | 1823 | if (netif_msg_intr(priv)) |
1555 | mii_info->dev->name, | 1824 | printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", |
1825 | mii_info->dev->name, | ||
1556 | priv->einfo->interruptPHY); | 1826 | priv->einfo->interruptPHY); |
1557 | } else { | 1827 | } else { |
1558 | mii_configure_phy_interrupt(priv->mii_info, | 1828 | mii_configure_phy_interrupt(priv->mii_info, |
1559 | MII_INTERRUPT_ENABLED); | 1829 | MII_INTERRUPT_ENABLED); |
1560 | return; | 1830 | return; |
1561 | } | 1831 | } |
@@ -1592,15 +1862,17 @@ static void adjust_link(struct net_device *dev) | |||
1592 | tempval &= ~(MACCFG2_FULL_DUPLEX); | 1862 | tempval &= ~(MACCFG2_FULL_DUPLEX); |
1593 | gfar_write(®s->maccfg2, tempval); | 1863 | gfar_write(®s->maccfg2, tempval); |
1594 | 1864 | ||
1595 | printk(KERN_INFO "%s: Half Duplex\n", | 1865 | if (netif_msg_link(priv)) |
1596 | dev->name); | 1866 | printk(KERN_INFO "%s: Half Duplex\n", |
1867 | dev->name); | ||
1597 | } else { | 1868 | } else { |
1598 | tempval = gfar_read(®s->maccfg2); | 1869 | tempval = gfar_read(®s->maccfg2); |
1599 | tempval |= MACCFG2_FULL_DUPLEX; | 1870 | tempval |= MACCFG2_FULL_DUPLEX; |
1600 | gfar_write(®s->maccfg2, tempval); | 1871 | gfar_write(®s->maccfg2, tempval); |
1601 | 1872 | ||
1602 | printk(KERN_INFO "%s: Full Duplex\n", | 1873 | if (netif_msg_link(priv)) |
1603 | dev->name); | 1874 | printk(KERN_INFO "%s: Full Duplex\n", |
1875 | dev->name); | ||
1604 | } | 1876 | } |
1605 | 1877 | ||
1606 | priv->oldduplex = mii_info->duplex; | 1878 | priv->oldduplex = mii_info->duplex; |
@@ -1622,27 +1894,32 @@ static void adjust_link(struct net_device *dev) | |||
1622 | gfar_write(®s->maccfg2, tempval); | 1894 | gfar_write(®s->maccfg2, tempval); |
1623 | break; | 1895 | break; |
1624 | default: | 1896 | default: |
1625 | printk(KERN_WARNING | 1897 | if (netif_msg_link(priv)) |
1626 | "%s: Ack! Speed (%d) is not 10/100/1000!\n", | 1898 | printk(KERN_WARNING |
1627 | dev->name, mii_info->speed); | 1899 | "%s: Ack! Speed (%d) is not 10/100/1000!\n", |
1900 | dev->name, mii_info->speed); | ||
1628 | break; | 1901 | break; |
1629 | } | 1902 | } |
1630 | 1903 | ||
1631 | printk(KERN_INFO "%s: Speed %dBT\n", dev->name, | 1904 | if (netif_msg_link(priv)) |
1632 | mii_info->speed); | 1905 | printk(KERN_INFO "%s: Speed %dBT\n", dev->name, |
1906 | mii_info->speed); | ||
1633 | 1907 | ||
1634 | priv->oldspeed = mii_info->speed; | 1908 | priv->oldspeed = mii_info->speed; |
1635 | } | 1909 | } |
1636 | 1910 | ||
1637 | if (!priv->oldlink) { | 1911 | if (!priv->oldlink) { |
1638 | printk(KERN_INFO "%s: Link is up\n", dev->name); | 1912 | if (netif_msg_link(priv)) |
1913 | printk(KERN_INFO "%s: Link is up\n", dev->name); | ||
1639 | priv->oldlink = 1; | 1914 | priv->oldlink = 1; |
1640 | netif_carrier_on(dev); | 1915 | netif_carrier_on(dev); |
1641 | netif_schedule(dev); | 1916 | netif_schedule(dev); |
1642 | } | 1917 | } |
1643 | } else { | 1918 | } else { |
1644 | if (priv->oldlink) { | 1919 | if (priv->oldlink) { |
1645 | printk(KERN_INFO "%s: Link is down\n", dev->name); | 1920 | if (netif_msg_link(priv)) |
1921 | printk(KERN_INFO "%s: Link is down\n", | ||
1922 | dev->name); | ||
1646 | priv->oldlink = 0; | 1923 | priv->oldlink = 0; |
1647 | priv->oldspeed = 0; | 1924 | priv->oldspeed = 0; |
1648 | priv->oldduplex = -1; | 1925 | priv->oldduplex = -1; |
@@ -1664,8 +1941,9 @@ static void gfar_set_multi(struct net_device *dev) | |||
1664 | u32 tempval; | 1941 | u32 tempval; |
1665 | 1942 | ||
1666 | if(dev->flags & IFF_PROMISC) { | 1943 | if(dev->flags & IFF_PROMISC) { |
1667 | printk(KERN_INFO "%s: Entering promiscuous mode.\n", | 1944 | if (netif_msg_drv(priv)) |
1668 | dev->name); | 1945 | printk(KERN_INFO "%s: Entering promiscuous mode.\n", |
1946 | dev->name); | ||
1669 | /* Set RCTRL to PROM */ | 1947 | /* Set RCTRL to PROM */ |
1670 | tempval = gfar_read(®s->rctrl); | 1948 | tempval = gfar_read(®s->rctrl); |
1671 | tempval |= RCTRL_PROM; | 1949 | tempval |= RCTRL_PROM; |
@@ -1679,6 +1957,14 @@ static void gfar_set_multi(struct net_device *dev) | |||
1679 | 1957 | ||
1680 | if(dev->flags & IFF_ALLMULTI) { | 1958 | if(dev->flags & IFF_ALLMULTI) { |
1681 | /* Set the hash to rx all multicast frames */ | 1959 | /* Set the hash to rx all multicast frames */ |
1960 | gfar_write(®s->igaddr0, 0xffffffff); | ||
1961 | gfar_write(®s->igaddr1, 0xffffffff); | ||
1962 | gfar_write(®s->igaddr2, 0xffffffff); | ||
1963 | gfar_write(®s->igaddr3, 0xffffffff); | ||
1964 | gfar_write(®s->igaddr4, 0xffffffff); | ||
1965 | gfar_write(®s->igaddr5, 0xffffffff); | ||
1966 | gfar_write(®s->igaddr6, 0xffffffff); | ||
1967 | gfar_write(®s->igaddr7, 0xffffffff); | ||
1682 | gfar_write(®s->gaddr0, 0xffffffff); | 1968 | gfar_write(®s->gaddr0, 0xffffffff); |
1683 | gfar_write(®s->gaddr1, 0xffffffff); | 1969 | gfar_write(®s->gaddr1, 0xffffffff); |
1684 | gfar_write(®s->gaddr2, 0xffffffff); | 1970 | gfar_write(®s->gaddr2, 0xffffffff); |
@@ -1689,6 +1975,14 @@ static void gfar_set_multi(struct net_device *dev) | |||
1689 | gfar_write(®s->gaddr7, 0xffffffff); | 1975 | gfar_write(®s->gaddr7, 0xffffffff); |
1690 | } else { | 1976 | } else { |
1691 | /* zero out the hash */ | 1977 | /* zero out the hash */ |
1978 | gfar_write(®s->igaddr0, 0x0); | ||
1979 | gfar_write(®s->igaddr1, 0x0); | ||
1980 | gfar_write(®s->igaddr2, 0x0); | ||
1981 | gfar_write(®s->igaddr3, 0x0); | ||
1982 | gfar_write(®s->igaddr4, 0x0); | ||
1983 | gfar_write(®s->igaddr5, 0x0); | ||
1984 | gfar_write(®s->igaddr6, 0x0); | ||
1985 | gfar_write(®s->igaddr7, 0x0); | ||
1692 | gfar_write(®s->gaddr0, 0x0); | 1986 | gfar_write(®s->gaddr0, 0x0); |
1693 | gfar_write(®s->gaddr1, 0x0); | 1987 | gfar_write(®s->gaddr1, 0x0); |
1694 | gfar_write(®s->gaddr2, 0x0); | 1988 | gfar_write(®s->gaddr2, 0x0); |
@@ -1727,16 +2021,15 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr) | |||
1727 | { | 2021 | { |
1728 | u32 tempval; | 2022 | u32 tempval; |
1729 | struct gfar_private *priv = netdev_priv(dev); | 2023 | struct gfar_private *priv = netdev_priv(dev); |
1730 | struct gfar *regs = priv->regs; | ||
1731 | u32 *hash = ®s->gaddr0; | ||
1732 | u32 result = ether_crc(MAC_ADDR_LEN, addr); | 2024 | u32 result = ether_crc(MAC_ADDR_LEN, addr); |
1733 | u8 whichreg = ((result >> 29) & 0x7); | 2025 | int width = priv->hash_width; |
1734 | u8 whichbit = ((result >> 24) & 0x1f); | 2026 | u8 whichbit = (result >> (32 - width)) & 0x1f; |
2027 | u8 whichreg = result >> (32 - width + 5); | ||
1735 | u32 value = (1 << (31-whichbit)); | 2028 | u32 value = (1 << (31-whichbit)); |
1736 | 2029 | ||
1737 | tempval = gfar_read(&hash[whichreg]); | 2030 | tempval = gfar_read(priv->hash_regs[whichreg]); |
1738 | tempval |= value; | 2031 | tempval |= value; |
1739 | gfar_write(&hash[whichreg], tempval); | 2032 | gfar_write(priv->hash_regs[whichreg], tempval); |
1740 | 2033 | ||
1741 | return; | 2034 | return; |
1742 | } | 2035 | } |
@@ -1754,10 +2047,9 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) | |||
1754 | gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK); | 2047 | gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK); |
1755 | 2048 | ||
1756 | /* Hmm... */ | 2049 | /* Hmm... */ |
1757 | #if defined (BRIEF_GFAR_ERRORS) || defined (VERBOSE_GFAR_ERRORS) | 2050 | if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv)) |
1758 | printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n", | 2051 | printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n", |
1759 | dev->name, events, gfar_read(&priv->regs->imask)); | 2052 | dev->name, events, gfar_read(&priv->regs->imask)); |
1760 | #endif | ||
1761 | 2053 | ||
1762 | /* Update the error counters */ | 2054 | /* Update the error counters */ |
1763 | if (events & IEVENT_TXE) { | 2055 | if (events & IEVENT_TXE) { |
@@ -1768,19 +2060,17 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) | |||
1768 | if (events & IEVENT_CRL) | 2060 | if (events & IEVENT_CRL) |
1769 | priv->stats.tx_aborted_errors++; | 2061 | priv->stats.tx_aborted_errors++; |
1770 | if (events & IEVENT_XFUN) { | 2062 | if (events & IEVENT_XFUN) { |
1771 | #ifdef VERBOSE_GFAR_ERRORS | 2063 | if (netif_msg_tx_err(priv)) |
1772 | printk(KERN_DEBUG "%s: underrun. packet dropped.\n", | 2064 | printk(KERN_DEBUG "%s: underrun. packet dropped.\n", |
1773 | dev->name); | 2065 | dev->name); |
1774 | #endif | ||
1775 | priv->stats.tx_dropped++; | 2066 | priv->stats.tx_dropped++; |
1776 | priv->extra_stats.tx_underrun++; | 2067 | priv->extra_stats.tx_underrun++; |
1777 | 2068 | ||
1778 | /* Reactivate the Tx Queues */ | 2069 | /* Reactivate the Tx Queues */ |
1779 | gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); | 2070 | gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); |
1780 | } | 2071 | } |
1781 | #ifdef VERBOSE_GFAR_ERRORS | 2072 | if (netif_msg_tx_err(priv)) |
1782 | printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); | 2073 | printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); |
1783 | #endif | ||
1784 | } | 2074 | } |
1785 | if (events & IEVENT_BSY) { | 2075 | if (events & IEVENT_BSY) { |
1786 | priv->stats.rx_errors++; | 2076 | priv->stats.rx_errors++; |
@@ -1793,35 +2083,31 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) | |||
1793 | gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); | 2083 | gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); |
1794 | #endif | 2084 | #endif |
1795 | 2085 | ||
1796 | #ifdef VERBOSE_GFAR_ERRORS | 2086 | if (netif_msg_rx_err(priv)) |
1797 | printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name, | 2087 | printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", |
1798 | gfar_read(&priv->regs->rstat)); | 2088 | dev->name, |
1799 | #endif | 2089 | gfar_read(&priv->regs->rstat)); |
1800 | } | 2090 | } |
1801 | if (events & IEVENT_BABR) { | 2091 | if (events & IEVENT_BABR) { |
1802 | priv->stats.rx_errors++; | 2092 | priv->stats.rx_errors++; |
1803 | priv->extra_stats.rx_babr++; | 2093 | priv->extra_stats.rx_babr++; |
1804 | 2094 | ||
1805 | #ifdef VERBOSE_GFAR_ERRORS | 2095 | if (netif_msg_rx_err(priv)) |
1806 | printk(KERN_DEBUG "%s: babbling error\n", dev->name); | 2096 | printk(KERN_DEBUG "%s: babbling error\n", dev->name); |
1807 | #endif | ||
1808 | } | 2097 | } |
1809 | if (events & IEVENT_EBERR) { | 2098 | if (events & IEVENT_EBERR) { |
1810 | priv->extra_stats.eberr++; | 2099 | priv->extra_stats.eberr++; |
1811 | #ifdef VERBOSE_GFAR_ERRORS | 2100 | if (netif_msg_rx_err(priv)) |
1812 | printk(KERN_DEBUG "%s: EBERR\n", dev->name); | 2101 | printk(KERN_DEBUG "%s: EBERR\n", dev->name); |
1813 | #endif | ||
1814 | } | 2102 | } |
1815 | if (events & IEVENT_RXC) | 2103 | if ((events & IEVENT_RXC) && netif_msg_rx_status(priv)) |
1816 | #ifdef VERBOSE_GFAR_ERRORS | 2104 | if (netif_msg_rx_status(priv)) |
1817 | printk(KERN_DEBUG "%s: control frame\n", dev->name); | 2105 | printk(KERN_DEBUG "%s: control frame\n", dev->name); |
1818 | #endif | ||
1819 | 2106 | ||
1820 | if (events & IEVENT_BABT) { | 2107 | if (events & IEVENT_BABT) { |
1821 | priv->extra_stats.tx_babt++; | 2108 | priv->extra_stats.tx_babt++; |
1822 | #ifdef VERBOSE_GFAR_ERRORS | 2109 | if (netif_msg_tx_err(priv)) |
1823 | printk(KERN_DEBUG "%s: babt error\n", dev->name); | 2110 | printk(KERN_DEBUG "%s: babt error\n", dev->name); |
1824 | #endif | ||
1825 | } | 2111 | } |
1826 | return IRQ_HANDLED; | 2112 | return IRQ_HANDLED; |
1827 | } | 2113 | } |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index c2f783a6a9fa..28af087d9fbb 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/net/gianfar.h | 2 | * drivers/net/gianfar.h |
3 | * | 3 | * |
4 | * Gianfar Ethernet Driver | 4 | * Gianfar Ethernet Driver |
@@ -53,6 +53,12 @@ | |||
53 | /* The maximum number of packets to be handled in one call of gfar_poll */ | 53 | /* The maximum number of packets to be handled in one call of gfar_poll */ |
54 | #define GFAR_DEV_WEIGHT 64 | 54 | #define GFAR_DEV_WEIGHT 64 |
55 | 55 | ||
56 | /* Length for FCB */ | ||
57 | #define GMAC_FCB_LEN 8 | ||
58 | |||
59 | /* Default padding amount */ | ||
60 | #define DEFAULT_PADDING 2 | ||
61 | |||
56 | /* Number of bytes to align the rx bufs to */ | 62 | /* Number of bytes to align the rx bufs to */ |
57 | #define RXBUF_ALIGNMENT 64 | 63 | #define RXBUF_ALIGNMENT 64 |
58 | 64 | ||
@@ -91,7 +97,7 @@ extern const char gfar_driver_version[]; | |||
91 | #define JUMBO_FRAME_SIZE 9600 | 97 | #define JUMBO_FRAME_SIZE 9600 |
92 | 98 | ||
93 | /* Latency of interface clock in nanoseconds */ | 99 | /* Latency of interface clock in nanoseconds */ |
94 | /* Interface clock latency , in this case, means the | 100 | /* Interface clock latency , in this case, means the |
95 | * time described by a value of 1 in the interrupt | 101 | * time described by a value of 1 in the interrupt |
96 | * coalescing registers' time fields. Since those fields | 102 | * coalescing registers' time fields. Since those fields |
97 | * refer to the time it takes for 64 clocks to pass, the | 103 | * refer to the time it takes for 64 clocks to pass, the |
@@ -166,9 +172,28 @@ extern const char gfar_driver_version[]; | |||
166 | mk_ic_icft(count) | \ | 172 | mk_ic_icft(count) | \ |
167 | mk_ic_ictt(time)) | 173 | mk_ic_ictt(time)) |
168 | 174 | ||
175 | #define RCTRL_PAL_MASK 0x001f0000 | ||
176 | #define RCTRL_VLEX 0x00002000 | ||
177 | #define RCTRL_FILREN 0x00001000 | ||
178 | #define RCTRL_GHTX 0x00000400 | ||
179 | #define RCTRL_IPCSEN 0x00000200 | ||
180 | #define RCTRL_TUCSEN 0x00000100 | ||
181 | #define RCTRL_PRSDEP_MASK 0x000000c0 | ||
182 | #define RCTRL_PRSDEP_INIT 0x000000c0 | ||
169 | #define RCTRL_PROM 0x00000008 | 183 | #define RCTRL_PROM 0x00000008 |
184 | #define RCTRL_CHECKSUMMING (RCTRL_IPCSEN \ | ||
185 | | RCTRL_TUCSEN | RCTRL_PRSDEP_INIT) | ||
186 | #define RCTRL_EXTHASH (RCTRL_GHTX) | ||
187 | #define RCTRL_VLAN (RCTRL_PRSDEP_INIT) | ||
188 | |||
189 | |||
170 | #define RSTAT_CLEAR_RHALT 0x00800000 | 190 | #define RSTAT_CLEAR_RHALT 0x00800000 |
171 | 191 | ||
192 | #define TCTRL_IPCSEN 0x00004000 | ||
193 | #define TCTRL_TUCSEN 0x00002000 | ||
194 | #define TCTRL_VLINS 0x00001000 | ||
195 | #define TCTRL_INIT_CSUM (TCTRL_TUCSEN | TCTRL_IPCSEN) | ||
196 | |||
172 | #define IEVENT_INIT_CLEAR 0xffffffff | 197 | #define IEVENT_INIT_CLEAR 0xffffffff |
173 | #define IEVENT_BABR 0x80000000 | 198 | #define IEVENT_BABR 0x80000000 |
174 | #define IEVENT_RXC 0x40000000 | 199 | #define IEVENT_RXC 0x40000000 |
@@ -187,12 +212,16 @@ extern const char gfar_driver_version[]; | |||
187 | #define IEVENT_RXB0 0x00008000 | 212 | #define IEVENT_RXB0 0x00008000 |
188 | #define IEVENT_GRSC 0x00000100 | 213 | #define IEVENT_GRSC 0x00000100 |
189 | #define IEVENT_RXF0 0x00000080 | 214 | #define IEVENT_RXF0 0x00000080 |
215 | #define IEVENT_FIR 0x00000008 | ||
216 | #define IEVENT_FIQ 0x00000004 | ||
217 | #define IEVENT_DPE 0x00000002 | ||
218 | #define IEVENT_PERR 0x00000001 | ||
190 | #define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0) | 219 | #define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0) |
191 | #define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF) | 220 | #define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF) |
192 | #define IEVENT_ERR_MASK \ | 221 | #define IEVENT_ERR_MASK \ |
193 | (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \ | 222 | (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \ |
194 | IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \ | 223 | IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \ |
195 | | IEVENT_CRL | IEVENT_XFUN) | 224 | | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR) |
196 | 225 | ||
197 | #define IMASK_INIT_CLEAR 0x00000000 | 226 | #define IMASK_INIT_CLEAR 0x00000000 |
198 | #define IMASK_BABR 0x80000000 | 227 | #define IMASK_BABR 0x80000000 |
@@ -212,10 +241,15 @@ extern const char gfar_driver_version[]; | |||
212 | #define IMASK_RXB0 0x00008000 | 241 | #define IMASK_RXB0 0x00008000 |
213 | #define IMASK_GTSC 0x00000100 | 242 | #define IMASK_GTSC 0x00000100 |
214 | #define IMASK_RXFEN0 0x00000080 | 243 | #define IMASK_RXFEN0 0x00000080 |
244 | #define IMASK_FIR 0x00000008 | ||
245 | #define IMASK_FIQ 0x00000004 | ||
246 | #define IMASK_DPE 0x00000002 | ||
247 | #define IMASK_PERR 0x00000001 | ||
215 | #define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY) | 248 | #define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY) |
216 | #define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \ | 249 | #define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \ |
217 | IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \ | 250 | IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \ |
218 | IMASK_XFUN | IMASK_RXC | IMASK_BABT) | 251 | IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \ |
252 | | IMASK_PERR) | ||
219 | 253 | ||
220 | 254 | ||
221 | /* Attribute fields */ | 255 | /* Attribute fields */ |
@@ -254,6 +288,18 @@ extern const char gfar_driver_version[]; | |||
254 | #define TXBD_RETRYLIMIT 0x0040 | 288 | #define TXBD_RETRYLIMIT 0x0040 |
255 | #define TXBD_RETRYCOUNTMASK 0x003c | 289 | #define TXBD_RETRYCOUNTMASK 0x003c |
256 | #define TXBD_UNDERRUN 0x0002 | 290 | #define TXBD_UNDERRUN 0x0002 |
291 | #define TXBD_TOE 0x0002 | ||
292 | |||
293 | /* Tx FCB param bits */ | ||
294 | #define TXFCB_VLN 0x80 | ||
295 | #define TXFCB_IP 0x40 | ||
296 | #define TXFCB_IP6 0x20 | ||
297 | #define TXFCB_TUP 0x10 | ||
298 | #define TXFCB_UDP 0x08 | ||
299 | #define TXFCB_CIP 0x04 | ||
300 | #define TXFCB_CTU 0x02 | ||
301 | #define TXFCB_NPH 0x01 | ||
302 | #define TXFCB_DEFAULT (TXFCB_IP|TXFCB_TUP|TXFCB_CTU|TXFCB_NPH) | ||
257 | 303 | ||
258 | /* RxBD status field bits */ | 304 | /* RxBD status field bits */ |
259 | #define RXBD_EMPTY 0x8000 | 305 | #define RXBD_EMPTY 0x8000 |
@@ -273,6 +319,18 @@ extern const char gfar_driver_version[]; | |||
273 | #define RXBD_TRUNCATED 0x0001 | 319 | #define RXBD_TRUNCATED 0x0001 |
274 | #define RXBD_STATS 0x01ff | 320 | #define RXBD_STATS 0x01ff |
275 | 321 | ||
322 | /* Rx FCB status field bits */ | ||
323 | #define RXFCB_VLN 0x8000 | ||
324 | #define RXFCB_IP 0x4000 | ||
325 | #define RXFCB_IP6 0x2000 | ||
326 | #define RXFCB_TUP 0x1000 | ||
327 | #define RXFCB_CIP 0x0800 | ||
328 | #define RXFCB_CTU 0x0400 | ||
329 | #define RXFCB_EIP 0x0200 | ||
330 | #define RXFCB_ETU 0x0100 | ||
331 | #define RXFCB_PERR_MASK 0x000c | ||
332 | #define RXFCB_PERR_BADL3 0x0008 | ||
333 | |||
276 | struct txbd8 | 334 | struct txbd8 |
277 | { | 335 | { |
278 | u16 status; /* Status Fields */ | 336 | u16 status; /* Status Fields */ |
@@ -280,6 +338,22 @@ struct txbd8 | |||
280 | u32 bufPtr; /* Buffer Pointer */ | 338 | u32 bufPtr; /* Buffer Pointer */ |
281 | }; | 339 | }; |
282 | 340 | ||
341 | struct txfcb { | ||
342 | u8 vln:1, | ||
343 | ip:1, | ||
344 | ip6:1, | ||
345 | tup:1, | ||
346 | udp:1, | ||
347 | cip:1, | ||
348 | ctu:1, | ||
349 | nph:1; | ||
350 | u8 reserved; | ||
351 | u8 l4os; /* Level 4 Header Offset */ | ||
352 | u8 l3os; /* Level 3 Header Offset */ | ||
353 | u16 phcs; /* Pseudo-header Checksum */ | ||
354 | u16 vlctl; /* VLAN control word */ | ||
355 | }; | ||
356 | |||
283 | struct rxbd8 | 357 | struct rxbd8 |
284 | { | 358 | { |
285 | u16 status; /* Status Fields */ | 359 | u16 status; /* Status Fields */ |
@@ -287,6 +361,21 @@ struct rxbd8 | |||
287 | u32 bufPtr; /* Buffer Pointer */ | 361 | u32 bufPtr; /* Buffer Pointer */ |
288 | }; | 362 | }; |
289 | 363 | ||
364 | struct rxfcb { | ||
365 | u16 vln:1, | ||
366 | ip:1, | ||
367 | ip6:1, | ||
368 | tup:1, | ||
369 | cip:1, | ||
370 | ctu:1, | ||
371 | eip:1, | ||
372 | etu:1; | ||
373 | u8 rq; /* Receive Queue index */ | ||
374 | u8 pro; /* Layer 4 Protocol */ | ||
375 | u16 reserved; | ||
376 | u16 vlctl; /* VLAN control word */ | ||
377 | }; | ||
378 | |||
290 | struct rmon_mib | 379 | struct rmon_mib |
291 | { | 380 | { |
292 | u32 tr64; /* 0x.680 - Transmit and Receive 64-byte Frame Counter */ | 381 | u32 tr64; /* 0x.680 - Transmit and Receive 64-byte Frame Counter */ |
@@ -371,90 +460,191 @@ struct gfar_stats { | |||
371 | 460 | ||
372 | 461 | ||
373 | struct gfar { | 462 | struct gfar { |
374 | u8 res1[16]; | 463 | u32 tsec_id; /* 0x.000 - Controller ID register */ |
375 | u32 ievent; /* 0x.010 - Interrupt Event Register */ | 464 | u8 res1[12]; |
376 | u32 imask; /* 0x.014 - Interrupt Mask Register */ | 465 | u32 ievent; /* 0x.010 - Interrupt Event Register */ |
377 | u32 edis; /* 0x.018 - Error Disabled Register */ | 466 | u32 imask; /* 0x.014 - Interrupt Mask Register */ |
467 | u32 edis; /* 0x.018 - Error Disabled Register */ | ||
378 | u8 res2[4]; | 468 | u8 res2[4]; |
379 | u32 ecntrl; /* 0x.020 - Ethernet Control Register */ | 469 | u32 ecntrl; /* 0x.020 - Ethernet Control Register */ |
380 | u32 minflr; /* 0x.024 - Minimum Frame Length Register */ | 470 | u32 minflr; /* 0x.024 - Minimum Frame Length Register */ |
381 | u32 ptv; /* 0x.028 - Pause Time Value Register */ | 471 | u32 ptv; /* 0x.028 - Pause Time Value Register */ |
382 | u32 dmactrl; /* 0x.02c - DMA Control Register */ | 472 | u32 dmactrl; /* 0x.02c - DMA Control Register */ |
383 | u32 tbipa; /* 0x.030 - TBI PHY Address Register */ | 473 | u32 tbipa; /* 0x.030 - TBI PHY Address Register */ |
384 | u8 res3[88]; | 474 | u8 res3[88]; |
385 | u32 fifo_tx_thr; /* 0x.08c - FIFO transmit threshold register */ | 475 | u32 fifo_tx_thr; /* 0x.08c - FIFO transmit threshold register */ |
386 | u8 res4[8]; | 476 | u8 res4[8]; |
387 | u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */ | 477 | u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */ |
388 | u32 fifo_tx_starve_shutoff; /* 0x.09c - FIFO transmit starve shutoff register */ | 478 | u32 fifo_tx_starve_shutoff; /* 0x.09c - FIFO transmit starve shutoff register */ |
389 | u8 res5[96]; | 479 | u8 res5[4]; |
390 | u32 tctrl; /* 0x.100 - Transmit Control Register */ | 480 | u32 fifo_rx_pause; /* 0x.0a4 - FIFO receive pause threshold register */ |
391 | u32 tstat; /* 0x.104 - Transmit Status Register */ | 481 | u32 fifo_rx_alarm; /* 0x.0a8 - FIFO receive alarm threshold register */ |
392 | u8 res6[4]; | 482 | u8 res6[84]; |
393 | u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */ | 483 | u32 tctrl; /* 0x.100 - Transmit Control Register */ |
394 | u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */ | 484 | u32 tstat; /* 0x.104 - Transmit Status Register */ |
395 | u8 res7[16]; | 485 | u32 dfvlan; /* 0x.108 - Default VLAN Control word */ |
396 | u32 ctbptr; /* 0x.124 - Current Transmit Buffer Descriptor Pointer Register */ | 486 | u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */ |
397 | u8 res8[92]; | 487 | u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */ |
398 | u32 tbptr; /* 0x.184 - Transmit Buffer Descriptor Pointer Low Register */ | 488 | u32 tqueue; /* 0x.114 - Transmit queue control register */ |
399 | u8 res9[124]; | 489 | u8 res7[40]; |
400 | u32 tbase; /* 0x.204 - Transmit Descriptor Base Address Register */ | 490 | u32 tr03wt; /* 0x.140 - TxBD Rings 0-3 round-robin weightings */ |
401 | u8 res10[168]; | 491 | u32 tr47wt; /* 0x.144 - TxBD Rings 4-7 round-robin weightings */ |
402 | u32 ostbd; /* 0x.2b0 - Out-of-Sequence Transmit Buffer Descriptor Register */ | 492 | u8 res8[52]; |
403 | u32 ostbdp; /* 0x.2b4 - Out-of-Sequence Transmit Data Buffer Pointer Register */ | 493 | u32 tbdbph; /* 0x.17c - Tx data buffer pointer high */ |
404 | u8 res11[72]; | 494 | u8 res9a[4]; |
405 | u32 rctrl; /* 0x.300 - Receive Control Register */ | 495 | u32 tbptr0; /* 0x.184 - TxBD Pointer for ring 0 */ |
406 | u32 rstat; /* 0x.304 - Receive Status Register */ | 496 | u8 res9b[4]; |
407 | u8 res12[4]; | 497 | u32 tbptr1; /* 0x.18c - TxBD Pointer for ring 1 */ |
408 | u32 rbdlen; /* 0x.30c - RxBD Data Length Register */ | 498 | u8 res9c[4]; |
409 | u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */ | 499 | u32 tbptr2; /* 0x.194 - TxBD Pointer for ring 2 */ |
410 | u8 res13[16]; | 500 | u8 res9d[4]; |
411 | u32 crbptr; /* 0x.324 - Current Receive Buffer Descriptor Pointer */ | 501 | u32 tbptr3; /* 0x.19c - TxBD Pointer for ring 3 */ |
412 | u8 res14[24]; | 502 | u8 res9e[4]; |
413 | u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */ | 503 | u32 tbptr4; /* 0x.1a4 - TxBD Pointer for ring 4 */ |
414 | u8 res15[64]; | 504 | u8 res9f[4]; |
415 | u32 rbptr; /* 0x.384 - Receive Buffer Descriptor Pointer */ | 505 | u32 tbptr5; /* 0x.1ac - TxBD Pointer for ring 5 */ |
416 | u8 res16[124]; | 506 | u8 res9g[4]; |
417 | u32 rbase; /* 0x.404 - Receive Descriptor Base Address */ | 507 | u32 tbptr6; /* 0x.1b4 - TxBD Pointer for ring 6 */ |
418 | u8 res17[248]; | 508 | u8 res9h[4]; |
419 | u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */ | 509 | u32 tbptr7; /* 0x.1bc - TxBD Pointer for ring 7 */ |
420 | u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */ | 510 | u8 res9[64]; |
421 | u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */ | 511 | u32 tbaseh; /* 0x.200 - TxBD base address high */ |
422 | u32 hafdup; /* 0x.50c - Half Duplex Register */ | 512 | u32 tbase0; /* 0x.204 - TxBD Base Address of ring 0 */ |
423 | u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */ | 513 | u8 res10a[4]; |
514 | u32 tbase1; /* 0x.20c - TxBD Base Address of ring 1 */ | ||
515 | u8 res10b[4]; | ||
516 | u32 tbase2; /* 0x.214 - TxBD Base Address of ring 2 */ | ||
517 | u8 res10c[4]; | ||
518 | u32 tbase3; /* 0x.21c - TxBD Base Address of ring 3 */ | ||
519 | u8 res10d[4]; | ||
520 | u32 tbase4; /* 0x.224 - TxBD Base Address of ring 4 */ | ||
521 | u8 res10e[4]; | ||
522 | u32 tbase5; /* 0x.22c - TxBD Base Address of ring 5 */ | ||
523 | u8 res10f[4]; | ||
524 | u32 tbase6; /* 0x.234 - TxBD Base Address of ring 6 */ | ||
525 | u8 res10g[4]; | ||
526 | u32 tbase7; /* 0x.23c - TxBD Base Address of ring 7 */ | ||
527 | u8 res10[192]; | ||
528 | u32 rctrl; /* 0x.300 - Receive Control Register */ | ||
529 | u32 rstat; /* 0x.304 - Receive Status Register */ | ||
530 | u8 res12[8]; | ||
531 | u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */ | ||
532 | u32 rqueue; /* 0x.314 - Receive queue control register */ | ||
533 | u8 res13[24]; | ||
534 | u32 rbifx; /* 0x.330 - Receive bit field extract control register */ | ||
535 | u32 rqfar; /* 0x.334 - Receive queue filing table address register */ | ||
536 | u32 rqfcr; /* 0x.338 - Receive queue filing table control register */ | ||
537 | u32 rqfpr; /* 0x.33c - Receive queue filing table property register */ | ||
538 | u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */ | ||
539 | u8 res14[56]; | ||
540 | u32 rbdbph; /* 0x.37c - Rx data buffer pointer high */ | ||
541 | u8 res15a[4]; | ||
542 | u32 rbptr0; /* 0x.384 - RxBD pointer for ring 0 */ | ||
543 | u8 res15b[4]; | ||
544 | u32 rbptr1; /* 0x.38c - RxBD pointer for ring 1 */ | ||
545 | u8 res15c[4]; | ||
546 | u32 rbptr2; /* 0x.394 - RxBD pointer for ring 2 */ | ||
547 | u8 res15d[4]; | ||
548 | u32 rbptr3; /* 0x.39c - RxBD pointer for ring 3 */ | ||
549 | u8 res15e[4]; | ||
550 | u32 rbptr4; /* 0x.3a4 - RxBD pointer for ring 4 */ | ||
551 | u8 res15f[4]; | ||
552 | u32 rbptr5; /* 0x.3ac - RxBD pointer for ring 5 */ | ||
553 | u8 res15g[4]; | ||
554 | u32 rbptr6; /* 0x.3b4 - RxBD pointer for ring 6 */ | ||
555 | u8 res15h[4]; | ||
556 | u32 rbptr7; /* 0x.3bc - RxBD pointer for ring 7 */ | ||
557 | u8 res16[64]; | ||
558 | u32 rbaseh; /* 0x.400 - RxBD base address high */ | ||
559 | u32 rbase0; /* 0x.404 - RxBD base address of ring 0 */ | ||
560 | u8 res17a[4]; | ||
561 | u32 rbase1; /* 0x.40c - RxBD base address of ring 1 */ | ||
562 | u8 res17b[4]; | ||
563 | u32 rbase2; /* 0x.414 - RxBD base address of ring 2 */ | ||
564 | u8 res17c[4]; | ||
565 | u32 rbase3; /* 0x.41c - RxBD base address of ring 3 */ | ||
566 | u8 res17d[4]; | ||
567 | u32 rbase4; /* 0x.424 - RxBD base address of ring 4 */ | ||
568 | u8 res17e[4]; | ||
569 | u32 rbase5; /* 0x.42c - RxBD base address of ring 5 */ | ||
570 | u8 res17f[4]; | ||
571 | u32 rbase6; /* 0x.434 - RxBD base address of ring 6 */ | ||
572 | u8 res17g[4]; | ||
573 | u32 rbase7; /* 0x.43c - RxBD base address of ring 7 */ | ||
574 | u8 res17[192]; | ||
575 | u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */ | ||
576 | u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */ | ||
577 | u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */ | ||
578 | u32 hafdup; /* 0x.50c - Half Duplex Register */ | ||
579 | u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */ | ||
424 | u8 res18[12]; | 580 | u8 res18[12]; |
425 | u32 miimcfg; /* 0x.520 - MII Management Configuration Register */ | 581 | u32 miimcfg; /* 0x.520 - MII Management Configuration Register */ |
426 | u32 miimcom; /* 0x.524 - MII Management Command Register */ | 582 | u32 miimcom; /* 0x.524 - MII Management Command Register */ |
427 | u32 miimadd; /* 0x.528 - MII Management Address Register */ | 583 | u32 miimadd; /* 0x.528 - MII Management Address Register */ |
428 | u32 miimcon; /* 0x.52c - MII Management Control Register */ | 584 | u32 miimcon; /* 0x.52c - MII Management Control Register */ |
429 | u32 miimstat; /* 0x.530 - MII Management Status Register */ | 585 | u32 miimstat; /* 0x.530 - MII Management Status Register */ |
430 | u32 miimind; /* 0x.534 - MII Management Indicator Register */ | 586 | u32 miimind; /* 0x.534 - MII Management Indicator Register */ |
431 | u8 res19[4]; | 587 | u8 res19[4]; |
432 | u32 ifstat; /* 0x.53c - Interface Status Register */ | 588 | u32 ifstat; /* 0x.53c - Interface Status Register */ |
433 | u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ | 589 | u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ |
434 | u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */ | 590 | u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */ |
435 | u8 res20[312]; | 591 | u32 mac01addr1; /* 0x.548 - MAC exact match address 1, part 1 */ |
436 | struct rmon_mib rmon; | 592 | u32 mac01addr2; /* 0x.54c - MAC exact match address 1, part 2 */ |
437 | u8 res21[192]; | 593 | u32 mac02addr1; /* 0x.550 - MAC exact match address 2, part 1 */ |
438 | u32 iaddr0; /* 0x.800 - Indivdual address register 0 */ | 594 | u32 mac02addr2; /* 0x.554 - MAC exact match address 2, part 2 */ |
439 | u32 iaddr1; /* 0x.804 - Indivdual address register 1 */ | 595 | u32 mac03addr1; /* 0x.558 - MAC exact match address 3, part 1 */ |
440 | u32 iaddr2; /* 0x.808 - Indivdual address register 2 */ | 596 | u32 mac03addr2; /* 0x.55c - MAC exact match address 3, part 2 */ |
441 | u32 iaddr3; /* 0x.80c - Indivdual address register 3 */ | 597 | u32 mac04addr1; /* 0x.560 - MAC exact match address 4, part 1 */ |
442 | u32 iaddr4; /* 0x.810 - Indivdual address register 4 */ | 598 | u32 mac04addr2; /* 0x.564 - MAC exact match address 4, part 2 */ |
443 | u32 iaddr5; /* 0x.814 - Indivdual address register 5 */ | 599 | u32 mac05addr1; /* 0x.568 - MAC exact match address 5, part 1 */ |
444 | u32 iaddr6; /* 0x.818 - Indivdual address register 6 */ | 600 | u32 mac05addr2; /* 0x.56c - MAC exact match address 5, part 2 */ |
445 | u32 iaddr7; /* 0x.81c - Indivdual address register 7 */ | 601 | u32 mac06addr1; /* 0x.570 - MAC exact match address 6, part 1 */ |
602 | u32 mac06addr2; /* 0x.574 - MAC exact match address 6, part 2 */ | ||
603 | u32 mac07addr1; /* 0x.578 - MAC exact match address 7, part 1 */ | ||
604 | u32 mac07addr2; /* 0x.57c - MAC exact match address 7, part 2 */ | ||
605 | u32 mac08addr1; /* 0x.580 - MAC exact match address 8, part 1 */ | ||
606 | u32 mac08addr2; /* 0x.584 - MAC exact match address 8, part 2 */ | ||
607 | u32 mac09addr1; /* 0x.588 - MAC exact match address 9, part 1 */ | ||
608 | u32 mac09addr2; /* 0x.58c - MAC exact match address 9, part 2 */ | ||
609 | u32 mac10addr1; /* 0x.590 - MAC exact match address 10, part 1*/ | ||
610 | u32 mac10addr2; /* 0x.594 - MAC exact match address 10, part 2*/ | ||
611 | u32 mac11addr1; /* 0x.598 - MAC exact match address 11, part 1*/ | ||
612 | u32 mac11addr2; /* 0x.59c - MAC exact match address 11, part 2*/ | ||
613 | u32 mac12addr1; /* 0x.5a0 - MAC exact match address 12, part 1*/ | ||
614 | u32 mac12addr2; /* 0x.5a4 - MAC exact match address 12, part 2*/ | ||
615 | u32 mac13addr1; /* 0x.5a8 - MAC exact match address 13, part 1*/ | ||
616 | u32 mac13addr2; /* 0x.5ac - MAC exact match address 13, part 2*/ | ||
617 | u32 mac14addr1; /* 0x.5b0 - MAC exact match address 14, part 1*/ | ||
618 | u32 mac14addr2; /* 0x.5b4 - MAC exact match address 14, part 2*/ | ||
619 | u32 mac15addr1; /* 0x.5b8 - MAC exact match address 15, part 1*/ | ||
620 | u32 mac15addr2; /* 0x.5bc - MAC exact match address 15, part 2*/ | ||
621 | u8 res20[192]; | ||
622 | struct rmon_mib rmon; /* 0x.680-0x.73c */ | ||
623 | u32 rrej; /* 0x.740 - Receive filer rejected packet counter */ | ||
624 | u8 res21[188]; | ||
625 | u32 igaddr0; /* 0x.800 - Indivdual/Group address register 0*/ | ||
626 | u32 igaddr1; /* 0x.804 - Indivdual/Group address register 1*/ | ||
627 | u32 igaddr2; /* 0x.808 - Indivdual/Group address register 2*/ | ||
628 | u32 igaddr3; /* 0x.80c - Indivdual/Group address register 3*/ | ||
629 | u32 igaddr4; /* 0x.810 - Indivdual/Group address register 4*/ | ||
630 | u32 igaddr5; /* 0x.814 - Indivdual/Group address register 5*/ | ||
631 | u32 igaddr6; /* 0x.818 - Indivdual/Group address register 6*/ | ||
632 | u32 igaddr7; /* 0x.81c - Indivdual/Group address register 7*/ | ||
446 | u8 res22[96]; | 633 | u8 res22[96]; |
447 | u32 gaddr0; /* 0x.880 - Global address register 0 */ | 634 | u32 gaddr0; /* 0x.880 - Group address register 0 */ |
448 | u32 gaddr1; /* 0x.884 - Global address register 1 */ | 635 | u32 gaddr1; /* 0x.884 - Group address register 1 */ |
449 | u32 gaddr2; /* 0x.888 - Global address register 2 */ | 636 | u32 gaddr2; /* 0x.888 - Group address register 2 */ |
450 | u32 gaddr3; /* 0x.88c - Global address register 3 */ | 637 | u32 gaddr3; /* 0x.88c - Group address register 3 */ |
451 | u32 gaddr4; /* 0x.890 - Global address register 4 */ | 638 | u32 gaddr4; /* 0x.890 - Group address register 4 */ |
452 | u32 gaddr5; /* 0x.894 - Global address register 5 */ | 639 | u32 gaddr5; /* 0x.894 - Group address register 5 */ |
453 | u32 gaddr6; /* 0x.898 - Global address register 6 */ | 640 | u32 gaddr6; /* 0x.898 - Group address register 6 */ |
454 | u32 gaddr7; /* 0x.89c - Global address register 7 */ | 641 | u32 gaddr7; /* 0x.89c - Group address register 7 */ |
455 | u8 res23[856]; | 642 | u8 res23a[352]; |
456 | u32 attr; /* 0x.bf8 - Attributes Register */ | 643 | u32 fifocfg; /* 0x.a00 - FIFO interface config register */ |
457 | u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */ | 644 | u8 res23b[252]; |
645 | u8 res23c[248]; | ||
646 | u32 attr; /* 0x.bf8 - Attributes Register */ | ||
647 | u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */ | ||
458 | u8 res24[1024]; | 648 | u8 res24[1024]; |
459 | 649 | ||
460 | }; | 650 | }; |
@@ -496,6 +686,8 @@ struct gfar_private { | |||
496 | struct txbd8 *cur_tx; /* Next free ring entry */ | 686 | struct txbd8 *cur_tx; /* Next free ring entry */ |
497 | struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ | 687 | struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ |
498 | struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ | 688 | struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ |
689 | u32 *hash_regs[16]; | ||
690 | int hash_width; | ||
499 | struct gfar *phyregs; | 691 | struct gfar *phyregs; |
500 | struct work_struct tq; | 692 | struct work_struct tq; |
501 | struct timer_list phy_info_timer; | 693 | struct timer_list phy_info_timer; |
@@ -506,9 +698,12 @@ struct gfar_private { | |||
506 | unsigned int rx_stash_size; | 698 | unsigned int rx_stash_size; |
507 | unsigned int tx_ring_size; | 699 | unsigned int tx_ring_size; |
508 | unsigned int rx_ring_size; | 700 | unsigned int rx_ring_size; |
509 | wait_queue_head_t rxcleanupq; | ||
510 | unsigned int rxclean; | ||
511 | 701 | ||
702 | unsigned char vlan_enable:1, | ||
703 | rx_csum_enable:1, | ||
704 | extended_hash:1; | ||
705 | unsigned short padding; | ||
706 | struct vlan_group *vlgrp; | ||
512 | /* Info structure initialized by board setup code */ | 707 | /* Info structure initialized by board setup code */ |
513 | unsigned int interruptTransmit; | 708 | unsigned int interruptTransmit; |
514 | unsigned int interruptReceive; | 709 | unsigned int interruptReceive; |
@@ -519,6 +714,8 @@ struct gfar_private { | |||
519 | int oldspeed; | 714 | int oldspeed; |
520 | int oldduplex; | 715 | int oldduplex; |
521 | int oldlink; | 716 | int oldlink; |
717 | |||
718 | uint32_t msg_enable; | ||
522 | }; | 719 | }; |
523 | 720 | ||
524 | extern inline u32 gfar_read(volatile unsigned *addr) | 721 | extern inline u32 gfar_read(volatile unsigned *addr) |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 28046e9e88ba..a451de629197 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -46,16 +46,18 @@ | |||
46 | 46 | ||
47 | extern int startup_gfar(struct net_device *dev); | 47 | extern int startup_gfar(struct net_device *dev); |
48 | extern void stop_gfar(struct net_device *dev); | 48 | extern void stop_gfar(struct net_device *dev); |
49 | extern void gfar_receive(int irq, void *dev_id, struct pt_regs *regs); | 49 | extern void gfar_halt(struct net_device *dev); |
50 | extern void gfar_start(struct net_device *dev); | ||
51 | extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); | ||
50 | 52 | ||
51 | void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, | 53 | static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, |
52 | u64 * buf); | 54 | u64 * buf); |
53 | void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); | 55 | static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); |
54 | int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); | 56 | static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); |
55 | int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); | 57 | static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); |
56 | void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals); | 58 | static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals); |
57 | int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); | 59 | static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); |
58 | void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); | 60 | static void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); |
59 | 61 | ||
60 | static char stat_gstrings[][ETH_GSTRING_LEN] = { | 62 | static char stat_gstrings[][ETH_GSTRING_LEN] = { |
61 | "rx-dropped-by-kernel", | 63 | "rx-dropped-by-kernel", |
@@ -118,57 +120,56 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = { | |||
118 | "tx-fragmented-frames", | 120 | "tx-fragmented-frames", |
119 | }; | 121 | }; |
120 | 122 | ||
123 | /* Fill in a buffer with the strings which correspond to the | ||
124 | * stats */ | ||
125 | static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) | ||
126 | { | ||
127 | struct gfar_private *priv = netdev_priv(dev); | ||
128 | |||
129 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) | ||
130 | memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); | ||
131 | else | ||
132 | memcpy(buf, stat_gstrings, | ||
133 | GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN); | ||
134 | } | ||
135 | |||
121 | /* Fill in an array of 64-bit statistics from various sources. | 136 | /* Fill in an array of 64-bit statistics from various sources. |
122 | * This array will be appended to the end of the ethtool_stats | 137 | * This array will be appended to the end of the ethtool_stats |
123 | * structure, and returned to user space | 138 | * structure, and returned to user space |
124 | */ | 139 | */ |
125 | void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) | 140 | static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) |
126 | { | 141 | { |
127 | int i; | 142 | int i; |
128 | struct gfar_private *priv = netdev_priv(dev); | 143 | struct gfar_private *priv = netdev_priv(dev); |
129 | u32 *rmon = (u32 *) & priv->regs->rmon; | ||
130 | u64 *extra = (u64 *) & priv->extra_stats; | 144 | u64 *extra = (u64 *) & priv->extra_stats; |
131 | struct gfar_stats *stats = (struct gfar_stats *) buf; | ||
132 | 145 | ||
133 | for (i = 0; i < GFAR_RMON_LEN; i++) { | 146 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { |
134 | stats->rmon[i] = (u64) (rmon[i]); | 147 | u32 *rmon = (u32 *) & priv->regs->rmon; |
135 | } | 148 | struct gfar_stats *stats = (struct gfar_stats *) buf; |
136 | |||
137 | for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) { | ||
138 | stats->extra[i] = extra[i]; | ||
139 | } | ||
140 | } | ||
141 | 149 | ||
142 | /* Returns the number of stats (and their corresponding strings) */ | 150 | for (i = 0; i < GFAR_RMON_LEN; i++) |
143 | int gfar_stats_count(struct net_device *dev) | 151 | stats->rmon[i] = (u64) (rmon[i]); |
144 | { | ||
145 | return GFAR_STATS_LEN; | ||
146 | } | ||
147 | 152 | ||
148 | void gfar_gstrings_normon(struct net_device *dev, u32 stringset, u8 * buf) | 153 | for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) |
149 | { | 154 | stats->extra[i] = extra[i]; |
150 | memcpy(buf, stat_gstrings, GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN); | 155 | } else |
156 | for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) | ||
157 | buf[i] = extra[i]; | ||
151 | } | 158 | } |
152 | 159 | ||
153 | void gfar_fill_stats_normon(struct net_device *dev, | 160 | /* Returns the number of stats (and their corresponding strings) */ |
154 | struct ethtool_stats *dummy, u64 * buf) | 161 | static int gfar_stats_count(struct net_device *dev) |
155 | { | 162 | { |
156 | int i; | ||
157 | struct gfar_private *priv = netdev_priv(dev); | 163 | struct gfar_private *priv = netdev_priv(dev); |
158 | u64 *extra = (u64 *) & priv->extra_stats; | ||
159 | 164 | ||
160 | for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) { | 165 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) |
161 | buf[i] = extra[i]; | 166 | return GFAR_STATS_LEN; |
162 | } | 167 | else |
168 | return GFAR_EXTRA_STATS_LEN; | ||
163 | } | 169 | } |
164 | 170 | ||
165 | |||
166 | int gfar_stats_count_normon(struct net_device *dev) | ||
167 | { | ||
168 | return GFAR_EXTRA_STATS_LEN; | ||
169 | } | ||
170 | /* Fills in the drvinfo structure with some basic info */ | 171 | /* Fills in the drvinfo structure with some basic info */ |
171 | void gfar_gdrvinfo(struct net_device *dev, struct | 172 | static void gfar_gdrvinfo(struct net_device *dev, struct |
172 | ethtool_drvinfo *drvinfo) | 173 | ethtool_drvinfo *drvinfo) |
173 | { | 174 | { |
174 | strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN); | 175 | strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN); |
@@ -182,7 +183,7 @@ void gfar_gdrvinfo(struct net_device *dev, struct | |||
182 | } | 183 | } |
183 | 184 | ||
184 | /* Return the current settings in the ethtool_cmd structure */ | 185 | /* Return the current settings in the ethtool_cmd structure */ |
185 | int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) | 186 | static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) |
186 | { | 187 | { |
187 | struct gfar_private *priv = netdev_priv(dev); | 188 | struct gfar_private *priv = netdev_priv(dev); |
188 | uint gigabit_support = | 189 | uint gigabit_support = |
@@ -216,13 +217,13 @@ int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
216 | } | 217 | } |
217 | 218 | ||
218 | /* Return the length of the register structure */ | 219 | /* Return the length of the register structure */ |
219 | int gfar_reglen(struct net_device *dev) | 220 | static int gfar_reglen(struct net_device *dev) |
220 | { | 221 | { |
221 | return sizeof (struct gfar); | 222 | return sizeof (struct gfar); |
222 | } | 223 | } |
223 | 224 | ||
224 | /* Return a dump of the GFAR register space */ | 225 | /* Return a dump of the GFAR register space */ |
225 | void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) | 226 | static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) |
226 | { | 227 | { |
227 | int i; | 228 | int i; |
228 | struct gfar_private *priv = netdev_priv(dev); | 229 | struct gfar_private *priv = netdev_priv(dev); |
@@ -233,13 +234,6 @@ void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regb | |||
233 | buf[i] = theregs[i]; | 234 | buf[i] = theregs[i]; |
234 | } | 235 | } |
235 | 236 | ||
236 | /* Fill in a buffer with the strings which correspond to the | ||
237 | * stats */ | ||
238 | void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) | ||
239 | { | ||
240 | memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); | ||
241 | } | ||
242 | |||
243 | /* Convert microseconds to ethernet clock ticks, which changes | 237 | /* Convert microseconds to ethernet clock ticks, which changes |
244 | * depending on what speed the controller is running at */ | 238 | * depending on what speed the controller is running at */ |
245 | static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs) | 239 | static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs) |
@@ -291,9 +285,12 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic | |||
291 | 285 | ||
292 | /* Get the coalescing parameters, and put them in the cvals | 286 | /* Get the coalescing parameters, and put them in the cvals |
293 | * structure. */ | 287 | * structure. */ |
294 | int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) | 288 | static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) |
295 | { | 289 | { |
296 | struct gfar_private *priv = netdev_priv(dev); | 290 | struct gfar_private *priv = netdev_priv(dev); |
291 | |||
292 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) | ||
293 | return -EOPNOTSUPP; | ||
297 | 294 | ||
298 | cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime); | 295 | cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime); |
299 | cvals->rx_max_coalesced_frames = priv->rxcount; | 296 | cvals->rx_max_coalesced_frames = priv->rxcount; |
@@ -337,10 +334,13 @@ int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) | |||
337 | * Both cvals->*_usecs and cvals->*_frames have to be > 0 | 334 | * Both cvals->*_usecs and cvals->*_frames have to be > 0 |
338 | * in order for coalescing to be active | 335 | * in order for coalescing to be active |
339 | */ | 336 | */ |
340 | int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) | 337 | static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) |
341 | { | 338 | { |
342 | struct gfar_private *priv = netdev_priv(dev); | 339 | struct gfar_private *priv = netdev_priv(dev); |
343 | 340 | ||
341 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) | ||
342 | return -EOPNOTSUPP; | ||
343 | |||
344 | /* Set up rx coalescing */ | 344 | /* Set up rx coalescing */ |
345 | if ((cvals->rx_coalesce_usecs == 0) || | 345 | if ((cvals->rx_coalesce_usecs == 0) || |
346 | (cvals->rx_max_coalesced_frames == 0)) | 346 | (cvals->rx_max_coalesced_frames == 0)) |
@@ -379,7 +379,7 @@ int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) | |||
379 | /* Fills in rvals with the current ring parameters. Currently, | 379 | /* Fills in rvals with the current ring parameters. Currently, |
380 | * rx, rx_mini, and rx_jumbo rings are the same size, as mini and | 380 | * rx, rx_mini, and rx_jumbo rings are the same size, as mini and |
381 | * jumbo are ignored by the driver */ | 381 | * jumbo are ignored by the driver */ |
382 | void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) | 382 | static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) |
383 | { | 383 | { |
384 | struct gfar_private *priv = netdev_priv(dev); | 384 | struct gfar_private *priv = netdev_priv(dev); |
385 | 385 | ||
@@ -401,9 +401,8 @@ void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) | |||
401 | * necessary so that we don't mess things up while we're in | 401 | * necessary so that we don't mess things up while we're in |
402 | * motion. We wait for the ring to be clean before reallocating | 402 | * motion. We wait for the ring to be clean before reallocating |
403 | * the rings. */ | 403 | * the rings. */ |
404 | int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) | 404 | static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) |
405 | { | 405 | { |
406 | u32 tempval; | ||
407 | struct gfar_private *priv = netdev_priv(dev); | 406 | struct gfar_private *priv = netdev_priv(dev); |
408 | int err = 0; | 407 | int err = 0; |
409 | 408 | ||
@@ -425,37 +424,54 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) | |||
425 | return -EINVAL; | 424 | return -EINVAL; |
426 | } | 425 | } |
427 | 426 | ||
428 | /* Stop the controller so we don't rx any more frames */ | 427 | if (dev->flags & IFF_UP) { |
429 | /* But first, make sure we clear the bits */ | 428 | unsigned long flags; |
430 | tempval = gfar_read(&priv->regs->dmactrl); | ||
431 | tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); | ||
432 | gfar_write(&priv->regs->dmactrl, tempval); | ||
433 | 429 | ||
434 | tempval = gfar_read(&priv->regs->dmactrl); | 430 | /* Halt TX and RX, and process the frames which |
435 | tempval |= (DMACTRL_GRS | DMACTRL_GTS); | 431 | * have already been received */ |
436 | gfar_write(&priv->regs->dmactrl, tempval); | 432 | spin_lock_irqsave(&priv->lock, flags); |
433 | gfar_halt(dev); | ||
434 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | ||
435 | spin_unlock_irqrestore(&priv->lock, flags); | ||
437 | 436 | ||
438 | while (!(gfar_read(&priv->regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))) | 437 | /* Now we take down the rings to rebuild them */ |
439 | cpu_relax(); | 438 | stop_gfar(dev); |
439 | } | ||
440 | 440 | ||
441 | /* Note that rx is not clean right now */ | 441 | /* Change the size */ |
442 | priv->rxclean = 0; | 442 | priv->rx_ring_size = rvals->rx_pending; |
443 | priv->tx_ring_size = rvals->tx_pending; | ||
443 | 444 | ||
444 | if (dev->flags & IFF_UP) { | 445 | /* Rebuild the rings with the new size */ |
445 | /* Tell the driver to process the rest of the frames */ | 446 | if (dev->flags & IFF_UP) |
446 | gfar_receive(0, (void *) dev, NULL); | 447 | err = startup_gfar(dev); |
447 | 448 | ||
448 | /* Now wait for it to be done */ | 449 | return err; |
449 | wait_event_interruptible(priv->rxcleanupq, priv->rxclean); | 450 | } |
450 | 451 | ||
451 | /* Ok, all packets have been handled. Now we bring it down, | 452 | static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) |
452 | * change the ring size, and bring it up */ | 453 | { |
454 | struct gfar_private *priv = netdev_priv(dev); | ||
455 | int err = 0; | ||
453 | 456 | ||
457 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | ||
458 | return -EOPNOTSUPP; | ||
459 | |||
460 | if (dev->flags & IFF_UP) { | ||
461 | unsigned long flags; | ||
462 | |||
463 | /* Halt TX and RX, and process the frames which | ||
464 | * have already been received */ | ||
465 | spin_lock_irqsave(&priv->lock, flags); | ||
466 | gfar_halt(dev); | ||
467 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | ||
468 | spin_unlock_irqrestore(&priv->lock, flags); | ||
469 | |||
470 | /* Now we take down the rings to rebuild them */ | ||
454 | stop_gfar(dev); | 471 | stop_gfar(dev); |
455 | } | 472 | } |
456 | 473 | ||
457 | priv->rx_ring_size = rvals->rx_pending; | 474 | priv->rx_csum_enable = data; |
458 | priv->tx_ring_size = rvals->tx_pending; | ||
459 | 475 | ||
460 | if (dev->flags & IFF_UP) | 476 | if (dev->flags & IFF_UP) |
461 | err = startup_gfar(dev); | 477 | err = startup_gfar(dev); |
@@ -463,6 +479,61 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) | |||
463 | return err; | 479 | return err; |
464 | } | 480 | } |
465 | 481 | ||
482 | static uint32_t gfar_get_rx_csum(struct net_device *dev) | ||
483 | { | ||
484 | struct gfar_private *priv = netdev_priv(dev); | ||
485 | |||
486 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | ||
487 | return 0; | ||
488 | |||
489 | return priv->rx_csum_enable; | ||
490 | } | ||
491 | |||
492 | static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) | ||
493 | { | ||
494 | unsigned long flags; | ||
495 | struct gfar_private *priv = netdev_priv(dev); | ||
496 | |||
497 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | ||
498 | return -EOPNOTSUPP; | ||
499 | |||
500 | spin_lock_irqsave(&priv->lock, flags); | ||
501 | gfar_halt(dev); | ||
502 | |||
503 | if (data) | ||
504 | dev->features |= NETIF_F_IP_CSUM; | ||
505 | else | ||
506 | dev->features &= ~NETIF_F_IP_CSUM; | ||
507 | |||
508 | gfar_start(dev); | ||
509 | spin_unlock_irqrestore(&priv->lock, flags); | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static uint32_t gfar_get_tx_csum(struct net_device *dev) | ||
515 | { | ||
516 | struct gfar_private *priv = netdev_priv(dev); | ||
517 | |||
518 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | ||
519 | return 0; | ||
520 | |||
521 | return (dev->features & NETIF_F_IP_CSUM) != 0; | ||
522 | } | ||
523 | |||
524 | static uint32_t gfar_get_msglevel(struct net_device *dev) | ||
525 | { | ||
526 | struct gfar_private *priv = netdev_priv(dev); | ||
527 | return priv->msg_enable; | ||
528 | } | ||
529 | |||
530 | static void gfar_set_msglevel(struct net_device *dev, uint32_t data) | ||
531 | { | ||
532 | struct gfar_private *priv = netdev_priv(dev); | ||
533 | priv->msg_enable = data; | ||
534 | } | ||
535 | |||
536 | |||
466 | struct ethtool_ops gfar_ethtool_ops = { | 537 | struct ethtool_ops gfar_ethtool_ops = { |
467 | .get_settings = gfar_gsettings, | 538 | .get_settings = gfar_gsettings, |
468 | .get_drvinfo = gfar_gdrvinfo, | 539 | .get_drvinfo = gfar_gdrvinfo, |
@@ -476,52 +547,10 @@ struct ethtool_ops gfar_ethtool_ops = { | |||
476 | .get_strings = gfar_gstrings, | 547 | .get_strings = gfar_gstrings, |
477 | .get_stats_count = gfar_stats_count, | 548 | .get_stats_count = gfar_stats_count, |
478 | .get_ethtool_stats = gfar_fill_stats, | 549 | .get_ethtool_stats = gfar_fill_stats, |
479 | }; | 550 | .get_rx_csum = gfar_get_rx_csum, |
480 | 551 | .get_tx_csum = gfar_get_tx_csum, | |
481 | struct ethtool_ops gfar_normon_nocoalesce_ethtool_ops = { | 552 | .set_rx_csum = gfar_set_rx_csum, |
482 | .get_settings = gfar_gsettings, | 553 | .set_tx_csum = gfar_set_tx_csum, |
483 | .get_drvinfo = gfar_gdrvinfo, | 554 | .get_msglevel = gfar_get_msglevel, |
484 | .get_regs_len = gfar_reglen, | 555 | .set_msglevel = gfar_set_msglevel, |
485 | .get_regs = gfar_get_regs, | ||
486 | .get_link = ethtool_op_get_link, | ||
487 | .get_ringparam = gfar_gringparam, | ||
488 | .set_ringparam = gfar_sringparam, | ||
489 | .get_strings = gfar_gstrings_normon, | ||
490 | .get_stats_count = gfar_stats_count_normon, | ||
491 | .get_ethtool_stats = gfar_fill_stats_normon, | ||
492 | }; | ||
493 | |||
494 | struct ethtool_ops gfar_nocoalesce_ethtool_ops = { | ||
495 | .get_settings = gfar_gsettings, | ||
496 | .get_drvinfo = gfar_gdrvinfo, | ||
497 | .get_regs_len = gfar_reglen, | ||
498 | .get_regs = gfar_get_regs, | ||
499 | .get_link = ethtool_op_get_link, | ||
500 | .get_ringparam = gfar_gringparam, | ||
501 | .set_ringparam = gfar_sringparam, | ||
502 | .get_strings = gfar_gstrings, | ||
503 | .get_stats_count = gfar_stats_count, | ||
504 | .get_ethtool_stats = gfar_fill_stats, | ||
505 | }; | ||
506 | |||
507 | struct ethtool_ops gfar_normon_ethtool_ops = { | ||
508 | .get_settings = gfar_gsettings, | ||
509 | .get_drvinfo = gfar_gdrvinfo, | ||
510 | .get_regs_len = gfar_reglen, | ||
511 | .get_regs = gfar_get_regs, | ||
512 | .get_link = ethtool_op_get_link, | ||
513 | .get_coalesce = gfar_gcoalesce, | ||
514 | .set_coalesce = gfar_scoalesce, | ||
515 | .get_ringparam = gfar_gringparam, | ||
516 | .set_ringparam = gfar_sringparam, | ||
517 | .get_strings = gfar_gstrings_normon, | ||
518 | .get_stats_count = gfar_stats_count_normon, | ||
519 | .get_ethtool_stats = gfar_fill_stats_normon, | ||
520 | }; | ||
521 | |||
522 | struct ethtool_ops *gfar_op_array[] = { | ||
523 | &gfar_ethtool_ops, | ||
524 | &gfar_normon_ethtool_ops, | ||
525 | &gfar_nocoalesce_ethtool_ops, | ||
526 | &gfar_normon_nocoalesce_ethtool_ops | ||
527 | }; | 556 | }; |
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 13f114876965..3213f3e50487 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c | |||
@@ -850,7 +850,7 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) | |||
850 | if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))) | 850 | if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))) |
851 | data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); | 851 | data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); |
852 | 852 | ||
853 | schedule_timeout(data * HZ); | 853 | msleep_interruptible(data * 1000); |
854 | del_timer_sync(&lp->blink_timer); | 854 | del_timer_sync(&lp->blink_timer); |
855 | 855 | ||
856 | /* Restore the original value of the bcrs */ | 856 | /* Restore the original value of the bcrs */ |
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index e15369c8d165..d6388e1533f0 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c | |||
@@ -90,7 +90,6 @@ static int sb1000_close(struct net_device *dev); | |||
90 | 90 | ||
91 | 91 | ||
92 | /* SB1000 hardware routines to be used during open/configuration phases */ | 92 | /* SB1000 hardware routines to be used during open/configuration phases */ |
93 | static inline void nicedelay(unsigned long usecs); | ||
94 | static inline int card_wait_for_busy_clear(const int ioaddr[], | 93 | static inline int card_wait_for_busy_clear(const int ioaddr[], |
95 | const char* name); | 94 | const char* name); |
96 | static inline int card_wait_for_ready(const int ioaddr[], const char* name, | 95 | static inline int card_wait_for_ready(const int ioaddr[], const char* name, |
@@ -254,13 +253,6 @@ static struct pnp_driver sb1000_driver = { | |||
254 | 253 | ||
255 | static const int TimeOutJiffies = (875 * HZ) / 100; | 254 | static const int TimeOutJiffies = (875 * HZ) / 100; |
256 | 255 | ||
257 | static inline void nicedelay(unsigned long usecs) | ||
258 | { | ||
259 | current->state = TASK_INTERRUPTIBLE; | ||
260 | schedule_timeout(HZ); | ||
261 | return; | ||
262 | } | ||
263 | |||
264 | /* Card Wait For Busy Clear (cannot be used during an interrupt) */ | 256 | /* Card Wait For Busy Clear (cannot be used during an interrupt) */ |
265 | static inline int | 257 | static inline int |
266 | card_wait_for_busy_clear(const int ioaddr[], const char* name) | 258 | card_wait_for_busy_clear(const int ioaddr[], const char* name) |
@@ -475,7 +467,7 @@ sb1000_reset(const int ioaddr[], const char* name) | |||
475 | udelay(1000); | 467 | udelay(1000); |
476 | outb(0x0, port); | 468 | outb(0x0, port); |
477 | inb(port); | 469 | inb(port); |
478 | nicedelay(60000); | 470 | ssleep(1); |
479 | outb(0x4, port); | 471 | outb(0x4, port); |
480 | inb(port); | 472 | inb(port); |
481 | udelay(1000); | 473 | udelay(1000); |
@@ -537,7 +529,7 @@ sb1000_activate(const int ioaddr[], const char* name) | |||
537 | const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00}; | 529 | const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00}; |
538 | const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00}; | 530 | const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00}; |
539 | 531 | ||
540 | nicedelay(50000); | 532 | ssleep(1); |
541 | if ((status = card_send_command(ioaddr, name, Command0, st))) | 533 | if ((status = card_send_command(ioaddr, name, Command0, st))) |
542 | return status; | 534 | return status; |
543 | if ((status = card_send_command(ioaddr, name, Command1, st))) | 535 | if ((status = card_send_command(ioaddr, name, Command1, st))) |
@@ -944,7 +936,7 @@ sb1000_open(struct net_device *dev) | |||
944 | /* initialize sb1000 */ | 936 | /* initialize sb1000 */ |
945 | if ((status = sb1000_reset(ioaddr, name))) | 937 | if ((status = sb1000_reset(ioaddr, name))) |
946 | return status; | 938 | return status; |
947 | nicedelay(200000); | 939 | ssleep(1); |
948 | if ((status = sb1000_check_CRC(ioaddr, name))) | 940 | if ((status = sb1000_check_CRC(ioaddr, name))) |
949 | return status; | 941 | return status; |
950 | 942 | ||
diff --git a/drivers/net/skfp/Makefile b/drivers/net/skfp/Makefile index 5f4bb1a67400..cb23580fcffa 100644 --- a/drivers/net/skfp/Makefile +++ b/drivers/net/skfp/Makefile | |||
@@ -6,8 +6,8 @@ obj-$(CONFIG_SKFP) += skfp.o | |||
6 | 6 | ||
7 | skfp-objs := skfddi.o hwmtm.o fplustm.o smt.o cfm.o \ | 7 | skfp-objs := skfddi.o hwmtm.o fplustm.o smt.o cfm.o \ |
8 | ecm.o pcmplc.o pmf.o queue.o rmt.o \ | 8 | ecm.o pcmplc.o pmf.o queue.o rmt.o \ |
9 | smtdef.o smtinit.o smttimer.o srf.o smtparse.o\ | 9 | smtdef.o smtinit.o smttimer.o srf.o hwt.o \ |
10 | hwt.o drvfbi.o ess.o | 10 | drvfbi.o ess.o |
11 | 11 | ||
12 | # NOTE: | 12 | # NOTE: |
13 | # Compiling this driver produces some warnings (and some more are | 13 | # Compiling this driver produces some warnings (and some more are |
diff --git a/drivers/net/skfp/drvfbi.c b/drivers/net/skfp/drvfbi.c index 052e841ba187..5b475833f645 100644 --- a/drivers/net/skfp/drvfbi.c +++ b/drivers/net/skfp/drvfbi.c | |||
@@ -105,8 +105,8 @@ extern int AIX_vpdReadByte() ; | |||
105 | #endif | 105 | #endif |
106 | 106 | ||
107 | 107 | ||
108 | /* Prototypes of local functions. */ | 108 | /* Prototype of a local function. */ |
109 | void smt_stop_watchdog(struct s_smc *smc); | 109 | static void smt_stop_watchdog(struct s_smc *smc); |
110 | 110 | ||
111 | #ifdef MCA | 111 | #ifdef MCA |
112 | static int read_card_id() ; | 112 | static int read_card_id() ; |
@@ -631,7 +631,7 @@ void plc_clear_irq(struct s_smc *smc, int p) | |||
631 | * LED_Y_OFF just switch yellow LED off | 631 | * LED_Y_OFF just switch yellow LED off |
632 | * LED_Y_ON just switch yello LED on | 632 | * LED_Y_ON just switch yello LED on |
633 | */ | 633 | */ |
634 | void led_indication(struct s_smc *smc, int led_event) | 634 | static void led_indication(struct s_smc *smc, int led_event) |
635 | { | 635 | { |
636 | /* use smc->hw.mac_ring_is_up == TRUE | 636 | /* use smc->hw.mac_ring_is_up == TRUE |
637 | * as indication for Ring Operational | 637 | * as indication for Ring Operational |
@@ -764,122 +764,6 @@ void llc_recover_tx(struct s_smc *smc) | |||
764 | #endif | 764 | #endif |
765 | } | 765 | } |
766 | 766 | ||
767 | /*--------------------------- DMA init ----------------------------*/ | ||
768 | #ifdef ISA | ||
769 | |||
770 | /* | ||
771 | * init DMA | ||
772 | */ | ||
773 | void init_dma(struct s_smc *smc, int dma) | ||
774 | { | ||
775 | SK_UNUSED(smc) ; | ||
776 | |||
777 | /* | ||
778 | * set cascade mode, | ||
779 | * clear mask bit (enable DMA cannal) | ||
780 | */ | ||
781 | if (dma > 3) { | ||
782 | outp(0xd6,(dma & 0x03) | 0xc0) ; | ||
783 | outp(0xd4, dma & 0x03) ; | ||
784 | } | ||
785 | else { | ||
786 | outp(0x0b,(dma & 0x03) | 0xc0) ; | ||
787 | outp(0x0a,dma & 0x03) ; | ||
788 | } | ||
789 | } | ||
790 | |||
791 | /* | ||
792 | * disable DMA | ||
793 | */ | ||
794 | void dis_dma(struct s_smc *smc, int dma) | ||
795 | { | ||
796 | SK_UNUSED(smc) ; | ||
797 | |||
798 | /* | ||
799 | * set mask bit (disable DMA cannal) | ||
800 | */ | ||
801 | if (dma > 3) { | ||
802 | outp(0xd4,(dma & 0x03) | 0x04) ; | ||
803 | } | ||
804 | else { | ||
805 | outp(0x0a,(dma & 0x03) | 0x04) ; | ||
806 | } | ||
807 | } | ||
808 | |||
809 | #endif /* ISA */ | ||
810 | |||
811 | #ifdef EISA | ||
812 | |||
813 | /*arrays with io addresses of dma controller length and address registers*/ | ||
814 | static const int cntr[8] = { 0x001,0x003,0x005,0x007,0,0x0c6,0x0ca,0x0ce } ; | ||
815 | static const int base[8] = { 0x000,0x002,0x004,0x006,0,0x0c4,0x0c8,0x0cc } ; | ||
816 | static const int page[8] = { 0x087,0x083,0x081,0x082,0,0x08b,0x089,0x08a } ; | ||
817 | |||
818 | void init_dma(struct s_smc *smc, int dma) | ||
819 | { | ||
820 | /* | ||
821 | * extended mode register | ||
822 | * 32 bit IO | ||
823 | * type c | ||
824 | * TC output | ||
825 | * disable stop | ||
826 | */ | ||
827 | |||
828 | /* mode read (write) demand */ | ||
829 | smc->hw.dma_rmode = (dma & 3) | 0x08 | 0x0 ; | ||
830 | smc->hw.dma_wmode = (dma & 3) | 0x04 | 0x0 ; | ||
831 | |||
832 | /* 32 bit IO's, burst DMA mode (type "C") */ | ||
833 | smc->hw.dma_emode = (dma & 3) | 0x08 | 0x30 ; | ||
834 | |||
835 | outp((dma < 4) ? 0x40b : 0x4d6,smc->hw.dma_emode) ; | ||
836 | |||
837 | /* disable chaining */ | ||
838 | outp((dma < 4) ? 0x40a : 0x4d4,(dma&3)) ; | ||
839 | |||
840 | /*load dma controller addresses for fast access during set dma*/ | ||
841 | smc->hw.dma_base_word_count = cntr[smc->hw.dma]; | ||
842 | smc->hw.dma_base_address = base[smc->hw.dma]; | ||
843 | smc->hw.dma_base_address_page = page[smc->hw.dma]; | ||
844 | |||
845 | } | ||
846 | |||
847 | void dis_dma(struct s_smc *smc, int dma) | ||
848 | { | ||
849 | SK_UNUSED(smc) ; | ||
850 | |||
851 | outp((dma < 4) ? 0x0a : 0xd4,(dma&3)|4) ;/* mask bit */ | ||
852 | } | ||
853 | #endif /* EISA */ | ||
854 | |||
855 | #ifdef MCA | ||
856 | void init_dma(struct s_smc *smc, int dma) | ||
857 | { | ||
858 | SK_UNUSED(smc) ; | ||
859 | SK_UNUSED(dma) ; | ||
860 | } | ||
861 | |||
862 | void dis_dma(struct s_smc *smc, int dma) | ||
863 | { | ||
864 | SK_UNUSED(smc) ; | ||
865 | SK_UNUSED(dma) ; | ||
866 | } | ||
867 | #endif | ||
868 | |||
869 | #ifdef PCI | ||
870 | void init_dma(struct s_smc *smc, int dma) | ||
871 | { | ||
872 | SK_UNUSED(smc) ; | ||
873 | SK_UNUSED(dma) ; | ||
874 | } | ||
875 | |||
876 | void dis_dma(struct s_smc *smc, int dma) | ||
877 | { | ||
878 | SK_UNUSED(smc) ; | ||
879 | SK_UNUSED(dma) ; | ||
880 | } | ||
881 | #endif | ||
882 | |||
883 | #ifdef MULT_OEM | 767 | #ifdef MULT_OEM |
884 | static int is_equal_num(char comp1[], char comp2[], int num) | 768 | static int is_equal_num(char comp1[], char comp2[], int num) |
885 | { | 769 | { |
@@ -1407,7 +1291,7 @@ void smt_start_watchdog(struct s_smc *smc) | |||
1407 | #endif /* DEBUG */ | 1291 | #endif /* DEBUG */ |
1408 | } | 1292 | } |
1409 | 1293 | ||
1410 | void smt_stop_watchdog(struct s_smc *smc) | 1294 | static void smt_stop_watchdog(struct s_smc *smc) |
1411 | { | 1295 | { |
1412 | SK_UNUSED(smc) ; /* Make LINT happy. */ | 1296 | SK_UNUSED(smc) ; /* Make LINT happy. */ |
1413 | #ifndef DEBUG | 1297 | #ifndef DEBUG |
@@ -1422,104 +1306,6 @@ void smt_stop_watchdog(struct s_smc *smc) | |||
1422 | } | 1306 | } |
1423 | 1307 | ||
1424 | #ifdef PCI | 1308 | #ifdef PCI |
1425 | static char get_rom_byte(struct s_smc *smc, u_short addr) | ||
1426 | { | ||
1427 | GET_PAGE(addr) ; | ||
1428 | return (READ_PROM(ADDR(B2_FDP))) ; | ||
1429 | } | ||
1430 | |||
1431 | /* | ||
1432 | * ROM image defines | ||
1433 | */ | ||
1434 | #define ROM_SIG_1 0 | ||
1435 | #define ROM_SIG_2 1 | ||
1436 | #define PCI_DATA_1 0x18 | ||
1437 | #define PCI_DATA_2 0x19 | ||
1438 | |||
1439 | /* | ||
1440 | * PCI data structure defines | ||
1441 | */ | ||
1442 | #define VPD_DATA_1 0x08 | ||
1443 | #define VPD_DATA_2 0x09 | ||
1444 | #define IMAGE_LEN_1 0x10 | ||
1445 | #define IMAGE_LEN_2 0x11 | ||
1446 | #define CODE_TYPE 0x14 | ||
1447 | #define INDICATOR 0x15 | ||
1448 | |||
1449 | /* | ||
1450 | * BEGIN_MANUAL_ENTRY(mac_drv_vpd_read) | ||
1451 | * mac_drv_vpd_read(smc,buf,size,image) | ||
1452 | * | ||
1453 | * function DOWNCALL (FDDIWARE) | ||
1454 | * reads the VPD data of the FPROM and writes it into the | ||
1455 | * buffer | ||
1456 | * | ||
1457 | * para buf points to the buffer for the VPD data | ||
1458 | * size size of the VPD data buffer | ||
1459 | * image boot image; code type of the boot image | ||
1460 | * image = 0 Intel x86, PC-AT compatible | ||
1461 | * 1 OPENBOOT standard for PCI | ||
1462 | * 2-FF reserved | ||
1463 | * | ||
1464 | * returns len number of VPD data bytes read form the FPROM | ||
1465 | * <0 number of read bytes | ||
1466 | * >0 error: data invalid | ||
1467 | * | ||
1468 | * END_MANUAL_ENTRY | ||
1469 | */ | ||
1470 | int mac_drv_vpd_read(struct s_smc *smc, char *buf, int size, char image) | ||
1471 | { | ||
1472 | u_short ibase ; | ||
1473 | u_short pci_base ; | ||
1474 | u_short vpd ; | ||
1475 | int len ; | ||
1476 | |||
1477 | len = 0 ; | ||
1478 | ibase = 0 ; | ||
1479 | /* | ||
1480 | * as long images defined | ||
1481 | */ | ||
1482 | while (get_rom_byte(smc,ibase+ROM_SIG_1) == 0x55 && | ||
1483 | (u_char) get_rom_byte(smc,ibase+ROM_SIG_2) == 0xaa) { | ||
1484 | /* | ||
1485 | * get the pointer to the PCI data structure | ||
1486 | */ | ||
1487 | pci_base = ibase + get_rom_byte(smc,ibase+PCI_DATA_1) + | ||
1488 | (get_rom_byte(smc,ibase+PCI_DATA_2) << 8) ; | ||
1489 | |||
1490 | if (image == get_rom_byte(smc,pci_base+CODE_TYPE)) { | ||
1491 | /* | ||
1492 | * we have the right image, read the VPD data | ||
1493 | */ | ||
1494 | vpd = ibase + get_rom_byte(smc,pci_base+VPD_DATA_1) + | ||
1495 | (get_rom_byte(smc,pci_base+VPD_DATA_2) << 8) ; | ||
1496 | if (vpd == ibase) { | ||
1497 | break ; /* no VPD data */ | ||
1498 | } | ||
1499 | for (len = 0; len < size; len++,buf++,vpd++) { | ||
1500 | *buf = get_rom_byte(smc,vpd) ; | ||
1501 | } | ||
1502 | break ; | ||
1503 | } | ||
1504 | else { | ||
1505 | /* | ||
1506 | * try the next image | ||
1507 | */ | ||
1508 | if (get_rom_byte(smc,pci_base+INDICATOR) & 0x80) { | ||
1509 | break ; /* this was the last image */ | ||
1510 | } | ||
1511 | ibase = ibase + get_rom_byte(smc,ibase+IMAGE_LEN_1) + | ||
1512 | (get_rom_byte(smc,ibase+IMAGE_LEN_2) << 8) ; | ||
1513 | } | ||
1514 | } | ||
1515 | |||
1516 | return(len) ; | ||
1517 | } | ||
1518 | |||
1519 | void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value) | ||
1520 | { | ||
1521 | smc->hw.pci_fix_value = fix_value ; | ||
1522 | } | ||
1523 | 1309 | ||
1524 | void mac_do_pci_fix(struct s_smc *smc) | 1310 | void mac_do_pci_fix(struct s_smc *smc) |
1525 | { | 1311 | { |
diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c index fd39b4b2ef7d..62b01328c496 100644 --- a/drivers/net/skfp/ess.c +++ b/drivers/net/skfp/ess.c | |||
@@ -102,7 +102,7 @@ void ess_timer_poll(struct s_smc *smc); | |||
102 | void ess_para_change(struct s_smc *smc); | 102 | void ess_para_change(struct s_smc *smc); |
103 | int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, | 103 | int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, |
104 | int fs); | 104 | int fs); |
105 | int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead); | 105 | static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead); |
106 | 106 | ||
107 | 107 | ||
108 | /* | 108 | /* |
@@ -375,7 +375,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, | |||
375 | * determines the synchronous bandwidth, set the TSYNC register and the | 375 | * determines the synchronous bandwidth, set the TSYNC register and the |
376 | * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG. | 376 | * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG. |
377 | */ | 377 | */ |
378 | int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead) | 378 | static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead) |
379 | { | 379 | { |
380 | /* | 380 | /* |
381 | * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG, | 381 | * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG, |
diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c index 76e78442fc24..a2ed47f1cc70 100644 --- a/drivers/net/skfp/fplustm.c +++ b/drivers/net/skfp/fplustm.c | |||
@@ -1117,30 +1117,6 @@ void mac_clear_multicast(struct s_smc *smc) | |||
1117 | /* | 1117 | /* |
1118 | BEGIN_MANUAL_ENTRY(if,func;others;2) | 1118 | BEGIN_MANUAL_ENTRY(if,func;others;2) |
1119 | 1119 | ||
1120 | int mac_set_func_addr(smc,f_addr) | ||
1121 | struct s_smc *smc ; | ||
1122 | u_long f_addr ; | ||
1123 | |||
1124 | Function DOWNCALL (SMT, fplustm.c) | ||
1125 | Set a Token-Ring functional address, the address will | ||
1126 | be activated after calling mac_update_multicast() | ||
1127 | |||
1128 | Para f_addr functional bits in non-canonical format | ||
1129 | |||
1130 | Returns 0: always success | ||
1131 | |||
1132 | END_MANUAL_ENTRY() | ||
1133 | */ | ||
1134 | int mac_set_func_addr(struct s_smc *smc, u_long f_addr) | ||
1135 | { | ||
1136 | smc->hw.fp.func_addr = f_addr ; | ||
1137 | return(0) ; | ||
1138 | } | ||
1139 | |||
1140 | |||
1141 | /* | ||
1142 | BEGIN_MANUAL_ENTRY(if,func;others;2) | ||
1143 | |||
1144 | int mac_add_multicast(smc,addr,can) | 1120 | int mac_add_multicast(smc,addr,can) |
1145 | struct s_smc *smc ; | 1121 | struct s_smc *smc ; |
1146 | struct fddi_addr *addr ; | 1122 | struct fddi_addr *addr ; |
@@ -1203,52 +1179,6 @@ int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) | |||
1203 | } | 1179 | } |
1204 | 1180 | ||
1205 | /* | 1181 | /* |
1206 | BEGIN_MANUAL_ENTRY(if,func;others;2) | ||
1207 | |||
1208 | void mac_del_multicast(smc,addr,can) | ||
1209 | struct s_smc *smc ; | ||
1210 | struct fddi_addr *addr ; | ||
1211 | int can ; | ||
1212 | |||
1213 | Function DOWNCALL (SMT, fplustm.c) | ||
1214 | Delete an entry from the multicast table | ||
1215 | |||
1216 | Para addr pointer to a multicast address | ||
1217 | can = 0: the multicast address has the physical format | ||
1218 | = 1: the multicast address has the canonical format | ||
1219 | | 0x80 permanent | ||
1220 | |||
1221 | END_MANUAL_ENTRY() | ||
1222 | */ | ||
1223 | void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) | ||
1224 | { | ||
1225 | SK_LOC_DECL(struct fddi_addr,own) ; | ||
1226 | struct s_fpmc *tb ; | ||
1227 | |||
1228 | if (!(tb = mac_get_mc_table(smc,addr,&own,1,can & ~0x80))) | ||
1229 | return ; | ||
1230 | /* | ||
1231 | * permanent addresses must be deleted with perm bit | ||
1232 | * and vice versa | ||
1233 | */ | ||
1234 | if (( tb->perm && (can & 0x80)) || | ||
1235 | (!tb->perm && !(can & 0x80))) { | ||
1236 | /* | ||
1237 | * delete it | ||
1238 | */ | ||
1239 | if (tb->n) { | ||
1240 | tb->n-- ; | ||
1241 | if (tb->perm) { | ||
1242 | smc->hw.fp.smt_slots_used-- ; | ||
1243 | } | ||
1244 | else { | ||
1245 | smc->hw.fp.os_slots_used-- ; | ||
1246 | } | ||
1247 | } | ||
1248 | } | ||
1249 | } | ||
1250 | |||
1251 | /* | ||
1252 | * mode | 1182 | * mode |
1253 | */ | 1183 | */ |
1254 | 1184 | ||
diff --git a/drivers/net/skfp/h/cmtdef.h b/drivers/net/skfp/h/cmtdef.h index 603982debc71..f2f771d8be76 100644 --- a/drivers/net/skfp/h/cmtdef.h +++ b/drivers/net/skfp/h/cmtdef.h | |||
@@ -507,7 +507,6 @@ void pcm_status_state(struct s_smc *smc, int np, int *type, int *state, | |||
507 | int *remote, int *mac); | 507 | int *remote, int *mac); |
508 | void plc_config_mux(struct s_smc *smc, int mux); | 508 | void plc_config_mux(struct s_smc *smc, int mux); |
509 | void sm_lem_evaluate(struct s_smc *smc); | 509 | void sm_lem_evaluate(struct s_smc *smc); |
510 | void smt_clear_una_dna(struct s_smc *smc); | ||
511 | void mac_update_counter(struct s_smc *smc); | 510 | void mac_update_counter(struct s_smc *smc); |
512 | void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off); | 511 | void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off); |
513 | void sm_ma_control(struct s_smc *smc, int mode); | 512 | void sm_ma_control(struct s_smc *smc, int mode); |
@@ -541,11 +540,9 @@ void smt_timer_poll(struct s_smc *smc); | |||
541 | u_long smt_get_time(void); | 540 | u_long smt_get_time(void); |
542 | u_long smt_get_tid(struct s_smc *smc); | 541 | u_long smt_get_tid(struct s_smc *smc); |
543 | void smt_timer_done(struct s_smc *smc); | 542 | void smt_timer_done(struct s_smc *smc); |
544 | void smt_set_defaults(struct s_smc *smc); | ||
545 | void smt_fixup_mib(struct s_smc *smc); | 543 | void smt_fixup_mib(struct s_smc *smc); |
546 | void smt_reset_defaults(struct s_smc *smc, int level); | 544 | void smt_reset_defaults(struct s_smc *smc, int level); |
547 | void smt_agent_task(struct s_smc *smc); | 545 | void smt_agent_task(struct s_smc *smc); |
548 | void smt_please_reconnect(struct s_smc *smc, int reconn_time); | ||
549 | int smt_check_para(struct s_smc *smc, struct smt_header *sm, | 546 | int smt_check_para(struct s_smc *smc, struct smt_header *sm, |
550 | const u_short list[]); | 547 | const u_short list[]); |
551 | void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr); | 548 | void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr); |
@@ -568,7 +565,6 @@ int pcm_get_s_port(struct s_smc *smc); | |||
568 | int pcm_rooted_station(struct s_smc *smc); | 565 | int pcm_rooted_station(struct s_smc *smc); |
569 | int cfm_get_mac_input(struct s_smc *smc); | 566 | int cfm_get_mac_input(struct s_smc *smc); |
570 | int cfm_get_mac_output(struct s_smc *smc); | 567 | int cfm_get_mac_output(struct s_smc *smc); |
571 | int port_to_mib(struct s_smc *smc, int p); | ||
572 | int cem_build_path(struct s_smc *smc, char *to, int path_index); | 568 | int cem_build_path(struct s_smc *smc, char *to, int path_index); |
573 | int sm_mac_get_tx_state(struct s_smc *smc); | 569 | int sm_mac_get_tx_state(struct s_smc *smc); |
574 | char *get_pcmstate(struct s_smc *smc, int np); | 570 | char *get_pcmstate(struct s_smc *smc, int np); |
@@ -580,8 +576,6 @@ void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local); | |||
580 | void smt_set_timestamp(struct s_smc *smc, u_char *p); | 576 | void smt_set_timestamp(struct s_smc *smc, u_char *p); |
581 | void mac_set_rx_mode(struct s_smc *smc, int mode); | 577 | void mac_set_rx_mode(struct s_smc *smc, int mode); |
582 | int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); | 578 | int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); |
583 | int mac_set_func_addr(struct s_smc *smc, u_long f_addr); | ||
584 | void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); | ||
585 | void mac_update_multicast(struct s_smc *smc); | 579 | void mac_update_multicast(struct s_smc *smc); |
586 | void mac_clear_multicast(struct s_smc *smc); | 580 | void mac_clear_multicast(struct s_smc *smc); |
587 | void set_formac_tsync(struct s_smc *smc, long sync_bw); | 581 | void set_formac_tsync(struct s_smc *smc, long sync_bw); |
@@ -599,7 +593,6 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd); | |||
599 | int smt_set_mac_opvalues(struct s_smc *smc); | 593 | int smt_set_mac_opvalues(struct s_smc *smc); |
600 | 594 | ||
601 | #ifdef TAG_MODE | 595 | #ifdef TAG_MODE |
602 | void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value); | ||
603 | void mac_do_pci_fix(struct s_smc *smc); | 596 | void mac_do_pci_fix(struct s_smc *smc); |
604 | void mac_drv_clear_tx_queue(struct s_smc *smc); | 597 | void mac_drv_clear_tx_queue(struct s_smc *smc); |
605 | void mac_drv_repair_descr(struct s_smc *smc); | 598 | void mac_drv_repair_descr(struct s_smc *smc); |
diff --git a/drivers/net/skfp/h/hwmtm.h b/drivers/net/skfp/h/hwmtm.h index 4e360af07d77..1a606d4bfe5e 100644 --- a/drivers/net/skfp/h/hwmtm.h +++ b/drivers/net/skfp/h/hwmtm.h | |||
@@ -262,31 +262,6 @@ struct os_debug { | |||
262 | (smc)->hw.fp.tx_q[queue].tx_curr_put | 262 | (smc)->hw.fp.tx_q[queue].tx_curr_put |
263 | 263 | ||
264 | /* | 264 | /* |
265 | * BEGIN_MANUAL_ENTRY(HWM_TX_CHECK) | ||
266 | * void HWM_TX_CHECK(smc,frame_status,low_water) | ||
267 | * | ||
268 | * function MACRO (hardware module, hwmtm.h) | ||
269 | * This macro is invoked by the OS-specific before it left it's | ||
270 | * driver_send function. This macro calls mac_drv_clear_txd | ||
271 | * if the free TxDs of the current transmit queue is equal or | ||
272 | * lower than the given low water mark. | ||
273 | * | ||
274 | * para frame_status status of the frame, see design description | ||
275 | * low_water low water mark of free TxD's | ||
276 | * | ||
277 | * END_MANUAL_ENTRY | ||
278 | */ | ||
279 | #ifndef HWM_NO_FLOW_CTL | ||
280 | #define HWM_TX_CHECK(smc,frame_status,low_water) {\ | ||
281 | if ((low_water)>=(smc)->hw.fp.tx_q[(frame_status)&QUEUE_A0].tx_free) {\ | ||
282 | mac_drv_clear_txd(smc) ;\ | ||
283 | }\ | ||
284 | } | ||
285 | #else | ||
286 | #define HWM_TX_CHECK(smc,frame_status,low_water) mac_drv_clear_txd(smc) | ||
287 | #endif | ||
288 | |||
289 | /* | ||
290 | * BEGIN_MANUAL_ENTRY(HWM_GET_RX_FRAG_LEN) | 265 | * BEGIN_MANUAL_ENTRY(HWM_GET_RX_FRAG_LEN) |
291 | * int HWM_GET_RX_FRAG_LEN(rxd) | 266 | * int HWM_GET_RX_FRAG_LEN(rxd) |
292 | * | 267 | * |
diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c index 18d429021edb..438f424e6361 100644 --- a/drivers/net/skfp/hwmtm.c +++ b/drivers/net/skfp/hwmtm.c | |||
@@ -86,6 +86,7 @@ static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue); | |||
86 | static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue); | 86 | static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue); |
87 | static SMbuf* get_llc_rx(struct s_smc *smc); | 87 | static SMbuf* get_llc_rx(struct s_smc *smc); |
88 | static SMbuf* get_txd_mb(struct s_smc *smc); | 88 | static SMbuf* get_txd_mb(struct s_smc *smc); |
89 | static void mac_drv_clear_txd(struct s_smc *smc); | ||
89 | 90 | ||
90 | /* | 91 | /* |
91 | ------------------------------------------------------------- | 92 | ------------------------------------------------------------- |
@@ -146,7 +147,6 @@ extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, | |||
146 | */ | 147 | */ |
147 | void process_receive(struct s_smc *smc); | 148 | void process_receive(struct s_smc *smc); |
148 | void fddi_isr(struct s_smc *smc); | 149 | void fddi_isr(struct s_smc *smc); |
149 | void mac_drv_clear_txd(struct s_smc *smc); | ||
150 | void smt_free_mbuf(struct s_smc *smc, SMbuf *mb); | 150 | void smt_free_mbuf(struct s_smc *smc, SMbuf *mb); |
151 | void init_driver_fplus(struct s_smc *smc); | 151 | void init_driver_fplus(struct s_smc *smc); |
152 | void mac_drv_rx_mode(struct s_smc *smc, int mode); | 152 | void mac_drv_rx_mode(struct s_smc *smc, int mode); |
@@ -158,7 +158,6 @@ void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, | |||
158 | void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, | 158 | void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, |
159 | int frame_status); | 159 | int frame_status); |
160 | 160 | ||
161 | int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len); | ||
162 | int mac_drv_init(struct s_smc *smc); | 161 | int mac_drv_init(struct s_smc *smc); |
163 | int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, | 162 | int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, |
164 | int frame_status); | 163 | int frame_status); |
@@ -1448,35 +1447,6 @@ void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, | |||
1448 | NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ; | 1447 | NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ; |
1449 | } | 1448 | } |
1450 | 1449 | ||
1451 | #ifndef NDIS_OS2 | ||
1452 | /* | ||
1453 | * BEGIN_MANUAL_ENTRY(mac_drv_rx_frag) | ||
1454 | * int mac_drv_rx_frag(smc,virt,len) | ||
1455 | * | ||
1456 | * function DOWNCALL (hwmtm.c) | ||
1457 | * mac_drv_rx_frag fills the fragment with a part of the frame. | ||
1458 | * | ||
1459 | * para virt the virtual address of the fragment | ||
1460 | * len the length in bytes of the fragment | ||
1461 | * | ||
1462 | * return 0: success code, no errors possible | ||
1463 | * | ||
1464 | * END_MANUAL_ENTRY | ||
1465 | */ | ||
1466 | int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len) | ||
1467 | { | ||
1468 | NDD_TRACE("RHSB",virt,len,smc->os.hwm.r.mb_pos) ; | ||
1469 | |||
1470 | DB_RX("receive from queue: len/virt: = %d/%x",len,virt,4) ; | ||
1471 | memcpy((char far *)virt,smc->os.hwm.r.mb_pos,len) ; | ||
1472 | smc->os.hwm.r.mb_pos += len ; | ||
1473 | |||
1474 | NDD_TRACE("RHSE",smc->os.hwm.r.mb_pos,0,0) ; | ||
1475 | return(0) ; | ||
1476 | } | ||
1477 | #endif | ||
1478 | |||
1479 | |||
1480 | /* | 1450 | /* |
1481 | * BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue) | 1451 | * BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue) |
1482 | * | 1452 | * |
@@ -1978,7 +1948,7 @@ void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc) | |||
1978 | * | 1948 | * |
1979 | * END_MANUAL_ENTRY | 1949 | * END_MANUAL_ENTRY |
1980 | */ | 1950 | */ |
1981 | void mac_drv_clear_txd(struct s_smc *smc) | 1951 | static void mac_drv_clear_txd(struct s_smc *smc) |
1982 | { | 1952 | { |
1983 | struct s_smt_tx_queue *queue ; | 1953 | struct s_smt_tx_queue *queue ; |
1984 | struct s_smt_fp_txd volatile *t1 ; | 1954 | struct s_smt_fp_txd volatile *t1 ; |
diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c index 571f055c096b..cd0aa4c151b0 100644 --- a/drivers/net/skfp/pcmplc.c +++ b/drivers/net/skfp/pcmplc.c | |||
@@ -1861,13 +1861,6 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd) | |||
1861 | #endif | 1861 | #endif |
1862 | } | 1862 | } |
1863 | 1863 | ||
1864 | void pcm_set_lct_short(struct s_smc *smc, int n) | ||
1865 | { | ||
1866 | if (n <= 0 || n > 1000) | ||
1867 | return ; | ||
1868 | smc->s.lct_short = n ; | ||
1869 | } | ||
1870 | |||
1871 | #ifdef DEBUG | 1864 | #ifdef DEBUG |
1872 | /* | 1865 | /* |
1873 | * fill state struct | 1866 | * fill state struct |
diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c index f2b446d8b0bf..efc639c013fd 100644 --- a/drivers/net/skfp/pmf.c +++ b/drivers/net/skfp/pmf.c | |||
@@ -36,12 +36,13 @@ static int smt_authorize(struct s_smc *smc, struct smt_header *sm); | |||
36 | static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm); | 36 | static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm); |
37 | static const struct s_p_tab* smt_get_ptab(u_short para); | 37 | static const struct s_p_tab* smt_get_ptab(u_short para); |
38 | static int smt_mib_phys(struct s_smc *smc); | 38 | static int smt_mib_phys(struct s_smc *smc); |
39 | int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, | 39 | static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, |
40 | int set); | 40 | int local, int set); |
41 | void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, | 41 | void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, |
42 | int index, int local); | 42 | int index, int local); |
43 | static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req, | 43 | static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req, |
44 | int set, int local); | 44 | int set, int local); |
45 | static int port_to_mib(struct s_smc *smc, int p); | ||
45 | 46 | ||
46 | #define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e)) | 47 | #define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e)) |
47 | #define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e)) | 48 | #define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e)) |
@@ -1078,8 +1079,8 @@ wrong_error: | |||
1078 | /* | 1079 | /* |
1079 | * set parameter | 1080 | * set parameter |
1080 | */ | 1081 | */ |
1081 | int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, | 1082 | static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, |
1082 | int set) | 1083 | int local, int set) |
1083 | { | 1084 | { |
1084 | #define IFSET(x) if (set) (x) | 1085 | #define IFSET(x) if (set) (x) |
1085 | 1086 | ||
@@ -1549,7 +1550,7 @@ static int smt_mib_phys(struct s_smc *smc) | |||
1549 | #endif | 1550 | #endif |
1550 | } | 1551 | } |
1551 | 1552 | ||
1552 | int port_to_mib(struct s_smc *smc, int p) | 1553 | static int port_to_mib(struct s_smc *smc, int p) |
1553 | { | 1554 | { |
1554 | #ifdef CONCENTRATOR | 1555 | #ifdef CONCENTRATOR |
1555 | SK_UNUSED(smc) ; | 1556 | SK_UNUSED(smc) ; |
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index c88aad6edd74..4b5ed2c63177 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c | |||
@@ -149,7 +149,6 @@ extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys, | |||
149 | extern void mac_drv_rx_mode(struct s_smc *smc, int mode); | 149 | extern void mac_drv_rx_mode(struct s_smc *smc, int mode); |
150 | extern void mac_drv_clear_rx_queue(struct s_smc *smc); | 150 | extern void mac_drv_clear_rx_queue(struct s_smc *smc); |
151 | extern void enable_tx_irq(struct s_smc *smc, u_short queue); | 151 | extern void enable_tx_irq(struct s_smc *smc, u_short queue); |
152 | extern void mac_drv_clear_txd(struct s_smc *smc); | ||
153 | 152 | ||
154 | static struct pci_device_id skfddi_pci_tbl[] = { | 153 | static struct pci_device_id skfddi_pci_tbl[] = { |
155 | { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, }, | 154 | { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, }, |
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c index c3a0d2f10b2b..f17c05cbe44b 100644 --- a/drivers/net/skfp/smt.c +++ b/drivers/net/skfp/smt.c | |||
@@ -110,7 +110,7 @@ static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount | |||
110 | static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, | 110 | static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, |
111 | int len); | 111 | int len); |
112 | 112 | ||
113 | void smt_clear_una_dna(struct s_smc *smc); | 113 | static void smt_clear_una_dna(struct s_smc *smc); |
114 | static void smt_clear_old_una_dna(struct s_smc *smc); | 114 | static void smt_clear_old_una_dna(struct s_smc *smc); |
115 | #ifdef CONCENTRATOR | 115 | #ifdef CONCENTRATOR |
116 | static int entity_to_index(void); | 116 | static int entity_to_index(void); |
@@ -118,7 +118,7 @@ static int entity_to_index(void); | |||
118 | static void update_dac(struct s_smc *smc, int report); | 118 | static void update_dac(struct s_smc *smc, int report); |
119 | static int div_ratio(u_long upper, u_long lower); | 119 | static int div_ratio(u_long upper, u_long lower); |
120 | #ifdef USE_CAN_ADDR | 120 | #ifdef USE_CAN_ADDR |
121 | void hwm_conv_can(struct s_smc *smc, char *data, int len); | 121 | static void hwm_conv_can(struct s_smc *smc, char *data, int len); |
122 | #else | 122 | #else |
123 | #define hwm_conv_can(smc,data,len) | 123 | #define hwm_conv_can(smc,data,len) |
124 | #endif | 124 | #endif |
@@ -216,24 +216,6 @@ void smt_agent_task(struct s_smc *smc) | |||
216 | DB_SMT("SMT agent task\n",0,0) ; | 216 | DB_SMT("SMT agent task\n",0,0) ; |
217 | } | 217 | } |
218 | 218 | ||
219 | void smt_please_reconnect(struct s_smc *smc, int reconn_time) | ||
220 | /* struct s_smc *smc; Pointer to SMT context */ | ||
221 | /* int reconn_time; Wait for reconnect time in seconds */ | ||
222 | { | ||
223 | /* | ||
224 | * The please reconnect variable is used as a timer. | ||
225 | * It is decremented each time smt_event is called. | ||
226 | * This happens every second or when smt_force_irq is called. | ||
227 | * Note: smt_force_irq () is called on some packet receives and | ||
228 | * when a multicast address is changed. Since nothing | ||
229 | * is received during the disconnect and the multicast | ||
230 | * address changes can be viewed as not very often and | ||
231 | * the timer runs out close to its given value | ||
232 | * (reconn_time). | ||
233 | */ | ||
234 | smc->sm.please_reconnect = reconn_time ; | ||
235 | } | ||
236 | |||
237 | #ifndef SMT_REAL_TOKEN_CT | 219 | #ifndef SMT_REAL_TOKEN_CT |
238 | void smt_emulate_token_ct(struct s_smc *smc, int mac_index) | 220 | void smt_emulate_token_ct(struct s_smc *smc, int mac_index) |
239 | { | 221 | { |
@@ -1574,7 +1556,7 @@ static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long see | |||
1574 | * clear DNA and UNA | 1556 | * clear DNA and UNA |
1575 | * called from CFM if configuration changes | 1557 | * called from CFM if configuration changes |
1576 | */ | 1558 | */ |
1577 | void smt_clear_una_dna(struct s_smc *smc) | 1559 | static void smt_clear_una_dna(struct s_smc *smc) |
1578 | { | 1560 | { |
1579 | smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; | 1561 | smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; |
1580 | smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; | 1562 | smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; |
@@ -2058,30 +2040,10 @@ int smt_action(struct s_smc *smc, int class, int code, int index) | |||
2058 | } | 2040 | } |
2059 | 2041 | ||
2060 | /* | 2042 | /* |
2061 | * change tneg | ||
2062 | * set T_Req in MIB (Path Attribute) | ||
2063 | * calculate new values for MAC | ||
2064 | * if change required | ||
2065 | * disconnect | ||
2066 | * set reconnect | ||
2067 | * end | ||
2068 | */ | ||
2069 | void smt_change_t_neg(struct s_smc *smc, u_long tneg) | ||
2070 | { | ||
2071 | smc->mib.a[PATH0].fddiPATHMaxT_Req = tneg ; | ||
2072 | |||
2073 | if (smt_set_mac_opvalues(smc)) { | ||
2074 | RS_SET(smc,RS_EVENT) ; | ||
2075 | smc->sm.please_reconnect = 1 ; | ||
2076 | queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; | ||
2077 | } | ||
2078 | } | ||
2079 | |||
2080 | /* | ||
2081 | * canonical conversion of <len> bytes beginning form *data | 2043 | * canonical conversion of <len> bytes beginning form *data |
2082 | */ | 2044 | */ |
2083 | #ifdef USE_CAN_ADDR | 2045 | #ifdef USE_CAN_ADDR |
2084 | void hwm_conv_can(struct s_smc *smc, char *data, int len) | 2046 | static void hwm_conv_can(struct s_smc *smc, char *data, int len) |
2085 | { | 2047 | { |
2086 | int i ; | 2048 | int i ; |
2087 | 2049 | ||
diff --git a/drivers/net/skfp/smtdef.c b/drivers/net/skfp/smtdef.c index 5a0c8db816d8..4e07ff7073f1 100644 --- a/drivers/net/skfp/smtdef.c +++ b/drivers/net/skfp/smtdef.c | |||
@@ -76,11 +76,6 @@ void smt_reset_defaults(struct s_smc *smc, int level); | |||
76 | static void smt_init_mib(struct s_smc *smc, int level); | 76 | static void smt_init_mib(struct s_smc *smc, int level); |
77 | static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper); | 77 | static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper); |
78 | 78 | ||
79 | void smt_set_defaults(struct s_smc *smc) | ||
80 | { | ||
81 | smt_reset_defaults(smc,0) ; | ||
82 | } | ||
83 | |||
84 | #define MS2BCLK(x) ((x)*12500L) | 79 | #define MS2BCLK(x) ((x)*12500L) |
85 | #define US2BCLK(x) ((x)*1250L) | 80 | #define US2BCLK(x) ((x)*1250L) |
86 | 81 | ||
diff --git a/drivers/net/skfp/smtparse.c b/drivers/net/skfp/smtparse.c deleted file mode 100644 index d5779e414dbe..000000000000 --- a/drivers/net/skfp/smtparse.c +++ /dev/null | |||
@@ -1,467 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * (C)Copyright 1998,1999 SysKonnect, | ||
4 | * a business unit of Schneider & Koch & Co. Datensysteme GmbH. | ||
5 | * | ||
6 | * See the file "skfddi.c" for further information. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * The information in this file is provided "AS IS" without warranty. | ||
14 | * | ||
15 | ******************************************************************************/ | ||
16 | |||
17 | |||
18 | /* | ||
19 | parser for SMT parameters | ||
20 | */ | ||
21 | |||
22 | #include "h/types.h" | ||
23 | #include "h/fddi.h" | ||
24 | #include "h/smc.h" | ||
25 | #include "h/smt_p.h" | ||
26 | |||
27 | #define KERNEL | ||
28 | #include "h/smtstate.h" | ||
29 | |||
30 | #ifndef lint | ||
31 | static const char ID_sccs[] = "@(#)smtparse.c 1.12 98/10/06 (C) SK " ; | ||
32 | #endif | ||
33 | |||
34 | #ifdef sun | ||
35 | #define _far | ||
36 | #endif | ||
37 | |||
38 | /* | ||
39 | * convert to BCLK units | ||
40 | */ | ||
41 | #define MS2BCLK(x) ((x)*12500L) | ||
42 | #define US2BCLK(x) ((x/10)*125L) | ||
43 | |||
44 | /* | ||
45 | * parameter table | ||
46 | */ | ||
47 | static struct s_ptab { | ||
48 | char *pt_name ; | ||
49 | u_short pt_num ; | ||
50 | u_short pt_type ; | ||
51 | u_long pt_min ; | ||
52 | u_long pt_max ; | ||
53 | } ptab[] = { | ||
54 | { "PMFPASSWD",0, 0 } , | ||
55 | { "USERDATA",1, 0 } , | ||
56 | { "LERCUTOFFA",2, 1, 4, 15 } , | ||
57 | { "LERCUTOFFB",3, 1, 4, 15 } , | ||
58 | { "LERALARMA",4, 1, 4, 15 } , | ||
59 | { "LERALARMB",5, 1, 4, 15 } , | ||
60 | { "TMAX",6, 1, 5, 165 } , | ||
61 | { "TMIN",7, 1, 5, 165 } , | ||
62 | { "TREQ",8, 1, 5, 165 } , | ||
63 | { "TVX",9, 1, 2500, 10000 } , | ||
64 | #ifdef ESS | ||
65 | { "SBAPAYLOAD",10, 1, 0, 1562 } , | ||
66 | { "SBAOVERHEAD",11, 1, 50, 5000 } , | ||
67 | { "MAXTNEG",12, 1, 5, 165 } , | ||
68 | { "MINSEGMENTSIZE",13, 1, 0, 4478 } , | ||
69 | { "SBACATEGORY",14, 1, 0, 0xffff } , | ||
70 | { "SYNCHTXMODE",15, 0 } , | ||
71 | #endif | ||
72 | #ifdef SBA | ||
73 | { "SBACOMMAND",16, 0 } , | ||
74 | { "SBAAVAILABLE",17, 1, 0, 100 } , | ||
75 | #endif | ||
76 | { NULL } | ||
77 | } ; | ||
78 | |||
79 | /* Define maximum string size for values and keybuffer */ | ||
80 | #define MAX_VAL 40 | ||
81 | |||
82 | /* | ||
83 | * local function declarations | ||
84 | */ | ||
85 | static u_long parse_num(int type, char _far *value, char *v, u_long mn, | ||
86 | u_long mx, int scale); | ||
87 | static int parse_word(char *buf, char _far *text); | ||
88 | |||
89 | #ifdef SIM | ||
90 | #define DB_MAIN(a,b,c) printf(a,b,c) | ||
91 | #else | ||
92 | #define DB_MAIN(a,b,c) | ||
93 | #endif | ||
94 | |||
95 | /* | ||
96 | * BEGIN_MANUAL_ENTRY() | ||
97 | * | ||
98 | * int smt_parse_arg(struct s_smc *,char _far *keyword,int type, | ||
99 | char _far *value) | ||
100 | * | ||
101 | * parse SMT parameter | ||
102 | * *keyword | ||
103 | * pointer to keyword, must be \0, \n or \r terminated | ||
104 | * *value pointer to value, either char * or u_long * | ||
105 | * if char * | ||
106 | * pointer to value, must be \0, \n or \r terminated | ||
107 | * if u_long * | ||
108 | * contains binary value | ||
109 | * | ||
110 | * type 0: integer | ||
111 | * 1: string | ||
112 | * return | ||
113 | * 0 parameter parsed ok | ||
114 | * != 0 error | ||
115 | * NOTE: | ||
116 | * function can be called with DS != SS | ||
117 | * | ||
118 | * | ||
119 | * END_MANUAL_ENTRY() | ||
120 | */ | ||
121 | int smt_parse_arg(struct s_smc *smc, char _far *keyword, int type, | ||
122 | char _far *value) | ||
123 | { | ||
124 | char keybuf[MAX_VAL+1]; | ||
125 | char valbuf[MAX_VAL+1]; | ||
126 | char c ; | ||
127 | char *p ; | ||
128 | char *v ; | ||
129 | char *d ; | ||
130 | u_long val = 0 ; | ||
131 | struct s_ptab *pt ; | ||
132 | int st ; | ||
133 | int i ; | ||
134 | |||
135 | /* | ||
136 | * parse keyword | ||
137 | */ | ||
138 | if ((st = parse_word(keybuf,keyword))) | ||
139 | return(st) ; | ||
140 | /* | ||
141 | * parse value if given as string | ||
142 | */ | ||
143 | if (type == 1) { | ||
144 | if ((st = parse_word(valbuf,value))) | ||
145 | return(st) ; | ||
146 | } | ||
147 | /* | ||
148 | * search in table | ||
149 | */ | ||
150 | st = 0 ; | ||
151 | for (pt = ptab ; (v = pt->pt_name) ; pt++) { | ||
152 | for (p = keybuf ; (c = *p) ; p++,v++) { | ||
153 | if (c != *v) | ||
154 | break ; | ||
155 | } | ||
156 | if (!c && !*v) | ||
157 | break ; | ||
158 | } | ||
159 | if (!v) | ||
160 | return(-1) ; | ||
161 | #if 0 | ||
162 | printf("=>%s<==>%s<=\n",pt->pt_name,valbuf) ; | ||
163 | #endif | ||
164 | /* | ||
165 | * set value in MIB | ||
166 | */ | ||
167 | if (pt->pt_type) | ||
168 | val = parse_num(type,value,valbuf,pt->pt_min,pt->pt_max,1) ; | ||
169 | switch (pt->pt_num) { | ||
170 | case 0 : | ||
171 | v = valbuf ; | ||
172 | d = (char *) smc->mib.fddiPRPMFPasswd ; | ||
173 | for (i = 0 ; i < (signed)sizeof(smc->mib.fddiPRPMFPasswd) ; i++) | ||
174 | *d++ = *v++ ; | ||
175 | DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiPRPMFPasswd) ; | ||
176 | break ; | ||
177 | case 1 : | ||
178 | v = valbuf ; | ||
179 | d = (char *) smc->mib.fddiSMTUserData ; | ||
180 | for (i = 0 ; i < (signed)sizeof(smc->mib.fddiSMTUserData) ; i++) | ||
181 | *d++ = *v++ ; | ||
182 | DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiSMTUserData) ; | ||
183 | break ; | ||
184 | case 2 : | ||
185 | smc->mib.p[PA].fddiPORTLer_Cutoff = (u_char) val ; | ||
186 | DB_MAIN("SET %s = %d\n", | ||
187 | pt->pt_name,smc->mib.p[PA].fddiPORTLer_Cutoff) ; | ||
188 | break ; | ||
189 | case 3 : | ||
190 | smc->mib.p[PB].fddiPORTLer_Cutoff = (u_char) val ; | ||
191 | DB_MAIN("SET %s = %d\n", | ||
192 | pt->pt_name,smc->mib.p[PB].fddiPORTLer_Cutoff) ; | ||
193 | break ; | ||
194 | case 4 : | ||
195 | smc->mib.p[PA].fddiPORTLer_Alarm = (u_char) val ; | ||
196 | DB_MAIN("SET %s = %d\n", | ||
197 | pt->pt_name,smc->mib.p[PA].fddiPORTLer_Alarm) ; | ||
198 | break ; | ||
199 | case 5 : | ||
200 | smc->mib.p[PB].fddiPORTLer_Alarm = (u_char) val ; | ||
201 | DB_MAIN("SET %s = %d\n", | ||
202 | pt->pt_name,smc->mib.p[PB].fddiPORTLer_Alarm) ; | ||
203 | break ; | ||
204 | case 6 : /* TMAX */ | ||
205 | DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; | ||
206 | smc->mib.a[PATH0].fddiPATHT_MaxLowerBound = | ||
207 | (u_long) -MS2BCLK((long)val) ; | ||
208 | break ; | ||
209 | case 7 : /* TMIN */ | ||
210 | DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; | ||
211 | smc->mib.m[MAC0].fddiMACT_Min = | ||
212 | (u_long) -MS2BCLK((long)val) ; | ||
213 | break ; | ||
214 | case 8 : /* TREQ */ | ||
215 | DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; | ||
216 | smc->mib.a[PATH0].fddiPATHMaxT_Req = | ||
217 | (u_long) -MS2BCLK((long)val) ; | ||
218 | break ; | ||
219 | case 9 : /* TVX */ | ||
220 | DB_MAIN("SET %s = %d \n",pt->pt_name,val) ; | ||
221 | smc->mib.a[PATH0].fddiPATHTVXLowerBound = | ||
222 | (u_long) -US2BCLK((long)val) ; | ||
223 | break ; | ||
224 | #ifdef ESS | ||
225 | case 10 : /* SBAPAYLOAD */ | ||
226 | DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; | ||
227 | if (smc->mib.fddiESSPayload != val) { | ||
228 | smc->ess.raf_act_timer_poll = TRUE ; | ||
229 | smc->mib.fddiESSPayload = val ; | ||
230 | } | ||
231 | break ; | ||
232 | case 11 : /* SBAOVERHEAD */ | ||
233 | DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; | ||
234 | smc->mib.fddiESSOverhead = val ; | ||
235 | break ; | ||
236 | case 12 : /* MAXTNEG */ | ||
237 | DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; | ||
238 | smc->mib.fddiESSMaxTNeg = (u_long) -MS2BCLK((long)val) ; | ||
239 | break ; | ||
240 | case 13 : /* MINSEGMENTSIZE */ | ||
241 | DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; | ||
242 | smc->mib.fddiESSMinSegmentSize = val ; | ||
243 | break ; | ||
244 | case 14 : /* SBACATEGORY */ | ||
245 | DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; | ||
246 | smc->mib.fddiESSCategory = | ||
247 | (smc->mib.fddiESSCategory & 0xffff) | | ||
248 | ((u_long)(val << 16)) ; | ||
249 | break ; | ||
250 | case 15 : /* SYNCHTXMODE */ | ||
251 | /* do not use memcmp(valbuf,"ALL",3) because DS != SS */ | ||
252 | if (valbuf[0] == 'A' && valbuf[1] == 'L' && valbuf[2] == 'L') { | ||
253 | smc->mib.fddiESSSynchTxMode = TRUE ; | ||
254 | DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; | ||
255 | } | ||
256 | /* if (!memcmp(valbuf,"SPLIT",5)) { */ | ||
257 | if (valbuf[0] == 'S' && valbuf[1] == 'P' && valbuf[2] == 'L' && | ||
258 | valbuf[3] == 'I' && valbuf[4] == 'T') { | ||
259 | DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; | ||
260 | smc->mib.fddiESSSynchTxMode = FALSE ; | ||
261 | } | ||
262 | break ; | ||
263 | #endif | ||
264 | #ifdef SBA | ||
265 | case 16 : /* SBACOMMAND */ | ||
266 | /* if (!memcmp(valbuf,"START",5)) { */ | ||
267 | if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'A' && | ||
268 | valbuf[3] == 'R' && valbuf[4] == 'T') { | ||
269 | DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; | ||
270 | smc->mib.fddiSBACommand = SB_START ; | ||
271 | } | ||
272 | /* if (!memcmp(valbuf,"STOP",4)) { */ | ||
273 | if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'O' && | ||
274 | valbuf[3] == 'P') { | ||
275 | DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; | ||
276 | smc->mib.fddiSBACommand = SB_STOP ; | ||
277 | } | ||
278 | break ; | ||
279 | case 17 : /* SBAAVAILABLE */ | ||
280 | DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; | ||
281 | smc->mib.fddiSBAAvailable = (u_char) val ; | ||
282 | break ; | ||
283 | #endif | ||
284 | } | ||
285 | return(0) ; | ||
286 | } | ||
287 | |||
288 | static int parse_word(char *buf, char _far *text) | ||
289 | { | ||
290 | char c ; | ||
291 | char *p ; | ||
292 | int p_len ; | ||
293 | int quote ; | ||
294 | int i ; | ||
295 | int ok ; | ||
296 | |||
297 | /* | ||
298 | * skip leading white space | ||
299 | */ | ||
300 | p = buf ; | ||
301 | for (i = 0 ; i < MAX_VAL ; i++) | ||
302 | *p++ = 0 ; | ||
303 | p = buf ; | ||
304 | p_len = 0 ; | ||
305 | ok = 0 ; | ||
306 | while ( (c = *text++) && (c != '\n') && (c != '\r')) { | ||
307 | if ((c != ' ') && (c != '\t')) { | ||
308 | ok = 1 ; | ||
309 | break ; | ||
310 | } | ||
311 | } | ||
312 | if (!ok) | ||
313 | return(-1) ; | ||
314 | if (c == '"') { | ||
315 | quote = 1 ; | ||
316 | } | ||
317 | else { | ||
318 | quote = 0 ; | ||
319 | text-- ; | ||
320 | } | ||
321 | /* | ||
322 | * parse valbuf | ||
323 | */ | ||
324 | ok = 0 ; | ||
325 | while (!ok && p_len < MAX_VAL-1 && (c = *text++) && (c != '\n') | ||
326 | && (c != '\r')) { | ||
327 | switch (quote) { | ||
328 | case 0 : | ||
329 | if ((c == ' ') || (c == '\t') || (c == '=')) { | ||
330 | ok = 1 ; | ||
331 | break ; | ||
332 | } | ||
333 | *p++ = c ; | ||
334 | p_len++ ; | ||
335 | break ; | ||
336 | case 2 : | ||
337 | *p++ = c ; | ||
338 | p_len++ ; | ||
339 | quote = 1 ; | ||
340 | break ; | ||
341 | case 1 : | ||
342 | switch (c) { | ||
343 | case '"' : | ||
344 | ok = 1 ; | ||
345 | break ; | ||
346 | case '\\' : | ||
347 | quote = 2 ; | ||
348 | break ; | ||
349 | default : | ||
350 | *p++ = c ; | ||
351 | p_len++ ; | ||
352 | } | ||
353 | } | ||
354 | } | ||
355 | *p++ = 0 ; | ||
356 | for (p = buf ; (c = *p) ; p++) { | ||
357 | if (c >= 'a' && c <= 'z') | ||
358 | *p = c + 'A' - 'a' ; | ||
359 | } | ||
360 | return(0) ; | ||
361 | } | ||
362 | |||
363 | static u_long parse_num(int type, char _far *value, char *v, u_long mn, | ||
364 | u_long mx, int scale) | ||
365 | { | ||
366 | u_long x = 0 ; | ||
367 | char c ; | ||
368 | |||
369 | if (type == 0) { /* integer */ | ||
370 | u_long _far *l ; | ||
371 | u_long u1 ; | ||
372 | |||
373 | l = (u_long _far *) value ; | ||
374 | u1 = *l ; | ||
375 | /* | ||
376 | * if the value is negative take the lower limit | ||
377 | */ | ||
378 | if ((long)u1 < 0) { | ||
379 | if (- ((long)u1) > (long) mx) { | ||
380 | u1 = 0 ; | ||
381 | } | ||
382 | else { | ||
383 | u1 = (u_long) - ((long)u1) ; | ||
384 | } | ||
385 | } | ||
386 | x = u1 ; | ||
387 | } | ||
388 | else { /* string */ | ||
389 | int sign = 0 ; | ||
390 | |||
391 | if (*v == '-') { | ||
392 | sign = 1 ; | ||
393 | } | ||
394 | while ((c = *v++) && (c >= '0') && (c <= '9')) { | ||
395 | x = x * 10 + c - '0' ; | ||
396 | } | ||
397 | if (scale == 10) { | ||
398 | x *= 10 ; | ||
399 | if (c == '.') { | ||
400 | if ((c = *v++) && (c >= '0') && (c <= '9')) { | ||
401 | x += c - '0' ; | ||
402 | } | ||
403 | } | ||
404 | } | ||
405 | if (sign) | ||
406 | x = (u_long) - ((long)x) ; | ||
407 | } | ||
408 | /* | ||
409 | * if the value is negative | ||
410 | * and the absolute value is outside the limits | ||
411 | * take the lower limit | ||
412 | * else | ||
413 | * take the absoute value | ||
414 | */ | ||
415 | if ((long)x < 0) { | ||
416 | if (- ((long)x) > (long) mx) { | ||
417 | x = 0 ; | ||
418 | } | ||
419 | else { | ||
420 | x = (u_long) - ((long)x) ; | ||
421 | } | ||
422 | } | ||
423 | if (x < mn) | ||
424 | return(mn) ; | ||
425 | else if (x > mx) | ||
426 | return(mx) ; | ||
427 | return(x) ; | ||
428 | } | ||
429 | |||
430 | #if 0 | ||
431 | struct s_smc SMC ; | ||
432 | main() | ||
433 | { | ||
434 | char *p ; | ||
435 | char *v ; | ||
436 | char buf[100] ; | ||
437 | int toggle = 0 ; | ||
438 | |||
439 | while (gets(buf)) { | ||
440 | p = buf ; | ||
441 | while (*p && ((*p == ' ') || (*p == '\t'))) | ||
442 | p++ ; | ||
443 | |||
444 | while (*p && ((*p != ' ') && (*p != '\t'))) | ||
445 | p++ ; | ||
446 | |||
447 | v = p ; | ||
448 | while (*v && ((*v == ' ') || (*v == '\t'))) | ||
449 | v++ ; | ||
450 | if ((*v >= '0') && (*v <= '9')) { | ||
451 | toggle = !toggle ; | ||
452 | if (toggle) { | ||
453 | u_long l ; | ||
454 | l = atol(v) ; | ||
455 | smt_parse_arg(&SMC,buf,0,(char _far *)&l) ; | ||
456 | } | ||
457 | else | ||
458 | smt_parse_arg(&SMC,buf,1,(char _far *)p) ; | ||
459 | } | ||
460 | else { | ||
461 | smt_parse_arg(&SMC,buf,1,(char _far *)p) ; | ||
462 | } | ||
463 | } | ||
464 | exit(0) ; | ||
465 | } | ||
466 | #endif | ||
467 | |||
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index fd80048f7f7a..cfb9d3cdb04a 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c | |||
@@ -315,15 +315,25 @@ static void smc_reset(struct net_device *dev) | |||
315 | struct smc_local *lp = netdev_priv(dev); | 315 | struct smc_local *lp = netdev_priv(dev); |
316 | void __iomem *ioaddr = lp->base; | 316 | void __iomem *ioaddr = lp->base; |
317 | unsigned int ctl, cfg; | 317 | unsigned int ctl, cfg; |
318 | struct sk_buff *pending_skb; | ||
318 | 319 | ||
319 | DBG(2, "%s: %s\n", dev->name, __FUNCTION__); | 320 | DBG(2, "%s: %s\n", dev->name, __FUNCTION__); |
320 | 321 | ||
321 | /* Disable all interrupts */ | 322 | /* Disable all interrupts, block TX tasklet */ |
322 | spin_lock(&lp->lock); | 323 | spin_lock(&lp->lock); |
323 | SMC_SELECT_BANK(2); | 324 | SMC_SELECT_BANK(2); |
324 | SMC_SET_INT_MASK(0); | 325 | SMC_SET_INT_MASK(0); |
326 | pending_skb = lp->pending_tx_skb; | ||
327 | lp->pending_tx_skb = NULL; | ||
325 | spin_unlock(&lp->lock); | 328 | spin_unlock(&lp->lock); |
326 | 329 | ||
330 | /* free any pending tx skb */ | ||
331 | if (pending_skb) { | ||
332 | dev_kfree_skb(pending_skb); | ||
333 | lp->stats.tx_errors++; | ||
334 | lp->stats.tx_aborted_errors++; | ||
335 | } | ||
336 | |||
327 | /* | 337 | /* |
328 | * This resets the registers mostly to defaults, but doesn't | 338 | * This resets the registers mostly to defaults, but doesn't |
329 | * affect EEPROM. That seems unnecessary | 339 | * affect EEPROM. That seems unnecessary |
@@ -389,14 +399,6 @@ static void smc_reset(struct net_device *dev) | |||
389 | SMC_SELECT_BANK(2); | 399 | SMC_SELECT_BANK(2); |
390 | SMC_SET_MMU_CMD(MC_RESET); | 400 | SMC_SET_MMU_CMD(MC_RESET); |
391 | SMC_WAIT_MMU_BUSY(); | 401 | SMC_WAIT_MMU_BUSY(); |
392 | |||
393 | /* clear anything saved */ | ||
394 | if (lp->pending_tx_skb != NULL) { | ||
395 | dev_kfree_skb (lp->pending_tx_skb); | ||
396 | lp->pending_tx_skb = NULL; | ||
397 | lp->stats.tx_errors++; | ||
398 | lp->stats.tx_aborted_errors++; | ||
399 | } | ||
400 | } | 402 | } |
401 | 403 | ||
402 | /* | 404 | /* |
@@ -440,6 +442,7 @@ static void smc_shutdown(struct net_device *dev) | |||
440 | { | 442 | { |
441 | struct smc_local *lp = netdev_priv(dev); | 443 | struct smc_local *lp = netdev_priv(dev); |
442 | void __iomem *ioaddr = lp->base; | 444 | void __iomem *ioaddr = lp->base; |
445 | struct sk_buff *pending_skb; | ||
443 | 446 | ||
444 | DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); | 447 | DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); |
445 | 448 | ||
@@ -447,7 +450,11 @@ static void smc_shutdown(struct net_device *dev) | |||
447 | spin_lock(&lp->lock); | 450 | spin_lock(&lp->lock); |
448 | SMC_SELECT_BANK(2); | 451 | SMC_SELECT_BANK(2); |
449 | SMC_SET_INT_MASK(0); | 452 | SMC_SET_INT_MASK(0); |
453 | pending_skb = lp->pending_tx_skb; | ||
454 | lp->pending_tx_skb = NULL; | ||
450 | spin_unlock(&lp->lock); | 455 | spin_unlock(&lp->lock); |
456 | if (pending_skb) | ||
457 | dev_kfree_skb(pending_skb); | ||
451 | 458 | ||
452 | /* and tell the card to stay away from that nasty outside world */ | 459 | /* and tell the card to stay away from that nasty outside world */ |
453 | SMC_SELECT_BANK(0); | 460 | SMC_SELECT_BANK(0); |
@@ -627,7 +634,12 @@ static void smc_hardware_send_pkt(unsigned long data) | |||
627 | } | 634 | } |
628 | 635 | ||
629 | skb = lp->pending_tx_skb; | 636 | skb = lp->pending_tx_skb; |
637 | if (unlikely(!skb)) { | ||
638 | smc_special_unlock(&lp->lock); | ||
639 | return; | ||
640 | } | ||
630 | lp->pending_tx_skb = NULL; | 641 | lp->pending_tx_skb = NULL; |
642 | |||
631 | packet_no = SMC_GET_AR(); | 643 | packet_no = SMC_GET_AR(); |
632 | if (unlikely(packet_no & AR_FAILED)) { | 644 | if (unlikely(packet_no & AR_FAILED)) { |
633 | printk("%s: Memory allocation failed.\n", dev->name); | 645 | printk("%s: Memory allocation failed.\n", dev->name); |
@@ -702,7 +714,6 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
702 | DBG(3, "%s: %s\n", dev->name, __FUNCTION__); | 714 | DBG(3, "%s: %s\n", dev->name, __FUNCTION__); |
703 | 715 | ||
704 | BUG_ON(lp->pending_tx_skb != NULL); | 716 | BUG_ON(lp->pending_tx_skb != NULL); |
705 | lp->pending_tx_skb = skb; | ||
706 | 717 | ||
707 | /* | 718 | /* |
708 | * The MMU wants the number of pages to be the number of 256 bytes | 719 | * The MMU wants the number of pages to be the number of 256 bytes |
@@ -718,7 +729,6 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
718 | numPages = ((skb->len & ~1) + (6 - 1)) >> 8; | 729 | numPages = ((skb->len & ~1) + (6 - 1)) >> 8; |
719 | if (unlikely(numPages > 7)) { | 730 | if (unlikely(numPages > 7)) { |
720 | printk("%s: Far too big packet error.\n", dev->name); | 731 | printk("%s: Far too big packet error.\n", dev->name); |
721 | lp->pending_tx_skb = NULL; | ||
722 | lp->stats.tx_errors++; | 732 | lp->stats.tx_errors++; |
723 | lp->stats.tx_dropped++; | 733 | lp->stats.tx_dropped++; |
724 | dev_kfree_skb(skb); | 734 | dev_kfree_skb(skb); |
@@ -745,6 +755,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
745 | 755 | ||
746 | smc_special_unlock(&lp->lock); | 756 | smc_special_unlock(&lp->lock); |
747 | 757 | ||
758 | lp->pending_tx_skb = skb; | ||
748 | if (!poll_count) { | 759 | if (!poll_count) { |
749 | /* oh well, wait until the chip finds memory later */ | 760 | /* oh well, wait until the chip finds memory later */ |
750 | netif_stop_queue(dev); | 761 | netif_stop_queue(dev); |
@@ -1062,7 +1073,7 @@ static void smc_phy_powerdown(struct net_device *dev) | |||
1062 | above). linkwatch_event() also wants the netlink semaphore. | 1073 | above). linkwatch_event() also wants the netlink semaphore. |
1063 | */ | 1074 | */ |
1064 | while(lp->work_pending) | 1075 | while(lp->work_pending) |
1065 | schedule(); | 1076 | yield(); |
1066 | 1077 | ||
1067 | bmcr = smc_phy_read(dev, phy, MII_BMCR); | 1078 | bmcr = smc_phy_read(dev, phy, MII_BMCR); |
1068 | smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); | 1079 | smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); |
@@ -1606,14 +1617,8 @@ static int smc_close(struct net_device *dev) | |||
1606 | 1617 | ||
1607 | /* clear everything */ | 1618 | /* clear everything */ |
1608 | smc_shutdown(dev); | 1619 | smc_shutdown(dev); |
1609 | 1620 | tasklet_kill(&lp->tx_task); | |
1610 | smc_phy_powerdown(dev); | 1621 | smc_phy_powerdown(dev); |
1611 | |||
1612 | if (lp->pending_tx_skb) { | ||
1613 | dev_kfree_skb(lp->pending_tx_skb); | ||
1614 | lp->pending_tx_skb = NULL; | ||
1615 | } | ||
1616 | |||
1617 | return 0; | 1622 | return 0; |
1618 | } | 1623 | } |
1619 | 1624 | ||
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 6e5ade99a38f..97712c3c4e07 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c | |||
@@ -455,8 +455,7 @@ static int streamer_reset(struct net_device *dev) | |||
455 | writew(readw(streamer_mmio + BCTL) | BCTL_SOFTRESET, streamer_mmio + BCTL); | 455 | writew(readw(streamer_mmio + BCTL) | BCTL_SOFTRESET, streamer_mmio + BCTL); |
456 | t = jiffies; | 456 | t = jiffies; |
457 | /* Hold soft reset bit for a while */ | 457 | /* Hold soft reset bit for a while */ |
458 | current->state = TASK_UNINTERRUPTIBLE; | 458 | ssleep(1); |
459 | schedule_timeout(HZ); | ||
460 | 459 | ||
461 | writew(readw(streamer_mmio + BCTL) & ~BCTL_SOFTRESET, | 460 | writew(readw(streamer_mmio + BCTL) & ~BCTL_SOFTRESET, |
462 | streamer_mmio + BCTL); | 461 | streamer_mmio + BCTL); |
@@ -512,8 +511,7 @@ static int streamer_reset(struct net_device *dev) | |||
512 | writew(SISR_MI, streamer_mmio + SISR_MASK_SUM); | 511 | writew(SISR_MI, streamer_mmio + SISR_MASK_SUM); |
513 | 512 | ||
514 | while (!((readw(streamer_mmio + SISR)) & SISR_SRB_REPLY)) { | 513 | while (!((readw(streamer_mmio + SISR)) & SISR_SRB_REPLY)) { |
515 | current->state = TASK_INTERRUPTIBLE; | 514 | msleep_interruptible(100); |
516 | schedule_timeout(HZ/10); | ||
517 | if (jiffies - t > 40 * HZ) { | 515 | if (jiffies - t > 40 * HZ) { |
518 | printk(KERN_ERR | 516 | printk(KERN_ERR |
519 | "IBM PCI tokenring card not responding\n"); | 517 | "IBM PCI tokenring card not responding\n"); |
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index cfc346e72d62..08e0f80f89d5 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c | |||
@@ -242,6 +242,7 @@ static struct pci_device_id tulip_pci_tbl[] = { | |||
242 | { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */ | 242 | { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */ |
243 | { 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */ | 243 | { 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */ |
244 | { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ | 244 | { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ |
245 | { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */ | ||
245 | { } /* terminate list */ | 246 | { } /* terminate list */ |
246 | }; | 247 | }; |
247 | MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); | 248 | MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); |
@@ -1756,11 +1757,19 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) | |||
1756 | { | 1757 | { |
1757 | struct net_device *dev = pci_get_drvdata(pdev); | 1758 | struct net_device *dev = pci_get_drvdata(pdev); |
1758 | 1759 | ||
1759 | if (dev && netif_running (dev) && netif_device_present (dev)) { | 1760 | if (!dev) |
1760 | netif_device_detach (dev); | 1761 | return -EINVAL; |
1761 | tulip_down (dev); | 1762 | |
1762 | /* pci_power_off(pdev, -1); */ | 1763 | if (netif_running(dev)) |
1763 | } | 1764 | tulip_down(dev); |
1765 | |||
1766 | netif_device_detach(dev); | ||
1767 | free_irq(dev->irq, dev); | ||
1768 | |||
1769 | pci_save_state(pdev); | ||
1770 | pci_disable_device(pdev); | ||
1771 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
1772 | |||
1764 | return 0; | 1773 | return 0; |
1765 | } | 1774 | } |
1766 | 1775 | ||
@@ -1768,15 +1777,26 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) | |||
1768 | static int tulip_resume(struct pci_dev *pdev) | 1777 | static int tulip_resume(struct pci_dev *pdev) |
1769 | { | 1778 | { |
1770 | struct net_device *dev = pci_get_drvdata(pdev); | 1779 | struct net_device *dev = pci_get_drvdata(pdev); |
1780 | int retval; | ||
1771 | 1781 | ||
1772 | if (dev && netif_running (dev) && !netif_device_present (dev)) { | 1782 | if (!dev) |
1773 | #if 1 | 1783 | return -EINVAL; |
1774 | pci_enable_device (pdev); | 1784 | |
1775 | #endif | 1785 | pci_set_power_state(pdev, PCI_D0); |
1776 | /* pci_power_on(pdev); */ | 1786 | pci_restore_state(pdev); |
1777 | tulip_up (dev); | 1787 | |
1778 | netif_device_attach (dev); | 1788 | pci_enable_device(pdev); |
1789 | |||
1790 | if ((retval = request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))) { | ||
1791 | printk (KERN_ERR "tulip: request_irq failed in resume\n"); | ||
1792 | return retval; | ||
1779 | } | 1793 | } |
1794 | |||
1795 | netif_device_attach(dev); | ||
1796 | |||
1797 | if (netif_running(dev)) | ||
1798 | tulip_up(dev); | ||
1799 | |||
1780 | return 0; | 1800 | return 0; |
1781 | } | 1801 | } |
1782 | 1802 | ||
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 6200cfc4244e..be1c1047b9ba 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c | |||
@@ -1398,7 +1398,7 @@ static void rhine_tx(struct net_device *dev) | |||
1398 | while (rp->dirty_tx != rp->cur_tx) { | 1398 | while (rp->dirty_tx != rp->cur_tx) { |
1399 | txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status); | 1399 | txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status); |
1400 | if (debug > 6) | 1400 | if (debug > 6) |
1401 | printk(KERN_DEBUG " Tx scavenge %d status %8.8x.\n", | 1401 | printk(KERN_DEBUG "Tx scavenge %d status %8.8x.\n", |
1402 | entry, txstatus); | 1402 | entry, txstatus); |
1403 | if (txstatus & DescOwn) | 1403 | if (txstatus & DescOwn) |
1404 | break; | 1404 | break; |
@@ -1469,7 +1469,7 @@ static void rhine_rx(struct net_device *dev) | |||
1469 | int data_size = desc_status >> 16; | 1469 | int data_size = desc_status >> 16; |
1470 | 1470 | ||
1471 | if (debug > 4) | 1471 | if (debug > 4) |
1472 | printk(KERN_DEBUG " rhine_rx() status is %8.8x.\n", | 1472 | printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n", |
1473 | desc_status); | 1473 | desc_status); |
1474 | if (--boguscnt < 0) | 1474 | if (--boguscnt < 0) |
1475 | break; | 1475 | break; |
@@ -1487,7 +1487,7 @@ static void rhine_rx(struct net_device *dev) | |||
1487 | } else if (desc_status & RxErr) { | 1487 | } else if (desc_status & RxErr) { |
1488 | /* There was a error. */ | 1488 | /* There was a error. */ |
1489 | if (debug > 2) | 1489 | if (debug > 2) |
1490 | printk(KERN_DEBUG " rhine_rx() Rx " | 1490 | printk(KERN_DEBUG "rhine_rx() Rx " |
1491 | "error was %8.8x.\n", | 1491 | "error was %8.8x.\n", |
1492 | desc_status); | 1492 | desc_status); |
1493 | rp->stats.rx_errors++; | 1493 | rp->stats.rx_errors++; |
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 7575b799ce53..7217d44e8854 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c | |||
@@ -981,6 +981,7 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd) | |||
981 | /* Wait for any previous command to complete */ | 981 | /* Wait for any previous command to complete */ |
982 | while (mbval > NAK) { | 982 | while (mbval > NAK) { |
983 | spin_unlock_irqrestore(&card->card_lock, flags); | 983 | spin_unlock_irqrestore(&card->card_lock, flags); |
984 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
984 | schedule_timeout(1); | 985 | schedule_timeout(1); |
985 | spin_lock_irqsave(&card->card_lock, flags); | 986 | spin_lock_irqsave(&card->card_lock, flags); |
986 | 987 | ||
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 180968899cad..c12648d8192b 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -900,7 +900,7 @@ typedef struct aironet_ioctl { | |||
900 | unsigned char __user *data; // d-data | 900 | unsigned char __user *data; // d-data |
901 | } aironet_ioctl; | 901 | } aironet_ioctl; |
902 | 902 | ||
903 | static char *swversion = "2.1"; | 903 | static char swversion[] = "2.1"; |
904 | #endif /* CISCO_EXT */ | 904 | #endif /* CISCO_EXT */ |
905 | 905 | ||
906 | #define NUM_MODULES 2 | 906 | #define NUM_MODULES 2 |
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index a57187391f81..4d0b5a336bd7 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -46,382 +46,9 @@ | |||
46 | * under either the MPL or the GPL. */ | 46 | * under either the MPL or the GPL. */ |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * v0.01 -> v0.02 - 21/3/2001 - Jean II | ||
50 | * o Allow to use regular ethX device name instead of dldwdX | ||
51 | * o Warning on IBSS with ESSID=any for firmware 6.06 | ||
52 | * o Put proper range.throughput values (optimistic) | ||
53 | * o IWSPY support (IOCTL and stat gather in Rx path) | ||
54 | * o Allow setting frequency in Ad-Hoc mode | ||
55 | * o Disable WEP setting if !has_wep to work on old firmware | ||
56 | * o Fix txpower range | ||
57 | * o Start adding support for Samsung/Compaq firmware | ||
58 | * | ||
59 | * v0.02 -> v0.03 - 23/3/2001 - Jean II | ||
60 | * o Start adding Symbol support - need to check all that | ||
61 | * o Fix Prism2/Symbol WEP to accept 128 bits keys | ||
62 | * o Add Symbol WEP (add authentication type) | ||
63 | * o Add Prism2/Symbol rate | ||
64 | * o Add PM timeout (holdover duration) | ||
65 | * o Enable "iwconfig eth0 key off" and friends (toggle flags) | ||
66 | * o Enable "iwconfig eth0 power unicast/all" (toggle flags) | ||
67 | * o Try with an Intel card. It report firmware 1.01, behave like | ||
68 | * an antiquated firmware, however on windows it says 2.00. Yuck ! | ||
69 | * o Workaround firmware bug in allocate buffer (Intel 1.01) | ||
70 | * o Finish external renaming to orinoco... | ||
71 | * o Testing with various Wavelan firmwares | ||
72 | * | ||
73 | * v0.03 -> v0.04 - 30/3/2001 - Jean II | ||
74 | * o Update to Wireless 11 -> add retry limit/lifetime support | ||
75 | * o Tested with a D-Link DWL 650 card, fill in firmware support | ||
76 | * o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot) | ||
77 | * o Fixed the Prism2 WEP bugs that I introduced in v0.03 :-( | ||
78 | * It works on D-Link *only* after a tcpdump. Weird... | ||
79 | * And still doesn't work on Intel card. Grrrr... | ||
80 | * o Update the mode after a setport3 | ||
81 | * o Add preamble setting for Symbol cards (not yet enabled) | ||
82 | * o Don't complain as much about Symbol cards... | ||
83 | * | ||
84 | * v0.04 -> v0.04b - 22/4/2001 - David Gibson | ||
85 | * o Removed the 'eth' parameter - always use ethXX as the | ||
86 | * interface name instead of dldwdXX. The other was racy | ||
87 | * anyway. | ||
88 | * o Clean up RID definitions in hermes.h, other cleanups | ||
89 | * | ||
90 | * v0.04b -> v0.04c - 24/4/2001 - Jean II | ||
91 | * o Tim Hurley <timster AT seiki.bliztech.com> reported a D-Link card | ||
92 | * with vendor 02 and firmware 0.08. Added in the capabilities... | ||
93 | * o Tested Lucent firmware 7.28, everything works... | ||
94 | * | ||
95 | * v0.04c -> v0.05 - 3/5/2001 - Benjamin Herrenschmidt | ||
96 | * o Spin-off Pcmcia code. This file is renamed orinoco.c, | ||
97 | * and orinoco_cs.c now contains only the Pcmcia specific stuff | ||
98 | * o Add Airport driver support on top of orinoco.c (see airport.c) | ||
99 | * | ||
100 | * v0.05 -> v0.05a - 4/5/2001 - Jean II | ||
101 | * o Revert to old Pcmcia code to fix breakage of Ben's changes... | ||
102 | * | ||
103 | * v0.05a -> v0.05b - 4/5/2001 - Jean II | ||
104 | * o add module parameter 'ignore_cis_vcc' for D-Link @ 5V | ||
105 | * o D-Link firmware doesn't support multicast. We just print a few | ||
106 | * error messages, but otherwise everything works... | ||
107 | * o For David : set/getport3 works fine, just upgrade iwpriv... | ||
108 | * | ||
109 | * v0.05b -> v0.05c - 5/5/2001 - Benjamin Herrenschmidt | ||
110 | * o Adapt airport.c to latest changes in orinoco.c | ||
111 | * o Remove deferred power enabling code | ||
112 | * | ||
113 | * v0.05c -> v0.05d - 5/5/2001 - Jean II | ||
114 | * o Workaround to SNAP decapsulate frame from Linksys AP | ||
115 | * original patch from : Dong Liu <dliu AT research.bell-labs.com> | ||
116 | * (note : the memcmp bug was mine - fixed) | ||
117 | * o Remove set_retry stuff, no firmware support it (bloat--). | ||
118 | * | ||
119 | * v0.05d -> v0.06 - 25/5/2001 - Jean II | ||
120 | * Original patch from "Hong Lin" <alin AT redhat.com>, | ||
121 | * "Ian Kinner" <ikinner AT redhat.com> | ||
122 | * and "David Smith" <dsmith AT redhat.com> | ||
123 | * o Init of priv->tx_rate_ctrl in firmware specific section. | ||
124 | * o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh ! | ||
125 | * o Spectrum card always need cor_reset (for every reset) | ||
126 | * o Fix cor_reset to not lose bit 7 in the register | ||
127 | * o flush_stale_links to remove zombie Pcmcia instances | ||
128 | * o Ack previous hermes event before reset | ||
129 | * Me (with my little hands) | ||
130 | * o Allow orinoco.c to call cor_reset via priv->card_reset_handler | ||
131 | * o Add priv->need_card_reset to toggle this feature | ||
132 | * o Fix various buglets when setting WEP in Symbol firmware | ||
133 | * Now, encryption is fully functional on Symbol cards. Youpi ! | ||
134 | * | ||
135 | * v0.06 -> v0.06b - 25/5/2001 - Jean II | ||
136 | * o IBSS on Symbol use port_mode = 4. Please don't ask... | ||
137 | * | ||
138 | * v0.06b -> v0.06c - 29/5/2001 - Jean II | ||
139 | * o Show first spy address in /proc/net/wireless for IBSS mode as well | ||
140 | * | ||
141 | * v0.06c -> v0.06d - 6/7/2001 - David Gibson | ||
142 | * o Change a bunch of KERN_INFO messages to KERN_DEBUG, as per Linus' | ||
143 | * wishes to reduce the number of unnecessary messages. | ||
144 | * o Removed bogus message on CRC error. | ||
145 | * o Merged fixes for v0.08 Prism 2 firmware from William Waghorn | ||
146 | * <willwaghorn AT yahoo.co.uk> | ||
147 | * o Slight cleanup/re-arrangement of firmware detection code. | ||
148 | * | ||
149 | * v0.06d -> v0.06e - 1/8/2001 - David Gibson | ||
150 | * o Removed some redundant global initializers (orinoco_cs.c). | ||
151 | * o Added some module metadata | ||
152 | * | ||
153 | * v0.06e -> v0.06f - 14/8/2001 - David Gibson | ||
154 | * o Wording fix to license | ||
155 | * o Added a 'use_alternate_encaps' module parameter for APs which need an | ||
156 | * oui of 00:00:00. We really need a better way of handling this, but | ||
157 | * the module flag is better than nothing for now. | ||
158 | * | ||
159 | * v0.06f -> v0.07 - 20/8/2001 - David Gibson | ||
160 | * o Removed BAP error retries from hermes_bap_seek(). For Tx we now | ||
161 | * let the upper layers handle the retry, we retry explicitly in the | ||
162 | * Rx path, but don't make as much noise about it. | ||
163 | * o Firmware detection cleanups. | ||
164 | * | ||
165 | * v0.07 -> v0.07a - 1/10/3001 - Jean II | ||
166 | * o Add code to read Symbol firmware revision, inspired by latest code | ||
167 | * in Spectrum24 by Lee John Keyser-Allen - Thanks Lee ! | ||
168 | * o Thanks to Jared Valentine <hidden AT xmission.com> for "providing" me | ||
169 | * a 3Com card with a recent firmware, fill out Symbol firmware | ||
170 | * capabilities of latest rev (2.20), as well as older Symbol cards. | ||
171 | * o Disable Power Management in newer Symbol firmware, the API | ||
172 | * has changed (documentation needed). | ||
173 | * | ||
174 | * v0.07a -> v0.08 - 3/10/2001 - David Gibson | ||
175 | * o Fixed a possible buffer overrun found by the Stanford checker (in | ||
176 | * dldwd_ioctl_setiwencode()). Can only be called by root anyway, so not | ||
177 | * a big problem. | ||
178 | * o Turned has_big_wep on for Intersil cards. That's not true for all of | ||
179 | * them but we should at least let the capable ones try. | ||
180 | * o Wait for BUSY to clear at the beginning of hermes_bap_seek(). I | ||
181 | * realized that my assumption that the driver's serialization | ||
182 | * would prevent the BAP being busy on entry was possibly false, because | ||
183 | * things other than seeks may make the BAP busy. | ||
184 | * o Use "alternate" (oui 00:00:00) encapsulation by default. | ||
185 | * Setting use_old_encaps will mimic the old behaviour, but I think we | ||
186 | * will be able to eliminate this. | ||
187 | * o Don't try to make __initdata const (the version string). This can't | ||
188 | * work because of the way the __initdata sectioning works. | ||
189 | * o Added MODULE_LICENSE tags. | ||
190 | * o Support for PLX (transparent PCMCIA->PCI bridge) cards. | ||
191 | * o Changed to using the new type-fascist min/max. | ||
192 | * | ||
193 | * v0.08 -> v0.08a - 9/10/2001 - David Gibson | ||
194 | * o Inserted some missing acknowledgements/info into the Changelog. | ||
195 | * o Fixed some bugs in the normalization of signal level reporting. | ||
196 | * o Fixed bad bug in WEP key handling on Intersil and Symbol firmware, | ||
197 | * which led to an instant crash on big-endian machines. | ||
198 | * | ||
199 | * v0.08a -> v0.08b - 20/11/2001 - David Gibson | ||
200 | * o Lots of cleanup and bugfixes in orinoco_plx.c | ||
201 | * o Cleanup to handling of Tx rate setting. | ||
202 | * o Removed support for old encapsulation method. | ||
203 | * o Removed old "dldwd" names. | ||
204 | * o Split RID constants into a new file hermes_rid.h | ||
205 | * o Renamed RID constants to match linux-wlan-ng and prism2.o | ||
206 | * o Bugfixes in hermes.c | ||
207 | * o Poke the PLX's INTCSR register, so it actually starts | ||
208 | * generating interrupts. These cards might actually work now. | ||
209 | * o Update to wireless extensions v12 (Jean II) | ||
210 | * o Support for tallies and inquire command (Jean II) | ||
211 | * o Airport updates for newer PPC kernels (BenH) | ||
212 | * | ||
213 | * v0.08b -> v0.09 - 21/12/2001 - David Gibson | ||
214 | * o Some new PCI IDs for PLX cards. | ||
215 | * o Removed broken attempt to do ALLMULTI reception. Just use | ||
216 | * promiscuous mode instead | ||
217 | * o Preliminary work for list-AP (Jean II) | ||
218 | * o Airport updates from (BenH) | ||
219 | * o Eliminated racy hw_ready stuff | ||
220 | * o Fixed generation of fake events in irq handler. This should | ||
221 | * finally kill the EIO problems (Jean II & dgibson) | ||
222 | * o Fixed breakage of bitrate set/get on Agere firmware (Jean II) | ||
223 | * | ||
224 | * v0.09 -> v0.09a - 2/1/2002 - David Gibson | ||
225 | * o Fixed stupid mistake in multicast list handling, triggering | ||
226 | * a BUG() | ||
227 | * | ||
228 | * v0.09a -> v0.09b - 16/1/2002 - David Gibson | ||
229 | * o Fixed even stupider mistake in new interrupt handling, which | ||
230 | * seriously broke things on big-endian machines. | ||
231 | * o Removed a bunch of redundant includes and exports. | ||
232 | * o Removed a redundant MOD_{INC,DEC}_USE_COUNT pair in airport.c | ||
233 | * o Don't attempt to do hardware level multicast reception on | ||
234 | * Intersil firmware, just go promisc instead. | ||
235 | * o Typo fixed in hermes_issue_cmd() | ||
236 | * o Eliminated WIRELESS_SPY #ifdefs | ||
237 | * o Status code reported on Tx exceptions | ||
238 | * o Moved netif_wake_queue() from ALLOC interrupts to TX and TXEXC | ||
239 | * interrupts, which should fix the timeouts we're seeing. | ||
240 | * | ||
241 | * v0.09b -> v0.10 - 25 Feb 2002 - David Gibson | ||
242 | * o Removed nested structures used for header parsing, so the | ||
243 | * driver should now work without hackery on ARM | ||
244 | * o Fix for WEP handling on Intersil (Hawk Newton) | ||
245 | * o Eliminated the /proc/hermes/ethXX/regs debugging file. It | ||
246 | * was never very useful. | ||
247 | * o Make Rx errors less noisy. | ||
248 | * | ||
249 | * v0.10 -> v0.11 - 5 Apr 2002 - David Gibson | ||
250 | * o Laid the groundwork in hermes.[ch] for devices which map | ||
251 | * into PCI memory space rather than IO space. | ||
252 | * o Fixed bug in multicast handling (cleared multicast list when | ||
253 | * leaving promiscuous mode). | ||
254 | * o Relegated Tx error messages to debug. | ||
255 | * o Cleaned up / corrected handling of allocation lengths. | ||
256 | * o Set OWNSSID in IBSS mode for WinXP interoperability (jimc). | ||
257 | * o Change to using alloc_etherdev() for structure allocations. | ||
258 | * o Check for and drop undersized packets. | ||
259 | * o Fixed a race in stopping/waking the queue. This should fix | ||
260 | * the timeout problems (Pavel Roskin) | ||
261 | * o Reverted to netif_wake_queue() on the ALLOC event. | ||
262 | * o Fixes for recent Symbol firmwares which lack AP density | ||
263 | * (Pavel Roskin). | ||
264 | * | ||
265 | * v0.11 -> v0.11a - 29 Apr 2002 - David Gibson | ||
266 | * o Handle different register spacing, necessary for Prism 2.5 | ||
267 | * PCI adaptors (Steve Hill). | ||
268 | * o Cleaned up initialization of card structures in orinoco_cs | ||
269 | * and airport. Removed card->priv field. | ||
270 | * o Make response structure optional for hermes_docmd_wait() | ||
271 | * Pavel Roskin) | ||
272 | * o Added PCI id for Nortel emobility to orinoco_plx.c. | ||
273 | * o Cleanup to handling of Symbol's allocation bug. (Pavel Roskin) | ||
274 | * o Cleanups to firmware capability detection. | ||
275 | * o Arrange for orinoco_pci.c to override firmware detection. | ||
276 | * We should be able to support the PCI Intersil cards now. | ||
277 | * o Cleanup handling of reset_cor and hard_reset (Pavel Roskin). | ||
278 | * o Remove erroneous use of USER_BAP in the TxExc handler (Jouni | ||
279 | * Malinen). | ||
280 | * o Makefile changes for better integration into David Hinds | ||
281 | * pcmcia-cs package. | ||
282 | * | ||
283 | * v0.11a -> v0.11b - 1 May 2002 - David Gibson | ||
284 | * o Better error reporting in orinoco_plx_init_one() | ||
285 | * o Fixed multiple bad kfree() bugs introduced by the | ||
286 | * alloc_orinocodev() changes. | ||
287 | * | ||
288 | * v0.11b -> v0.12 - 19 Jun 2002 - David Gibson | ||
289 | * o Support changing the MAC address. | ||
290 | * o Correct display of Intersil firmware revision numbers. | ||
291 | * o Entirely revised locking scheme. Should be both simpler and | ||
292 | * better. | ||
293 | * o Merged some common code in orinoco_plx, orinoco_pci and | ||
294 | * airport by creating orinoco_default_{open,stop,reset}() | ||
295 | * which are used as the dev->open, dev->stop, priv->reset | ||
296 | * callbacks if none are specified when alloc_orinocodev() is | ||
297 | * called. | ||
298 | * o Removed orinoco_plx_interrupt() and orinoco_pci_interrupt(). | ||
299 | * They didn't do anything. | ||
300 | * | ||
301 | * v0.12 -> v0.12a - 4 Jul 2002 - David Gibson | ||
302 | * o Some rearrangement of code. | ||
303 | * o Numerous fixups to locking and rest handling, particularly | ||
304 | * for PCMCIA. | ||
305 | * o This allows open and stop net_device methods to be in | ||
306 | * orinoco.c now, rather than in the init modules. | ||
307 | * o In orinoco_cs.c link->priv now points to the struct | ||
308 | * net_device not to the struct orinoco_private. | ||
309 | * o Added a check for undersized SNAP frames, which could cause | ||
310 | * crashes. | ||
311 | * | ||
312 | * v0.12a -> v0.12b - 11 Jul 2002 - David Gibson | ||
313 | * o Fix hw->num_init testing code, so num_init is actually | ||
314 | * incremented. | ||
315 | * o Fix very stupid bug in orinoco_cs which broke compile with | ||
316 | * CONFIG_SMP. | ||
317 | * o Squashed a warning. | ||
318 | * | ||
319 | * v0.12b -> v0.12c - 26 Jul 2002 - David Gibson | ||
320 | * o Change to C9X style designated initializers. | ||
321 | * o Add support for 3Com AirConnect PCI. | ||
322 | * o No longer ignore the hard_reset argument to | ||
323 | * alloc_orinocodev(). Oops. | ||
324 | * | ||
325 | * v0.12c -> v0.13beta1 - 13 Sep 2002 - David Gibson | ||
326 | * o Revert the broken 0.12* locking scheme and go to a new yet | ||
327 | * simpler scheme. | ||
328 | * o Do firmware resets only in orinoco_init() and when waking | ||
329 | * the card from hard sleep. | ||
330 | * | ||
331 | * v0.13beta1 -> v0.13 - 27 Sep 2002 - David Gibson | ||
332 | * o Re-introduced full resets (via schedule_task()) on Tx | ||
333 | * timeout. | ||
334 | * | ||
335 | * v0.13 -> v0.13a - 30 Sep 2002 - David Gibson | ||
336 | * o Minor cleanups to info frame handling. Add basic support | ||
337 | * for linkstatus info frames. | ||
338 | * o Include required kernel headers in orinoco.h, to avoid | ||
339 | * compile problems. | ||
340 | * | ||
341 | * v0.13a -> v0.13b - 10 Feb 2003 - David Gibson | ||
342 | * o Implemented hard reset for Airport cards | ||
343 | * o Experimental suspend/resume implementation for orinoco_pci | ||
344 | * o Abolished /proc debugging support, replaced with a debugging | ||
345 | * iwpriv. Now it's ugly and simple instead of ugly and complex. | ||
346 | * o Bugfix in hermes.c if the firmware returned a record length | ||
347 | * of 0, we could go clobbering memory. | ||
348 | * o Bugfix in orinoco_stop() - it used to fail if hw_unavailable | ||
349 | * was set, which was usually true on PCMCIA hot removes. | ||
350 | * o Track LINKSTATUS messages, silently drop Tx packets before | ||
351 | * we are connected (avoids confusing the firmware), and only | ||
352 | * give LINKSTATUS printk()s if the status has changed. | ||
353 | * | ||
354 | * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson | ||
355 | * o Cleanup: use dev instead of priv in various places. | ||
356 | * o Bug fix: Don't ReleaseConfiguration on RESET_PHYSICAL event | ||
357 | * if we're in the middle of a (driver initiated) hard reset. | ||
358 | * o Bug fix: ETH_ZLEN is supposed to include the header | ||
359 | * (Dionysus Blazakis & Manish Karir) | ||
360 | * o Convert to using workqueues instead of taskqueues (and | ||
361 | * backwards compatibility macros for pre 2.5.41 kernels). | ||
362 | * o Drop redundant (I think...) MOD_{INC,DEC}_USE_COUNT in | ||
363 | * airport.c | ||
364 | * o New orinoco_tmd.c init module from Joerg Dorchain for | ||
365 | * TMD7160 based PCI to PCMCIA bridges (similar to | ||
366 | * orinoco_plx.c). | ||
367 | * | ||
368 | * v0.13c -> v0.13d - 22 Apr 2003 - David Gibson | ||
369 | * o Make hw_unavailable a counter, rather than just a flag, this | ||
370 | * is necessary to avoid some races (such as a card being | ||
371 | * removed in the middle of orinoco_reset(). | ||
372 | * o Restore Release/RequestConfiguration in the PCMCIA event handler | ||
373 | * when dealing with a driver initiated hard reset. This is | ||
374 | * necessary to prevent hangs due to a spurious interrupt while | ||
375 | * the reset is in progress. | ||
376 | * o Clear the 802.11 header when transmitting, even though we | ||
377 | * don't use it. This fixes a long standing bug on some | ||
378 | * firmwares, which seem to get confused if that isn't done. | ||
379 | * o Be less eager to de-encapsulate SNAP frames, only do so if | ||
380 | * the OUI is 00:00:00 or 00:00:f8, leave others alone. The old | ||
381 | * behaviour broke CDP (Cisco Discovery Protocol). | ||
382 | * o Use dev instead of priv for free_irq() as well as | ||
383 | * request_irq() (oops). | ||
384 | * o Attempt to reset rather than giving up if we get too many | ||
385 | * IRQs. | ||
386 | * o Changed semantics of __orinoco_down() so it can be called | ||
387 | * safely with hw_unavailable set. It also now clears the | ||
388 | * linkstatus (since we're going to have to reassociate). | ||
389 | * | ||
390 | * v0.13d -> v0.13e - 12 May 2003 - David Gibson | ||
391 | * o Support for post-2.5.68 return values from irq handler. | ||
392 | * o Fixed bug where underlength packets would be double counted | ||
393 | * in the rx_dropped statistics. | ||
394 | * o Provided a module parameter to suppress linkstatus messages. | ||
395 | * | ||
396 | * v0.13e -> v0.14alpha1 - 30 Sep 2003 - David Gibson | ||
397 | * o Replaced priv->connected logic with netif_carrier_on/off() | ||
398 | * calls. | ||
399 | * o Remove has_ibss_any and never set the CREATEIBSS RID when | ||
400 | * the ESSID is empty. Too many firmwares break if we do. | ||
401 | * o 2.6 merges: Replace pdev->slot_name with pci_name(), remove | ||
402 | * __devinitdata from PCI ID tables, use free_netdev(). | ||
403 | * o Enabled shared-key authentication for Agere firmware (from | ||
404 | * Robert J. Moore <Robert.J.Moore AT allanbank.com> | ||
405 | * o Move netif_wake_queue() (back) to the Tx completion from the | ||
406 | * ALLOC event. This seems to prevent/mitigate the rolling | ||
407 | * error -110 problems at least on some Intersil firmwares. | ||
408 | * Theoretically reduces performance, but I can't measure it. | ||
409 | * Patch from Andrew Tridgell <tridge AT samba.org> | ||
410 | * | ||
411 | * v0.14alpha1 -> v0.14alpha2 - 20 Oct 2003 - David Gibson | ||
412 | * o Correctly turn off shared-key authentication when requested | ||
413 | * (bugfix from Robert J. Moore). | ||
414 | * o Correct airport sleep interfaces for current 2.6 kernels. | ||
415 | * o Add code for key change without disabling/enabling the MAC | ||
416 | * port. This is supposed to allow 802.1x to work sanely, but | ||
417 | * doesn't seem to yet. | ||
418 | * | ||
419 | * TODO | 49 | * TODO |
420 | * o New wireless extensions API (patch from Moustafa | ||
421 | * Youssef, updated by Jim Carter and Pavel Roskin). | ||
422 | * o Handle de-encapsulation within network layer, provide 802.11 | 50 | * o Handle de-encapsulation within network layer, provide 802.11 |
423 | * headers (patch from Thomas 'Dent' Mirlacher) | 51 | * headers (patch from Thomas 'Dent' Mirlacher) |
424 | * o RF monitor mode support | ||
425 | * o Fix possible races in SPY handling. | 52 | * o Fix possible races in SPY handling. |
426 | * o Disconnect wireless extensions from fundamental configuration. | 53 | * o Disconnect wireless extensions from fundamental configuration. |
427 | * o (maybe) Software WEP support (patch from Stano Meduna). | 54 | * o (maybe) Software WEP support (patch from Stano Meduna). |
@@ -462,7 +89,10 @@ | |||
462 | #include <linux/netdevice.h> | 89 | #include <linux/netdevice.h> |
463 | #include <linux/if_arp.h> | 90 | #include <linux/if_arp.h> |
464 | #include <linux/etherdevice.h> | 91 | #include <linux/etherdevice.h> |
92 | #include <linux/ethtool.h> | ||
465 | #include <linux/wireless.h> | 93 | #include <linux/wireless.h> |
94 | #include <net/iw_handler.h> | ||
95 | #include <net/ieee80211.h> | ||
466 | 96 | ||
467 | #include <net/ieee80211.h> | 97 | #include <net/ieee80211.h> |
468 | 98 | ||
@@ -497,6 +127,10 @@ static int ignore_disconnect; /* = 0 */ | |||
497 | module_param(ignore_disconnect, int, 0644); | 127 | module_param(ignore_disconnect, int, 0644); |
498 | MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer"); | 128 | MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer"); |
499 | 129 | ||
130 | static int force_monitor; /* = 0 */ | ||
131 | module_param(force_monitor, int, 0644); | ||
132 | MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); | ||
133 | |||
500 | /********************************************************************/ | 134 | /********************************************************************/ |
501 | /* Compile time configuration and compatibility stuff */ | 135 | /* Compile time configuration and compatibility stuff */ |
502 | /********************************************************************/ | 136 | /********************************************************************/ |
@@ -512,6 +146,10 @@ MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer | |||
512 | /* Internal constants */ | 146 | /* Internal constants */ |
513 | /********************************************************************/ | 147 | /********************************************************************/ |
514 | 148 | ||
149 | /* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ | ||
150 | static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | ||
151 | #define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) | ||
152 | |||
515 | #define ORINOCO_MIN_MTU 256 | 153 | #define ORINOCO_MIN_MTU 256 |
516 | #define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD) | 154 | #define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD) |
517 | 155 | ||
@@ -538,6 +176,11 @@ MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer | |||
538 | | HERMES_EV_WTERR | HERMES_EV_INFO \ | 176 | | HERMES_EV_WTERR | HERMES_EV_INFO \ |
539 | | HERMES_EV_INFDROP ) | 177 | | HERMES_EV_INFDROP ) |
540 | 178 | ||
179 | #define MAX_RID_LEN 1024 | ||
180 | |||
181 | static const struct iw_handler_def orinoco_handler_def; | ||
182 | static struct ethtool_ops orinoco_ethtool_ops; | ||
183 | |||
541 | /********************************************************************/ | 184 | /********************************************************************/ |
542 | /* Data tables */ | 185 | /* Data tables */ |
543 | /********************************************************************/ | 186 | /********************************************************************/ |
@@ -572,26 +215,45 @@ static struct { | |||
572 | /* Data types */ | 215 | /* Data types */ |
573 | /********************************************************************/ | 216 | /********************************************************************/ |
574 | 217 | ||
575 | struct header_struct { | 218 | /* Used in Event handling. |
576 | /* 802.3 */ | 219 | * We avoid nested structres as they break on ARM -- Moustafa */ |
577 | u8 dest[ETH_ALEN]; | 220 | struct hermes_tx_descriptor_802_11 { |
578 | u8 src[ETH_ALEN]; | 221 | /* hermes_tx_descriptor */ |
579 | u16 len; | 222 | u16 status; |
580 | /* 802.2 */ | 223 | u16 reserved1; |
224 | u16 reserved2; | ||
225 | u32 sw_support; | ||
226 | u8 retry_count; | ||
227 | u8 tx_rate; | ||
228 | u16 tx_control; | ||
229 | |||
230 | /* ieee802_11_hdr */ | ||
231 | u16 frame_ctl; | ||
232 | u16 duration_id; | ||
233 | u8 addr1[ETH_ALEN]; | ||
234 | u8 addr2[ETH_ALEN]; | ||
235 | u8 addr3[ETH_ALEN]; | ||
236 | u16 seq_ctl; | ||
237 | u8 addr4[ETH_ALEN]; | ||
238 | u16 data_len; | ||
239 | |||
240 | /* ethhdr */ | ||
241 | unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ | ||
242 | unsigned char h_source[ETH_ALEN]; /* source ether addr */ | ||
243 | unsigned short h_proto; /* packet type ID field */ | ||
244 | |||
245 | /* p8022_hdr */ | ||
581 | u8 dsap; | 246 | u8 dsap; |
582 | u8 ssap; | 247 | u8 ssap; |
583 | u8 ctrl; | 248 | u8 ctrl; |
584 | /* SNAP */ | ||
585 | u8 oui[3]; | 249 | u8 oui[3]; |
250 | |||
586 | u16 ethertype; | 251 | u16 ethertype; |
587 | } __attribute__ ((packed)); | 252 | } __attribute__ ((packed)); |
588 | 253 | ||
589 | /* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ | 254 | /* Rx frame header except compatibility 802.3 header */ |
590 | u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | ||
591 | |||
592 | #define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) | ||
593 | |||
594 | struct hermes_rx_descriptor { | 255 | struct hermes_rx_descriptor { |
256 | /* Control */ | ||
595 | u16 status; | 257 | u16 status; |
596 | u32 time; | 258 | u32 time; |
597 | u8 silence; | 259 | u8 silence; |
@@ -599,13 +261,24 @@ struct hermes_rx_descriptor { | |||
599 | u8 rate; | 261 | u8 rate; |
600 | u8 rxflow; | 262 | u8 rxflow; |
601 | u32 reserved; | 263 | u32 reserved; |
264 | |||
265 | /* 802.11 header */ | ||
266 | u16 frame_ctl; | ||
267 | u16 duration_id; | ||
268 | u8 addr1[ETH_ALEN]; | ||
269 | u8 addr2[ETH_ALEN]; | ||
270 | u8 addr3[ETH_ALEN]; | ||
271 | u16 seq_ctl; | ||
272 | u8 addr4[ETH_ALEN]; | ||
273 | |||
274 | /* Data length */ | ||
275 | u16 data_len; | ||
602 | } __attribute__ ((packed)); | 276 | } __attribute__ ((packed)); |
603 | 277 | ||
604 | /********************************************************************/ | 278 | /********************************************************************/ |
605 | /* Function prototypes */ | 279 | /* Function prototypes */ |
606 | /********************************************************************/ | 280 | /********************************************************************/ |
607 | 281 | ||
608 | static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
609 | static int __orinoco_program_rids(struct net_device *dev); | 282 | static int __orinoco_program_rids(struct net_device *dev); |
610 | static void __orinoco_set_multicast_list(struct net_device *dev); | 283 | static void __orinoco_set_multicast_list(struct net_device *dev); |
611 | 284 | ||
@@ -629,6 +302,10 @@ static inline void set_port_type(struct orinoco_private *priv) | |||
629 | priv->createibss = 1; | 302 | priv->createibss = 1; |
630 | } | 303 | } |
631 | break; | 304 | break; |
305 | case IW_MODE_MONITOR: | ||
306 | priv->port_type = 3; | ||
307 | priv->createibss = 0; | ||
308 | break; | ||
632 | default: | 309 | default: |
633 | printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", | 310 | printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", |
634 | priv->ndev->name); | 311 | priv->ndev->name); |
@@ -815,7 +492,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
815 | return 1; | 492 | return 1; |
816 | } | 493 | } |
817 | 494 | ||
818 | if (! netif_carrier_ok(dev)) { | 495 | if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) { |
819 | /* Oops, the firmware hasn't established a connection, | 496 | /* Oops, the firmware hasn't established a connection, |
820 | silently drop the packet (this seems to be the | 497 | silently drop the packet (this seems to be the |
821 | safest approach). */ | 498 | safest approach). */ |
@@ -952,26 +629,55 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) | |||
952 | struct orinoco_private *priv = netdev_priv(dev); | 629 | struct orinoco_private *priv = netdev_priv(dev); |
953 | struct net_device_stats *stats = &priv->stats; | 630 | struct net_device_stats *stats = &priv->stats; |
954 | u16 fid = hermes_read_regn(hw, TXCOMPLFID); | 631 | u16 fid = hermes_read_regn(hw, TXCOMPLFID); |
955 | struct hermes_tx_descriptor desc; | 632 | struct hermes_tx_descriptor_802_11 hdr; |
956 | int err = 0; | 633 | int err = 0; |
957 | 634 | ||
958 | if (fid == DUMMY_FID) | 635 | if (fid == DUMMY_FID) |
959 | return; /* Nothing's really happened */ | 636 | return; /* Nothing's really happened */ |
960 | 637 | ||
961 | err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0); | 638 | /* Read the frame header */ |
639 | err = hermes_bap_pread(hw, IRQ_BAP, &hdr, | ||
640 | sizeof(struct hermes_tx_descriptor) + | ||
641 | sizeof(struct ieee80211_hdr), | ||
642 | fid, 0); | ||
643 | |||
644 | hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); | ||
645 | stats->tx_errors++; | ||
646 | |||
962 | if (err) { | 647 | if (err) { |
963 | printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " | 648 | printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " |
964 | "(FID=%04X error %d)\n", | 649 | "(FID=%04X error %d)\n", |
965 | dev->name, fid, err); | 650 | dev->name, fid, err); |
966 | } else { | 651 | return; |
967 | DEBUG(1, "%s: Tx error, status %d\n", | ||
968 | dev->name, le16_to_cpu(desc.status)); | ||
969 | } | 652 | } |
970 | 653 | ||
971 | stats->tx_errors++; | 654 | DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name, |
655 | err, fid); | ||
656 | |||
657 | /* We produce a TXDROP event only for retry or lifetime | ||
658 | * exceeded, because that's the only status that really mean | ||
659 | * that this particular node went away. | ||
660 | * Other errors means that *we* screwed up. - Jean II */ | ||
661 | hdr.status = le16_to_cpu(hdr.status); | ||
662 | if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { | ||
663 | union iwreq_data wrqu; | ||
664 | |||
665 | /* Copy 802.11 dest address. | ||
666 | * We use the 802.11 header because the frame may | ||
667 | * not be 802.3 or may be mangled... | ||
668 | * In Ad-Hoc mode, it will be the node address. | ||
669 | * In managed mode, it will be most likely the AP addr | ||
670 | * User space will figure out how to convert it to | ||
671 | * whatever it needs (IP address or else). | ||
672 | * - Jean II */ | ||
673 | memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN); | ||
674 | wrqu.addr.sa_family = ARPHRD_ETHER; | ||
675 | |||
676 | /* Send event to user space */ | ||
677 | wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL); | ||
678 | } | ||
972 | 679 | ||
973 | netif_wake_queue(dev); | 680 | netif_wake_queue(dev); |
974 | hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); | ||
975 | } | 681 | } |
976 | 682 | ||
977 | static void orinoco_tx_timeout(struct net_device *dev) | 683 | static void orinoco_tx_timeout(struct net_device *dev) |
@@ -1048,18 +754,127 @@ static void orinoco_stat_gather(struct net_device *dev, | |||
1048 | } | 754 | } |
1049 | } | 755 | } |
1050 | 756 | ||
757 | /* | ||
758 | * orinoco_rx_monitor - handle received monitor frames. | ||
759 | * | ||
760 | * Arguments: | ||
761 | * dev network device | ||
762 | * rxfid received FID | ||
763 | * desc rx descriptor of the frame | ||
764 | * | ||
765 | * Call context: interrupt | ||
766 | */ | ||
767 | static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, | ||
768 | struct hermes_rx_descriptor *desc) | ||
769 | { | ||
770 | u32 hdrlen = 30; /* return full header by default */ | ||
771 | u32 datalen = 0; | ||
772 | u16 fc; | ||
773 | int err; | ||
774 | int len; | ||
775 | struct sk_buff *skb; | ||
776 | struct orinoco_private *priv = netdev_priv(dev); | ||
777 | struct net_device_stats *stats = &priv->stats; | ||
778 | hermes_t *hw = &priv->hw; | ||
779 | |||
780 | len = le16_to_cpu(desc->data_len); | ||
781 | |||
782 | /* Determine the size of the header and the data */ | ||
783 | fc = le16_to_cpu(desc->frame_ctl); | ||
784 | switch (fc & IEEE80211_FCTL_FTYPE) { | ||
785 | case IEEE80211_FTYPE_DATA: | ||
786 | if ((fc & IEEE80211_FCTL_TODS) | ||
787 | && (fc & IEEE80211_FCTL_FROMDS)) | ||
788 | hdrlen = 30; | ||
789 | else | ||
790 | hdrlen = 24; | ||
791 | datalen = len; | ||
792 | break; | ||
793 | case IEEE80211_FTYPE_MGMT: | ||
794 | hdrlen = 24; | ||
795 | datalen = len; | ||
796 | break; | ||
797 | case IEEE80211_FTYPE_CTL: | ||
798 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
799 | case IEEE80211_STYPE_PSPOLL: | ||
800 | case IEEE80211_STYPE_RTS: | ||
801 | case IEEE80211_STYPE_CFEND: | ||
802 | case IEEE80211_STYPE_CFENDACK: | ||
803 | hdrlen = 16; | ||
804 | break; | ||
805 | case IEEE80211_STYPE_CTS: | ||
806 | case IEEE80211_STYPE_ACK: | ||
807 | hdrlen = 10; | ||
808 | break; | ||
809 | } | ||
810 | break; | ||
811 | default: | ||
812 | /* Unknown frame type */ | ||
813 | break; | ||
814 | } | ||
815 | |||
816 | /* sanity check the length */ | ||
817 | if (datalen > IEEE80211_DATA_LEN + 12) { | ||
818 | printk(KERN_DEBUG "%s: oversized monitor frame, " | ||
819 | "data length = %d\n", dev->name, datalen); | ||
820 | err = -EIO; | ||
821 | stats->rx_length_errors++; | ||
822 | goto update_stats; | ||
823 | } | ||
824 | |||
825 | skb = dev_alloc_skb(hdrlen + datalen); | ||
826 | if (!skb) { | ||
827 | printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n", | ||
828 | dev->name); | ||
829 | err = -ENOMEM; | ||
830 | goto drop; | ||
831 | } | ||
832 | |||
833 | /* Copy the 802.11 header to the skb */ | ||
834 | memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen); | ||
835 | skb->mac.raw = skb->data; | ||
836 | |||
837 | /* If any, copy the data from the card to the skb */ | ||
838 | if (datalen > 0) { | ||
839 | err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), | ||
840 | ALIGN(datalen, 2), rxfid, | ||
841 | HERMES_802_2_OFFSET); | ||
842 | if (err) { | ||
843 | printk(KERN_ERR "%s: error %d reading monitor frame\n", | ||
844 | dev->name, err); | ||
845 | goto drop; | ||
846 | } | ||
847 | } | ||
848 | |||
849 | skb->dev = dev; | ||
850 | skb->ip_summed = CHECKSUM_NONE; | ||
851 | skb->pkt_type = PACKET_OTHERHOST; | ||
852 | skb->protocol = __constant_htons(ETH_P_802_2); | ||
853 | |||
854 | dev->last_rx = jiffies; | ||
855 | stats->rx_packets++; | ||
856 | stats->rx_bytes += skb->len; | ||
857 | |||
858 | netif_rx(skb); | ||
859 | return; | ||
860 | |||
861 | drop: | ||
862 | dev_kfree_skb_irq(skb); | ||
863 | update_stats: | ||
864 | stats->rx_errors++; | ||
865 | stats->rx_dropped++; | ||
866 | } | ||
867 | |||
1051 | static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) | 868 | static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) |
1052 | { | 869 | { |
1053 | struct orinoco_private *priv = netdev_priv(dev); | 870 | struct orinoco_private *priv = netdev_priv(dev); |
1054 | struct net_device_stats *stats = &priv->stats; | 871 | struct net_device_stats *stats = &priv->stats; |
1055 | struct iw_statistics *wstats = &priv->wstats; | 872 | struct iw_statistics *wstats = &priv->wstats; |
1056 | struct sk_buff *skb = NULL; | 873 | struct sk_buff *skb = NULL; |
1057 | u16 rxfid, status; | 874 | u16 rxfid, status, fc; |
1058 | int length, data_len, data_off; | 875 | int length; |
1059 | char *p; | ||
1060 | struct hermes_rx_descriptor desc; | 876 | struct hermes_rx_descriptor desc; |
1061 | struct header_struct hdr; | 877 | struct ethhdr *hdr; |
1062 | struct ethhdr *eh; | ||
1063 | int err; | 878 | int err; |
1064 | 879 | ||
1065 | rxfid = hermes_read_regn(hw, RXFID); | 880 | rxfid = hermes_read_regn(hw, RXFID); |
@@ -1069,53 +884,46 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) | |||
1069 | if (err) { | 884 | if (err) { |
1070 | printk(KERN_ERR "%s: error %d reading Rx descriptor. " | 885 | printk(KERN_ERR "%s: error %d reading Rx descriptor. " |
1071 | "Frame dropped.\n", dev->name, err); | 886 | "Frame dropped.\n", dev->name, err); |
1072 | stats->rx_errors++; | 887 | goto update_stats; |
1073 | goto drop; | ||
1074 | } | 888 | } |
1075 | 889 | ||
1076 | status = le16_to_cpu(desc.status); | 890 | status = le16_to_cpu(desc.status); |
1077 | 891 | ||
1078 | if (status & HERMES_RXSTAT_ERR) { | 892 | if (status & HERMES_RXSTAT_BADCRC) { |
1079 | if (status & HERMES_RXSTAT_UNDECRYPTABLE) { | 893 | DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", |
1080 | wstats->discard.code++; | 894 | dev->name); |
1081 | DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", | 895 | stats->rx_crc_errors++; |
1082 | dev->name); | 896 | goto update_stats; |
1083 | } else { | ||
1084 | stats->rx_crc_errors++; | ||
1085 | DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); | ||
1086 | } | ||
1087 | stats->rx_errors++; | ||
1088 | goto drop; | ||
1089 | } | 897 | } |
1090 | 898 | ||
1091 | /* For now we ignore the 802.11 header completely, assuming | 899 | /* Handle frames in monitor mode */ |
1092 | that the card's firmware has handled anything vital */ | 900 | if (priv->iw_mode == IW_MODE_MONITOR) { |
901 | orinoco_rx_monitor(dev, rxfid, &desc); | ||
902 | return; | ||
903 | } | ||
1093 | 904 | ||
1094 | err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), | 905 | if (status & HERMES_RXSTAT_UNDECRYPTABLE) { |
1095 | rxfid, HERMES_802_3_OFFSET); | 906 | DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", |
1096 | if (err) { | 907 | dev->name); |
1097 | printk(KERN_ERR "%s: error %d reading frame header. " | 908 | wstats->discard.code++; |
1098 | "Frame dropped.\n", dev->name, err); | 909 | goto update_stats; |
1099 | stats->rx_errors++; | ||
1100 | goto drop; | ||
1101 | } | 910 | } |
1102 | 911 | ||
1103 | length = ntohs(hdr.len); | 912 | length = le16_to_cpu(desc.data_len); |
1104 | 913 | fc = le16_to_cpu(desc.frame_ctl); | |
914 | |||
1105 | /* Sanity checks */ | 915 | /* Sanity checks */ |
1106 | if (length < 3) { /* No for even an 802.2 LLC header */ | 916 | if (length < 3) { /* No for even an 802.2 LLC header */ |
1107 | /* At least on Symbol firmware with PCF we get quite a | 917 | /* At least on Symbol firmware with PCF we get quite a |
1108 | lot of these legitimately - Poll frames with no | 918 | lot of these legitimately - Poll frames with no |
1109 | data. */ | 919 | data. */ |
1110 | stats->rx_dropped++; | 920 | return; |
1111 | goto drop; | ||
1112 | } | 921 | } |
1113 | if (length > IEEE80211_DATA_LEN) { | 922 | if (length > IEEE80211_DATA_LEN) { |
1114 | printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", | 923 | printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", |
1115 | dev->name, length); | 924 | dev->name, length); |
1116 | stats->rx_length_errors++; | 925 | stats->rx_length_errors++; |
1117 | stats->rx_errors++; | 926 | goto update_stats; |
1118 | goto drop; | ||
1119 | } | 927 | } |
1120 | 928 | ||
1121 | /* We need space for the packet data itself, plus an ethernet | 929 | /* We need space for the packet data itself, plus an ethernet |
@@ -1127,60 +935,53 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) | |||
1127 | if (!skb) { | 935 | if (!skb) { |
1128 | printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", | 936 | printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", |
1129 | dev->name); | 937 | dev->name); |
1130 | goto drop; | 938 | goto update_stats; |
1131 | } | 939 | } |
1132 | 940 | ||
1133 | skb_reserve(skb, 2); /* This way the IP header is aligned */ | 941 | /* We'll prepend the header, so reserve space for it. The worst |
942 | case is no decapsulation, when 802.3 header is prepended and | ||
943 | nothing is removed. 2 is for aligning the IP header. */ | ||
944 | skb_reserve(skb, ETH_HLEN + 2); | ||
945 | |||
946 | err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length), | ||
947 | ALIGN(length, 2), rxfid, | ||
948 | HERMES_802_2_OFFSET); | ||
949 | if (err) { | ||
950 | printk(KERN_ERR "%s: error %d reading frame. " | ||
951 | "Frame dropped.\n", dev->name, err); | ||
952 | goto drop; | ||
953 | } | ||
1134 | 954 | ||
1135 | /* Handle decapsulation | 955 | /* Handle decapsulation |
1136 | * In most cases, the firmware tell us about SNAP frames. | 956 | * In most cases, the firmware tell us about SNAP frames. |
1137 | * For some reason, the SNAP frames sent by LinkSys APs | 957 | * For some reason, the SNAP frames sent by LinkSys APs |
1138 | * are not properly recognised by most firmwares. | 958 | * are not properly recognised by most firmwares. |
1139 | * So, check ourselves */ | 959 | * So, check ourselves */ |
1140 | if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || | 960 | if (length >= ENCAPS_OVERHEAD && |
1141 | ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || | 961 | (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || |
1142 | is_ethersnap(&hdr)) { | 962 | ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || |
963 | is_ethersnap(skb->data))) { | ||
1143 | /* These indicate a SNAP within 802.2 LLC within | 964 | /* These indicate a SNAP within 802.2 LLC within |
1144 | 802.11 frame which we'll need to de-encapsulate to | 965 | 802.11 frame which we'll need to de-encapsulate to |
1145 | the original EthernetII frame. */ | 966 | the original EthernetII frame. */ |
1146 | 967 | hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD); | |
1147 | if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */ | ||
1148 | stats->rx_length_errors++; | ||
1149 | goto drop; | ||
1150 | } | ||
1151 | |||
1152 | /* Remove SNAP header, reconstruct EthernetII frame */ | ||
1153 | data_len = length - ENCAPS_OVERHEAD; | ||
1154 | data_off = HERMES_802_3_OFFSET + sizeof(hdr); | ||
1155 | |||
1156 | eh = (struct ethhdr *)skb_put(skb, ETH_HLEN); | ||
1157 | |||
1158 | memcpy(eh, &hdr, 2 * ETH_ALEN); | ||
1159 | eh->h_proto = hdr.ethertype; | ||
1160 | } else { | 968 | } else { |
1161 | /* All other cases indicate a genuine 802.3 frame. No | 969 | /* 802.3 frame - prepend 802.3 header as is */ |
1162 | decapsulation needed. We just throw the whole | 970 | hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN); |
1163 | thing in, and hope the protocol layer can deal with | 971 | hdr->h_proto = htons(length); |
1164 | it as 802.3 */ | ||
1165 | data_len = length; | ||
1166 | data_off = HERMES_802_3_OFFSET; | ||
1167 | /* FIXME: we re-read from the card data we already read here */ | ||
1168 | } | ||
1169 | |||
1170 | p = skb_put(skb, data_len); | ||
1171 | err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2), | ||
1172 | rxfid, data_off); | ||
1173 | if (err) { | ||
1174 | printk(KERN_ERR "%s: error %d reading frame. " | ||
1175 | "Frame dropped.\n", dev->name, err); | ||
1176 | stats->rx_errors++; | ||
1177 | goto drop; | ||
1178 | } | 972 | } |
973 | memcpy(hdr->h_dest, desc.addr1, ETH_ALEN); | ||
974 | if (fc & IEEE80211_FCTL_FROMDS) | ||
975 | memcpy(hdr->h_source, desc.addr3, ETH_ALEN); | ||
976 | else | ||
977 | memcpy(hdr->h_source, desc.addr2, ETH_ALEN); | ||
1179 | 978 | ||
1180 | dev->last_rx = jiffies; | 979 | dev->last_rx = jiffies; |
1181 | skb->dev = dev; | 980 | skb->dev = dev; |
1182 | skb->protocol = eth_type_trans(skb, dev); | 981 | skb->protocol = eth_type_trans(skb, dev); |
1183 | skb->ip_summed = CHECKSUM_NONE; | 982 | skb->ip_summed = CHECKSUM_NONE; |
983 | if (fc & IEEE80211_FCTL_TODS) | ||
984 | skb->pkt_type = PACKET_OTHERHOST; | ||
1184 | 985 | ||
1185 | /* Process the wireless stats if needed */ | 986 | /* Process the wireless stats if needed */ |
1186 | orinoco_stat_gather(dev, skb, &desc); | 987 | orinoco_stat_gather(dev, skb, &desc); |
@@ -1193,11 +994,10 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) | |||
1193 | return; | 994 | return; |
1194 | 995 | ||
1195 | drop: | 996 | drop: |
997 | dev_kfree_skb_irq(skb); | ||
998 | update_stats: | ||
999 | stats->rx_errors++; | ||
1196 | stats->rx_dropped++; | 1000 | stats->rx_dropped++; |
1197 | |||
1198 | if (skb) | ||
1199 | dev_kfree_skb_irq(skb); | ||
1200 | return; | ||
1201 | } | 1001 | } |
1202 | 1002 | ||
1203 | /********************************************************************/ | 1003 | /********************************************************************/ |
@@ -1241,6 +1041,99 @@ static void print_linkstatus(struct net_device *dev, u16 status) | |||
1241 | dev->name, s, status); | 1041 | dev->name, s, status); |
1242 | } | 1042 | } |
1243 | 1043 | ||
1044 | /* Search scan results for requested BSSID, join it if found */ | ||
1045 | static void orinoco_join_ap(struct net_device *dev) | ||
1046 | { | ||
1047 | struct orinoco_private *priv = netdev_priv(dev); | ||
1048 | struct hermes *hw = &priv->hw; | ||
1049 | int err; | ||
1050 | unsigned long flags; | ||
1051 | struct join_req { | ||
1052 | u8 bssid[ETH_ALEN]; | ||
1053 | u16 channel; | ||
1054 | } __attribute__ ((packed)) req; | ||
1055 | const int atom_len = offsetof(struct prism2_scan_apinfo, atim); | ||
1056 | struct prism2_scan_apinfo *atom; | ||
1057 | int offset = 4; | ||
1058 | u8 *buf; | ||
1059 | u16 len; | ||
1060 | |||
1061 | /* Allocate buffer for scan results */ | ||
1062 | buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL); | ||
1063 | if (! buf) | ||
1064 | return; | ||
1065 | |||
1066 | if (orinoco_lock(priv, &flags) != 0) | ||
1067 | goto out; | ||
1068 | |||
1069 | /* Sanity checks in case user changed something in the meantime */ | ||
1070 | if (! priv->bssid_fixed) | ||
1071 | goto out; | ||
1072 | |||
1073 | if (strlen(priv->desired_essid) == 0) | ||
1074 | goto out; | ||
1075 | |||
1076 | /* Read scan results from the firmware */ | ||
1077 | err = hermes_read_ltv(hw, USER_BAP, | ||
1078 | HERMES_RID_SCANRESULTSTABLE, | ||
1079 | MAX_SCAN_LEN, &len, buf); | ||
1080 | if (err) { | ||
1081 | printk(KERN_ERR "%s: Cannot read scan results\n", | ||
1082 | dev->name); | ||
1083 | goto out; | ||
1084 | } | ||
1085 | |||
1086 | len = HERMES_RECLEN_TO_BYTES(len); | ||
1087 | |||
1088 | /* Go through the scan results looking for the channel of the AP | ||
1089 | * we were requested to join */ | ||
1090 | for (; offset + atom_len <= len; offset += atom_len) { | ||
1091 | atom = (struct prism2_scan_apinfo *) (buf + offset); | ||
1092 | if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) | ||
1093 | goto found; | ||
1094 | } | ||
1095 | |||
1096 | DEBUG(1, "%s: Requested AP not found in scan results\n", | ||
1097 | dev->name); | ||
1098 | goto out; | ||
1099 | |||
1100 | found: | ||
1101 | memcpy(req.bssid, priv->desired_bssid, ETH_ALEN); | ||
1102 | req.channel = atom->channel; /* both are little-endian */ | ||
1103 | err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST, | ||
1104 | &req); | ||
1105 | if (err) | ||
1106 | printk(KERN_ERR "%s: Error issuing join request\n", dev->name); | ||
1107 | |||
1108 | out: | ||
1109 | kfree(buf); | ||
1110 | orinoco_unlock(priv, &flags); | ||
1111 | } | ||
1112 | |||
1113 | /* Send new BSSID to userspace */ | ||
1114 | static void orinoco_send_wevents(struct net_device *dev) | ||
1115 | { | ||
1116 | struct orinoco_private *priv = netdev_priv(dev); | ||
1117 | struct hermes *hw = &priv->hw; | ||
1118 | union iwreq_data wrqu; | ||
1119 | int err; | ||
1120 | unsigned long flags; | ||
1121 | |||
1122 | if (orinoco_lock(priv, &flags) != 0) | ||
1123 | return; | ||
1124 | |||
1125 | err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID, | ||
1126 | ETH_ALEN, NULL, wrqu.ap_addr.sa_data); | ||
1127 | if (err != 0) | ||
1128 | return; | ||
1129 | |||
1130 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
1131 | |||
1132 | /* Send event to user space */ | ||
1133 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | ||
1134 | orinoco_unlock(priv, &flags); | ||
1135 | } | ||
1136 | |||
1244 | static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | 1137 | static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) |
1245 | { | 1138 | { |
1246 | struct orinoco_private *priv = netdev_priv(dev); | 1139 | struct orinoco_private *priv = netdev_priv(dev); |
@@ -1308,6 +1201,9 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | |||
1308 | u16 newstatus; | 1201 | u16 newstatus; |
1309 | int connected; | 1202 | int connected; |
1310 | 1203 | ||
1204 | if (priv->iw_mode == IW_MODE_MONITOR) | ||
1205 | break; | ||
1206 | |||
1311 | if (len != sizeof(linkstatus)) { | 1207 | if (len != sizeof(linkstatus)) { |
1312 | printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", | 1208 | printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", |
1313 | dev->name, len); | 1209 | dev->name, len); |
@@ -1320,6 +1216,15 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | |||
1320 | break; | 1216 | break; |
1321 | newstatus = le16_to_cpu(linkstatus.linkstatus); | 1217 | newstatus = le16_to_cpu(linkstatus.linkstatus); |
1322 | 1218 | ||
1219 | /* Symbol firmware uses "out of range" to signal that | ||
1220 | * the hostscan frame can be requested. */ | ||
1221 | if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE && | ||
1222 | priv->firmware_type == FIRMWARE_TYPE_SYMBOL && | ||
1223 | priv->has_hostscan && priv->scan_inprogress) { | ||
1224 | hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL); | ||
1225 | break; | ||
1226 | } | ||
1227 | |||
1323 | connected = (newstatus == HERMES_LINKSTATUS_CONNECTED) | 1228 | connected = (newstatus == HERMES_LINKSTATUS_CONNECTED) |
1324 | || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) | 1229 | || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) |
1325 | || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE); | 1230 | || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE); |
@@ -1329,12 +1234,89 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | |||
1329 | else if (!ignore_disconnect) | 1234 | else if (!ignore_disconnect) |
1330 | netif_carrier_off(dev); | 1235 | netif_carrier_off(dev); |
1331 | 1236 | ||
1332 | if (newstatus != priv->last_linkstatus) | 1237 | if (newstatus != priv->last_linkstatus) { |
1238 | priv->last_linkstatus = newstatus; | ||
1333 | print_linkstatus(dev, newstatus); | 1239 | print_linkstatus(dev, newstatus); |
1240 | /* The info frame contains only one word which is the | ||
1241 | * status (see hermes.h). The status is pretty boring | ||
1242 | * in itself, that's why we export the new BSSID... | ||
1243 | * Jean II */ | ||
1244 | schedule_work(&priv->wevent_work); | ||
1245 | } | ||
1246 | } | ||
1247 | break; | ||
1248 | case HERMES_INQ_SCAN: | ||
1249 | if (!priv->scan_inprogress && priv->bssid_fixed && | ||
1250 | priv->firmware_type == FIRMWARE_TYPE_INTERSIL) { | ||
1251 | schedule_work(&priv->join_work); | ||
1252 | break; | ||
1253 | } | ||
1254 | /* fall through */ | ||
1255 | case HERMES_INQ_HOSTSCAN: | ||
1256 | case HERMES_INQ_HOSTSCAN_SYMBOL: { | ||
1257 | /* Result of a scanning. Contains information about | ||
1258 | * cells in the vicinity - Jean II */ | ||
1259 | union iwreq_data wrqu; | ||
1260 | unsigned char *buf; | ||
1261 | |||
1262 | /* Sanity check */ | ||
1263 | if (len > 4096) { | ||
1264 | printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n", | ||
1265 | dev->name, len); | ||
1266 | break; | ||
1267 | } | ||
1268 | |||
1269 | /* We are a strict producer. If the previous scan results | ||
1270 | * have not been consumed, we just have to drop this | ||
1271 | * frame. We can't remove the previous results ourselves, | ||
1272 | * that would be *very* racy... Jean II */ | ||
1273 | if (priv->scan_result != NULL) { | ||
1274 | printk(KERN_WARNING "%s: Previous scan results not consumed, dropping info frame.\n", dev->name); | ||
1275 | break; | ||
1276 | } | ||
1277 | |||
1278 | /* Allocate buffer for results */ | ||
1279 | buf = kmalloc(len, GFP_ATOMIC); | ||
1280 | if (buf == NULL) | ||
1281 | /* No memory, so can't printk()... */ | ||
1282 | break; | ||
1334 | 1283 | ||
1335 | priv->last_linkstatus = newstatus; | 1284 | /* Read scan data */ |
1285 | err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, | ||
1286 | infofid, sizeof(info)); | ||
1287 | if (err) | ||
1288 | break; | ||
1289 | |||
1290 | #ifdef ORINOCO_DEBUG | ||
1291 | { | ||
1292 | int i; | ||
1293 | printk(KERN_DEBUG "Scan result [%02X", buf[0]); | ||
1294 | for(i = 1; i < (len * 2); i++) | ||
1295 | printk(":%02X", buf[i]); | ||
1296 | printk("]\n"); | ||
1297 | } | ||
1298 | #endif /* ORINOCO_DEBUG */ | ||
1299 | |||
1300 | /* Allow the clients to access the results */ | ||
1301 | priv->scan_len = len; | ||
1302 | priv->scan_result = buf; | ||
1303 | |||
1304 | /* Send an empty event to user space. | ||
1305 | * We don't send the received data on the event because | ||
1306 | * it would require us to do complex transcoding, and | ||
1307 | * we want to minimise the work done in the irq handler | ||
1308 | * Use a request to extract the data - Jean II */ | ||
1309 | wrqu.data.length = 0; | ||
1310 | wrqu.data.flags = 0; | ||
1311 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); | ||
1336 | } | 1312 | } |
1337 | break; | 1313 | break; |
1314 | case HERMES_INQ_SEC_STAT_AGERE: | ||
1315 | /* Security status (Agere specific) */ | ||
1316 | /* Ignore this frame for now */ | ||
1317 | if (priv->firmware_type == FIRMWARE_TYPE_AGERE) | ||
1318 | break; | ||
1319 | /* fall through */ | ||
1338 | default: | 1320 | default: |
1339 | printk(KERN_DEBUG "%s: Unknown information frame received: " | 1321 | printk(KERN_DEBUG "%s: Unknown information frame received: " |
1340 | "type 0x%04x, length %d\n", dev->name, type, len); | 1322 | "type 0x%04x, length %d\n", dev->name, type, len); |
@@ -1471,6 +1453,36 @@ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) | |||
1471 | return err; | 1453 | return err; |
1472 | } | 1454 | } |
1473 | 1455 | ||
1456 | /* Set fixed AP address */ | ||
1457 | static int __orinoco_hw_set_wap(struct orinoco_private *priv) | ||
1458 | { | ||
1459 | int roaming_flag; | ||
1460 | int err = 0; | ||
1461 | hermes_t *hw = &priv->hw; | ||
1462 | |||
1463 | switch (priv->firmware_type) { | ||
1464 | case FIRMWARE_TYPE_AGERE: | ||
1465 | /* not supported */ | ||
1466 | break; | ||
1467 | case FIRMWARE_TYPE_INTERSIL: | ||
1468 | if (priv->bssid_fixed) | ||
1469 | roaming_flag = 2; | ||
1470 | else | ||
1471 | roaming_flag = 1; | ||
1472 | |||
1473 | err = hermes_write_wordrec(hw, USER_BAP, | ||
1474 | HERMES_RID_CNFROAMINGMODE, | ||
1475 | roaming_flag); | ||
1476 | break; | ||
1477 | case FIRMWARE_TYPE_SYMBOL: | ||
1478 | err = HERMES_WRITE_RECORD(hw, USER_BAP, | ||
1479 | HERMES_RID_CNFMANDATORYBSSID_SYMBOL, | ||
1480 | &priv->desired_bssid); | ||
1481 | break; | ||
1482 | } | ||
1483 | return err; | ||
1484 | } | ||
1485 | |||
1474 | /* Change the WEP keys and/or the current keys. Can be called | 1486 | /* Change the WEP keys and/or the current keys. Can be called |
1475 | * either from __orinoco_hw_setup_wep() or directly from | 1487 | * either from __orinoco_hw_setup_wep() or directly from |
1476 | * orinoco_ioctl_setiwencode(). In the later case the association | 1488 | * orinoco_ioctl_setiwencode(). In the later case the association |
@@ -1656,6 +1668,13 @@ static int __orinoco_program_rids(struct net_device *dev) | |||
1656 | } | 1668 | } |
1657 | } | 1669 | } |
1658 | 1670 | ||
1671 | /* Set the desired BSSID */ | ||
1672 | err = __orinoco_hw_set_wap(priv); | ||
1673 | if (err) { | ||
1674 | printk(KERN_ERR "%s: Error %d setting AP address\n", | ||
1675 | dev->name, err); | ||
1676 | return err; | ||
1677 | } | ||
1659 | /* Set the desired ESSID */ | 1678 | /* Set the desired ESSID */ |
1660 | idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); | 1679 | idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); |
1661 | memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); | 1680 | memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); |
@@ -1794,6 +1813,20 @@ static int __orinoco_program_rids(struct net_device *dev) | |||
1794 | } | 1813 | } |
1795 | } | 1814 | } |
1796 | 1815 | ||
1816 | if (priv->iw_mode == IW_MODE_MONITOR) { | ||
1817 | /* Enable monitor mode */ | ||
1818 | dev->type = ARPHRD_IEEE80211; | ||
1819 | err = hermes_docmd_wait(hw, HERMES_CMD_TEST | | ||
1820 | HERMES_TEST_MONITOR, 0, NULL); | ||
1821 | } else { | ||
1822 | /* Disable monitor mode */ | ||
1823 | dev->type = ARPHRD_ETHER; | ||
1824 | err = hermes_docmd_wait(hw, HERMES_CMD_TEST | | ||
1825 | HERMES_TEST_STOP, 0, NULL); | ||
1826 | } | ||
1827 | if (err) | ||
1828 | return err; | ||
1829 | |||
1797 | /* Set promiscuity / multicast*/ | 1830 | /* Set promiscuity / multicast*/ |
1798 | priv->promiscuous = 0; | 1831 | priv->promiscuous = 0; |
1799 | priv->mc_count = 0; | 1832 | priv->mc_count = 0; |
@@ -1870,55 +1903,6 @@ __orinoco_set_multicast_list(struct net_device *dev) | |||
1870 | dev->flags &= ~IFF_PROMISC; | 1903 | dev->flags &= ~IFF_PROMISC; |
1871 | } | 1904 | } |
1872 | 1905 | ||
1873 | static int orinoco_reconfigure(struct net_device *dev) | ||
1874 | { | ||
1875 | struct orinoco_private *priv = netdev_priv(dev); | ||
1876 | struct hermes *hw = &priv->hw; | ||
1877 | unsigned long flags; | ||
1878 | int err = 0; | ||
1879 | |||
1880 | if (priv->broken_disableport) { | ||
1881 | schedule_work(&priv->reset_work); | ||
1882 | return 0; | ||
1883 | } | ||
1884 | |||
1885 | if (orinoco_lock(priv, &flags) != 0) | ||
1886 | return -EBUSY; | ||
1887 | |||
1888 | err = hermes_disable_port(hw, 0); | ||
1889 | if (err) { | ||
1890 | printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n", | ||
1891 | dev->name); | ||
1892 | priv->broken_disableport = 1; | ||
1893 | goto out; | ||
1894 | } | ||
1895 | |||
1896 | err = __orinoco_program_rids(dev); | ||
1897 | if (err) { | ||
1898 | printk(KERN_WARNING "%s: Unable to reconfigure card\n", | ||
1899 | dev->name); | ||
1900 | goto out; | ||
1901 | } | ||
1902 | |||
1903 | err = hermes_enable_port(hw, 0); | ||
1904 | if (err) { | ||
1905 | printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", | ||
1906 | dev->name); | ||
1907 | goto out; | ||
1908 | } | ||
1909 | |||
1910 | out: | ||
1911 | if (err) { | ||
1912 | printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); | ||
1913 | schedule_work(&priv->reset_work); | ||
1914 | err = 0; | ||
1915 | } | ||
1916 | |||
1917 | orinoco_unlock(priv, &flags); | ||
1918 | return err; | ||
1919 | |||
1920 | } | ||
1921 | |||
1922 | /* This must be called from user context, without locks held - use | 1906 | /* This must be called from user context, without locks held - use |
1923 | * schedule_work() */ | 1907 | * schedule_work() */ |
1924 | static void orinoco_reset(struct net_device *dev) | 1908 | static void orinoco_reset(struct net_device *dev) |
@@ -1947,6 +1931,11 @@ static void orinoco_reset(struct net_device *dev) | |||
1947 | 1931 | ||
1948 | orinoco_unlock(priv, &flags); | 1932 | orinoco_unlock(priv, &flags); |
1949 | 1933 | ||
1934 | /* Scanning support: Cleanup of driver struct */ | ||
1935 | kfree(priv->scan_result); | ||
1936 | priv->scan_result = NULL; | ||
1937 | priv->scan_inprogress = 0; | ||
1938 | |||
1950 | if (priv->hard_reset) { | 1939 | if (priv->hard_reset) { |
1951 | err = (*priv->hard_reset)(priv); | 1940 | err = (*priv->hard_reset)(priv); |
1952 | if (err) { | 1941 | if (err) { |
@@ -2185,6 +2174,8 @@ static int determine_firmware(struct net_device *dev) | |||
2185 | priv->has_mwo = (firmver >= 0x60000); | 2174 | priv->has_mwo = (firmver >= 0x60000); |
2186 | priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ | 2175 | priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ |
2187 | priv->ibss_port = 1; | 2176 | priv->ibss_port = 1; |
2177 | priv->has_hostscan = (firmver >= 0x8000a); | ||
2178 | priv->broken_monitor = (firmver >= 0x80000); | ||
2188 | 2179 | ||
2189 | /* Tested with Agere firmware : | 2180 | /* Tested with Agere firmware : |
2190 | * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II | 2181 | * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II |
@@ -2230,6 +2221,8 @@ static int determine_firmware(struct net_device *dev) | |||
2230 | priv->ibss_port = 4; | 2221 | priv->ibss_port = 4; |
2231 | priv->broken_disableport = (firmver == 0x25013) || | 2222 | priv->broken_disableport = (firmver == 0x25013) || |
2232 | (firmver >= 0x30000 && firmver <= 0x31000); | 2223 | (firmver >= 0x30000 && firmver <= 0x31000); |
2224 | priv->has_hostscan = (firmver >= 0x31001) || | ||
2225 | (firmver >= 0x29057 && firmver < 0x30000); | ||
2233 | /* Tested with Intel firmware : 0x20015 => Jean II */ | 2226 | /* Tested with Intel firmware : 0x20015 => Jean II */ |
2234 | /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */ | 2227 | /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */ |
2235 | break; | 2228 | break; |
@@ -2249,6 +2242,7 @@ static int determine_firmware(struct net_device *dev) | |||
2249 | priv->has_ibss = (firmver >= 0x000700); /* FIXME */ | 2242 | priv->has_ibss = (firmver >= 0x000700); /* FIXME */ |
2250 | priv->has_big_wep = priv->has_wep = (firmver >= 0x000800); | 2243 | priv->has_big_wep = priv->has_wep = (firmver >= 0x000800); |
2251 | priv->has_pm = (firmver >= 0x000700); | 2244 | priv->has_pm = (firmver >= 0x000700); |
2245 | priv->has_hostscan = (firmver >= 0x010301); | ||
2252 | 2246 | ||
2253 | if (firmver >= 0x000800) | 2247 | if (firmver >= 0x000800) |
2254 | priv->ibss_port = 0; | 2248 | priv->ibss_port = 0; |
@@ -2457,8 +2451,9 @@ struct net_device *alloc_orinocodev(int sizeof_card, | |||
2457 | dev->tx_timeout = orinoco_tx_timeout; | 2451 | dev->tx_timeout = orinoco_tx_timeout; |
2458 | dev->watchdog_timeo = HZ; /* 1 second timeout */ | 2452 | dev->watchdog_timeo = HZ; /* 1 second timeout */ |
2459 | dev->get_stats = orinoco_get_stats; | 2453 | dev->get_stats = orinoco_get_stats; |
2454 | dev->ethtool_ops = &orinoco_ethtool_ops; | ||
2460 | dev->get_wireless_stats = orinoco_get_wireless_stats; | 2455 | dev->get_wireless_stats = orinoco_get_wireless_stats; |
2461 | dev->do_ioctl = orinoco_ioctl; | 2456 | dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; |
2462 | dev->change_mtu = orinoco_change_mtu; | 2457 | dev->change_mtu = orinoco_change_mtu; |
2463 | dev->set_multicast_list = orinoco_set_multicast_list; | 2458 | dev->set_multicast_list = orinoco_set_multicast_list; |
2464 | /* we use the default eth_mac_addr for setting the MAC addr */ | 2459 | /* we use the default eth_mac_addr for setting the MAC addr */ |
@@ -2474,6 +2469,8 @@ struct net_device *alloc_orinocodev(int sizeof_card, | |||
2474 | * before anything else touches the | 2469 | * before anything else touches the |
2475 | * hardware */ | 2470 | * hardware */ |
2476 | INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); | 2471 | INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); |
2472 | INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev); | ||
2473 | INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev); | ||
2477 | 2474 | ||
2478 | netif_carrier_off(dev); | 2475 | netif_carrier_off(dev); |
2479 | priv->last_linkstatus = 0xffff; | 2476 | priv->last_linkstatus = 0xffff; |
@@ -2484,6 +2481,9 @@ struct net_device *alloc_orinocodev(int sizeof_card, | |||
2484 | 2481 | ||
2485 | void free_orinocodev(struct net_device *dev) | 2482 | void free_orinocodev(struct net_device *dev) |
2486 | { | 2483 | { |
2484 | struct orinoco_private *priv = netdev_priv(dev); | ||
2485 | |||
2486 | kfree(priv->scan_result); | ||
2487 | free_netdev(dev); | 2487 | free_netdev(dev); |
2488 | } | 2488 | } |
2489 | 2489 | ||
@@ -2491,24 +2491,6 @@ void free_orinocodev(struct net_device *dev) | |||
2491 | /* Wireless extensions */ | 2491 | /* Wireless extensions */ |
2492 | /********************************************************************/ | 2492 | /********************************************************************/ |
2493 | 2493 | ||
2494 | static int orinoco_hw_get_bssid(struct orinoco_private *priv, | ||
2495 | char buf[ETH_ALEN]) | ||
2496 | { | ||
2497 | hermes_t *hw = &priv->hw; | ||
2498 | int err = 0; | ||
2499 | unsigned long flags; | ||
2500 | |||
2501 | if (orinoco_lock(priv, &flags) != 0) | ||
2502 | return -EBUSY; | ||
2503 | |||
2504 | err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, | ||
2505 | ETH_ALEN, NULL, buf); | ||
2506 | |||
2507 | orinoco_unlock(priv, &flags); | ||
2508 | |||
2509 | return err; | ||
2510 | } | ||
2511 | |||
2512 | static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, | 2494 | static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, |
2513 | char buf[IW_ESSID_MAX_SIZE+1]) | 2495 | char buf[IW_ESSID_MAX_SIZE+1]) |
2514 | { | 2496 | { |
@@ -2634,140 +2616,271 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, | |||
2634 | return 0; | 2616 | return 0; |
2635 | } | 2617 | } |
2636 | 2618 | ||
2637 | static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq) | 2619 | static int orinoco_ioctl_getname(struct net_device *dev, |
2620 | struct iw_request_info *info, | ||
2621 | char *name, | ||
2622 | char *extra) | ||
2638 | { | 2623 | { |
2639 | struct orinoco_private *priv = netdev_priv(dev); | 2624 | struct orinoco_private *priv = netdev_priv(dev); |
2640 | int err = 0; | ||
2641 | int mode; | ||
2642 | struct iw_range range; | ||
2643 | int numrates; | 2625 | int numrates; |
2644 | int i, k; | 2626 | int err; |
2627 | |||
2628 | err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0); | ||
2629 | |||
2630 | if (!err && (numrates > 2)) | ||
2631 | strcpy(name, "IEEE 802.11b"); | ||
2632 | else | ||
2633 | strcpy(name, "IEEE 802.11-DS"); | ||
2634 | |||
2635 | return 0; | ||
2636 | } | ||
2637 | |||
2638 | static int orinoco_ioctl_setwap(struct net_device *dev, | ||
2639 | struct iw_request_info *info, | ||
2640 | struct sockaddr *ap_addr, | ||
2641 | char *extra) | ||
2642 | { | ||
2643 | struct orinoco_private *priv = netdev_priv(dev); | ||
2644 | int err = -EINPROGRESS; /* Call commit handler */ | ||
2645 | unsigned long flags; | 2645 | unsigned long flags; |
2646 | static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
2647 | static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
2646 | 2648 | ||
2647 | TRACE_ENTER(dev->name); | 2649 | if (orinoco_lock(priv, &flags) != 0) |
2650 | return -EBUSY; | ||
2651 | |||
2652 | /* Enable automatic roaming - no sanity checks are needed */ | ||
2653 | if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 || | ||
2654 | memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) { | ||
2655 | priv->bssid_fixed = 0; | ||
2656 | memset(priv->desired_bssid, 0, ETH_ALEN); | ||
2657 | |||
2658 | /* "off" means keep existing connection */ | ||
2659 | if (ap_addr->sa_data[0] == 0) { | ||
2660 | __orinoco_hw_set_wap(priv); | ||
2661 | err = 0; | ||
2662 | } | ||
2663 | goto out; | ||
2664 | } | ||
2648 | 2665 | ||
2649 | if (!access_ok(VERIFY_WRITE, rrq->pointer, sizeof(range))) | 2666 | if (priv->firmware_type == FIRMWARE_TYPE_AGERE) { |
2650 | return -EFAULT; | 2667 | printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't " |
2668 | "support manual roaming\n", | ||
2669 | dev->name); | ||
2670 | err = -EOPNOTSUPP; | ||
2671 | goto out; | ||
2672 | } | ||
2651 | 2673 | ||
2652 | rrq->length = sizeof(range); | 2674 | if (priv->iw_mode != IW_MODE_INFRA) { |
2675 | printk(KERN_WARNING "%s: Manual roaming supported only in " | ||
2676 | "managed mode\n", dev->name); | ||
2677 | err = -EOPNOTSUPP; | ||
2678 | goto out; | ||
2679 | } | ||
2680 | |||
2681 | /* Intersil firmware hangs without Desired ESSID */ | ||
2682 | if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL && | ||
2683 | strlen(priv->desired_essid) == 0) { | ||
2684 | printk(KERN_WARNING "%s: Desired ESSID must be set for " | ||
2685 | "manual roaming\n", dev->name); | ||
2686 | err = -EOPNOTSUPP; | ||
2687 | goto out; | ||
2688 | } | ||
2689 | |||
2690 | /* Finally, enable manual roaming */ | ||
2691 | priv->bssid_fixed = 1; | ||
2692 | memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN); | ||
2693 | |||
2694 | out: | ||
2695 | orinoco_unlock(priv, &flags); | ||
2696 | return err; | ||
2697 | } | ||
2698 | |||
2699 | static int orinoco_ioctl_getwap(struct net_device *dev, | ||
2700 | struct iw_request_info *info, | ||
2701 | struct sockaddr *ap_addr, | ||
2702 | char *extra) | ||
2703 | { | ||
2704 | struct orinoco_private *priv = netdev_priv(dev); | ||
2705 | |||
2706 | hermes_t *hw = &priv->hw; | ||
2707 | int err = 0; | ||
2708 | unsigned long flags; | ||
2653 | 2709 | ||
2654 | if (orinoco_lock(priv, &flags) != 0) | 2710 | if (orinoco_lock(priv, &flags) != 0) |
2655 | return -EBUSY; | 2711 | return -EBUSY; |
2656 | 2712 | ||
2657 | mode = priv->iw_mode; | 2713 | ap_addr->sa_family = ARPHRD_ETHER; |
2714 | err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, | ||
2715 | ETH_ALEN, NULL, ap_addr->sa_data); | ||
2716 | |||
2658 | orinoco_unlock(priv, &flags); | 2717 | orinoco_unlock(priv, &flags); |
2659 | 2718 | ||
2660 | memset(&range, 0, sizeof(range)); | 2719 | return err; |
2720 | } | ||
2661 | 2721 | ||
2662 | /* Much of this shamelessly taken from wvlan_cs.c. No idea | 2722 | static int orinoco_ioctl_setmode(struct net_device *dev, |
2663 | * what it all means -dgibson */ | 2723 | struct iw_request_info *info, |
2664 | range.we_version_compiled = WIRELESS_EXT; | 2724 | u32 *mode, |
2665 | range.we_version_source = 11; | 2725 | char *extra) |
2726 | { | ||
2727 | struct orinoco_private *priv = netdev_priv(dev); | ||
2728 | int err = -EINPROGRESS; /* Call commit handler */ | ||
2729 | unsigned long flags; | ||
2666 | 2730 | ||
2667 | range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ | 2731 | if (priv->iw_mode == *mode) |
2732 | return 0; | ||
2733 | |||
2734 | if (orinoco_lock(priv, &flags) != 0) | ||
2735 | return -EBUSY; | ||
2736 | |||
2737 | switch (*mode) { | ||
2738 | case IW_MODE_ADHOC: | ||
2739 | if (!priv->has_ibss && !priv->has_port3) | ||
2740 | err = -EOPNOTSUPP; | ||
2741 | break; | ||
2742 | |||
2743 | case IW_MODE_INFRA: | ||
2744 | break; | ||
2745 | |||
2746 | case IW_MODE_MONITOR: | ||
2747 | if (priv->broken_monitor && !force_monitor) { | ||
2748 | printk(KERN_WARNING "%s: Monitor mode support is " | ||
2749 | "buggy in this firmware, not enabling\n", | ||
2750 | dev->name); | ||
2751 | err = -EOPNOTSUPP; | ||
2752 | } | ||
2753 | break; | ||
2754 | |||
2755 | default: | ||
2756 | err = -EOPNOTSUPP; | ||
2757 | break; | ||
2758 | } | ||
2759 | |||
2760 | if (err == -EINPROGRESS) { | ||
2761 | priv->iw_mode = *mode; | ||
2762 | set_port_type(priv); | ||
2763 | } | ||
2764 | |||
2765 | orinoco_unlock(priv, &flags); | ||
2766 | |||
2767 | return err; | ||
2768 | } | ||
2769 | |||
2770 | static int orinoco_ioctl_getmode(struct net_device *dev, | ||
2771 | struct iw_request_info *info, | ||
2772 | u32 *mode, | ||
2773 | char *extra) | ||
2774 | { | ||
2775 | struct orinoco_private *priv = netdev_priv(dev); | ||
2776 | |||
2777 | *mode = priv->iw_mode; | ||
2778 | return 0; | ||
2779 | } | ||
2780 | |||
2781 | static int orinoco_ioctl_getiwrange(struct net_device *dev, | ||
2782 | struct iw_request_info *info, | ||
2783 | struct iw_point *rrq, | ||
2784 | char *extra) | ||
2785 | { | ||
2786 | struct orinoco_private *priv = netdev_priv(dev); | ||
2787 | int err = 0; | ||
2788 | struct iw_range *range = (struct iw_range *) extra; | ||
2789 | int numrates; | ||
2790 | int i, k; | ||
2791 | |||
2792 | TRACE_ENTER(dev->name); | ||
2793 | |||
2794 | rrq->length = sizeof(struct iw_range); | ||
2795 | memset(range, 0, sizeof(struct iw_range)); | ||
2796 | |||
2797 | range->we_version_compiled = WIRELESS_EXT; | ||
2798 | range->we_version_source = 14; | ||
2668 | 2799 | ||
2669 | /* Set available channels/frequencies */ | 2800 | /* Set available channels/frequencies */ |
2670 | range.num_channels = NUM_CHANNELS; | 2801 | range->num_channels = NUM_CHANNELS; |
2671 | k = 0; | 2802 | k = 0; |
2672 | for (i = 0; i < NUM_CHANNELS; i++) { | 2803 | for (i = 0; i < NUM_CHANNELS; i++) { |
2673 | if (priv->channel_mask & (1 << i)) { | 2804 | if (priv->channel_mask & (1 << i)) { |
2674 | range.freq[k].i = i + 1; | 2805 | range->freq[k].i = i + 1; |
2675 | range.freq[k].m = channel_frequency[i] * 100000; | 2806 | range->freq[k].m = channel_frequency[i] * 100000; |
2676 | range.freq[k].e = 1; | 2807 | range->freq[k].e = 1; |
2677 | k++; | 2808 | k++; |
2678 | } | 2809 | } |
2679 | 2810 | ||
2680 | if (k >= IW_MAX_FREQUENCIES) | 2811 | if (k >= IW_MAX_FREQUENCIES) |
2681 | break; | 2812 | break; |
2682 | } | 2813 | } |
2683 | range.num_frequency = k; | 2814 | range->num_frequency = k; |
2815 | range->sensitivity = 3; | ||
2684 | 2816 | ||
2685 | range.sensitivity = 3; | 2817 | if (priv->has_wep) { |
2818 | range->max_encoding_tokens = ORINOCO_MAX_KEYS; | ||
2819 | range->encoding_size[0] = SMALL_KEY_SIZE; | ||
2820 | range->num_encoding_sizes = 1; | ||
2686 | 2821 | ||
2687 | if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ | 2822 | if (priv->has_big_wep) { |
2823 | range->encoding_size[1] = LARGE_KEY_SIZE; | ||
2824 | range->num_encoding_sizes = 2; | ||
2825 | } | ||
2826 | } | ||
2827 | |||
2828 | if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ | ||
2688 | /* Quality stats meaningless in ad-hoc mode */ | 2829 | /* Quality stats meaningless in ad-hoc mode */ |
2689 | range.max_qual.qual = 0; | ||
2690 | range.max_qual.level = 0; | ||
2691 | range.max_qual.noise = 0; | ||
2692 | range.avg_qual.qual = 0; | ||
2693 | range.avg_qual.level = 0; | ||
2694 | range.avg_qual.noise = 0; | ||
2695 | } else { | 2830 | } else { |
2696 | range.max_qual.qual = 0x8b - 0x2f; | 2831 | range->max_qual.qual = 0x8b - 0x2f; |
2697 | range.max_qual.level = 0x2f - 0x95 - 1; | 2832 | range->max_qual.level = 0x2f - 0x95 - 1; |
2698 | range.max_qual.noise = 0x2f - 0x95 - 1; | 2833 | range->max_qual.noise = 0x2f - 0x95 - 1; |
2699 | /* Need to get better values */ | 2834 | /* Need to get better values */ |
2700 | range.avg_qual.qual = 0x24; | 2835 | range->avg_qual.qual = 0x24; |
2701 | range.avg_qual.level = 0xC2; | 2836 | range->avg_qual.level = 0xC2; |
2702 | range.avg_qual.noise = 0x9E; | 2837 | range->avg_qual.noise = 0x9E; |
2703 | } | 2838 | } |
2704 | 2839 | ||
2705 | err = orinoco_hw_get_bitratelist(priv, &numrates, | 2840 | err = orinoco_hw_get_bitratelist(priv, &numrates, |
2706 | range.bitrate, IW_MAX_BITRATES); | 2841 | range->bitrate, IW_MAX_BITRATES); |
2707 | if (err) | 2842 | if (err) |
2708 | return err; | 2843 | return err; |
2709 | range.num_bitrates = numrates; | 2844 | range->num_bitrates = numrates; |
2710 | 2845 | ||
2711 | /* Set an indication of the max TCP throughput in bit/s that we can | 2846 | /* Set an indication of the max TCP throughput in bit/s that we can |
2712 | * expect using this interface. May be use for QoS stuff... | 2847 | * expect using this interface. May be use for QoS stuff... |
2713 | * Jean II */ | 2848 | * Jean II */ |
2714 | if(numrates > 2) | 2849 | if (numrates > 2) |
2715 | range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ | 2850 | range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ |
2716 | else | 2851 | else |
2717 | range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ | 2852 | range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ |
2718 | 2853 | ||
2719 | range.min_rts = 0; | 2854 | range->min_rts = 0; |
2720 | range.max_rts = 2347; | 2855 | range->max_rts = 2347; |
2721 | range.min_frag = 256; | 2856 | range->min_frag = 256; |
2722 | range.max_frag = 2346; | 2857 | range->max_frag = 2346; |
2723 | 2858 | ||
2724 | if (orinoco_lock(priv, &flags) != 0) | 2859 | range->min_pmp = 0; |
2725 | return -EBUSY; | 2860 | range->max_pmp = 65535000; |
2726 | if (priv->has_wep) { | 2861 | range->min_pmt = 0; |
2727 | range.max_encoding_tokens = ORINOCO_MAX_KEYS; | 2862 | range->max_pmt = 65535 * 1000; /* ??? */ |
2728 | 2863 | range->pmp_flags = IW_POWER_PERIOD; | |
2729 | range.encoding_size[0] = SMALL_KEY_SIZE; | 2864 | range->pmt_flags = IW_POWER_TIMEOUT; |
2730 | range.num_encoding_sizes = 1; | 2865 | range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; |
2731 | 2866 | ||
2732 | if (priv->has_big_wep) { | 2867 | range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; |
2733 | range.encoding_size[1] = LARGE_KEY_SIZE; | 2868 | range->retry_flags = IW_RETRY_LIMIT; |
2734 | range.num_encoding_sizes = 2; | 2869 | range->r_time_flags = IW_RETRY_LIFETIME; |
2735 | } | 2870 | range->min_retry = 0; |
2736 | } else { | 2871 | range->max_retry = 65535; /* ??? */ |
2737 | range.num_encoding_sizes = 0; | 2872 | range->min_r_time = 0; |
2738 | range.max_encoding_tokens = 0; | 2873 | range->max_r_time = 65535 * 1000; /* ??? */ |
2739 | } | ||
2740 | orinoco_unlock(priv, &flags); | ||
2741 | |||
2742 | range.min_pmp = 0; | ||
2743 | range.max_pmp = 65535000; | ||
2744 | range.min_pmt = 0; | ||
2745 | range.max_pmt = 65535 * 1000; /* ??? */ | ||
2746 | range.pmp_flags = IW_POWER_PERIOD; | ||
2747 | range.pmt_flags = IW_POWER_TIMEOUT; | ||
2748 | range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; | ||
2749 | |||
2750 | range.num_txpower = 1; | ||
2751 | range.txpower[0] = 15; /* 15dBm */ | ||
2752 | range.txpower_capa = IW_TXPOW_DBM; | ||
2753 | |||
2754 | range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; | ||
2755 | range.retry_flags = IW_RETRY_LIMIT; | ||
2756 | range.r_time_flags = IW_RETRY_LIFETIME; | ||
2757 | range.min_retry = 0; | ||
2758 | range.max_retry = 65535; /* ??? */ | ||
2759 | range.min_r_time = 0; | ||
2760 | range.max_r_time = 65535 * 1000; /* ??? */ | ||
2761 | |||
2762 | if (copy_to_user(rrq->pointer, &range, sizeof(range))) | ||
2763 | return -EFAULT; | ||
2764 | 2874 | ||
2765 | TRACE_EXIT(dev->name); | 2875 | TRACE_EXIT(dev->name); |
2766 | 2876 | ||
2767 | return 0; | 2877 | return 0; |
2768 | } | 2878 | } |
2769 | 2879 | ||
2770 | static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq) | 2880 | static int orinoco_ioctl_setiwencode(struct net_device *dev, |
2881 | struct iw_request_info *info, | ||
2882 | struct iw_point *erq, | ||
2883 | char *keybuf) | ||
2771 | { | 2884 | { |
2772 | struct orinoco_private *priv = netdev_priv(dev); | 2885 | struct orinoco_private *priv = netdev_priv(dev); |
2773 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; | 2886 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; |
@@ -2775,8 +2888,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er | |||
2775 | int enable = priv->wep_on; | 2888 | int enable = priv->wep_on; |
2776 | int restricted = priv->wep_restrict; | 2889 | int restricted = priv->wep_restrict; |
2777 | u16 xlen = 0; | 2890 | u16 xlen = 0; |
2778 | int err = 0; | 2891 | int err = -EINPROGRESS; /* Call commit handler */ |
2779 | char keybuf[ORINOCO_MAX_KEY_SIZE]; | ||
2780 | unsigned long flags; | 2892 | unsigned long flags; |
2781 | 2893 | ||
2782 | if (! priv->has_wep) | 2894 | if (! priv->has_wep) |
@@ -2789,9 +2901,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er | |||
2789 | 2901 | ||
2790 | if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) | 2902 | if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) |
2791 | return -E2BIG; | 2903 | return -E2BIG; |
2792 | |||
2793 | if (copy_from_user(keybuf, erq->pointer, erq->length)) | ||
2794 | return -EFAULT; | ||
2795 | } | 2904 | } |
2796 | 2905 | ||
2797 | if (orinoco_lock(priv, &flags) != 0) | 2906 | if (orinoco_lock(priv, &flags) != 0) |
@@ -2865,12 +2974,14 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er | |||
2865 | return err; | 2974 | return err; |
2866 | } | 2975 | } |
2867 | 2976 | ||
2868 | static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq) | 2977 | static int orinoco_ioctl_getiwencode(struct net_device *dev, |
2978 | struct iw_request_info *info, | ||
2979 | struct iw_point *erq, | ||
2980 | char *keybuf) | ||
2869 | { | 2981 | { |
2870 | struct orinoco_private *priv = netdev_priv(dev); | 2982 | struct orinoco_private *priv = netdev_priv(dev); |
2871 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; | 2983 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; |
2872 | u16 xlen = 0; | 2984 | u16 xlen = 0; |
2873 | char keybuf[ORINOCO_MAX_KEY_SIZE]; | ||
2874 | unsigned long flags; | 2985 | unsigned long flags; |
2875 | 2986 | ||
2876 | if (! priv->has_wep) | 2987 | if (! priv->has_wep) |
@@ -2899,51 +3010,47 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er | |||
2899 | memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); | 3010 | memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); |
2900 | 3011 | ||
2901 | orinoco_unlock(priv, &flags); | 3012 | orinoco_unlock(priv, &flags); |
2902 | |||
2903 | if (erq->pointer) { | ||
2904 | if (copy_to_user(erq->pointer, keybuf, xlen)) | ||
2905 | return -EFAULT; | ||
2906 | } | ||
2907 | |||
2908 | return 0; | 3013 | return 0; |
2909 | } | 3014 | } |
2910 | 3015 | ||
2911 | static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq) | 3016 | static int orinoco_ioctl_setessid(struct net_device *dev, |
3017 | struct iw_request_info *info, | ||
3018 | struct iw_point *erq, | ||
3019 | char *essidbuf) | ||
2912 | { | 3020 | { |
2913 | struct orinoco_private *priv = netdev_priv(dev); | 3021 | struct orinoco_private *priv = netdev_priv(dev); |
2914 | char essidbuf[IW_ESSID_MAX_SIZE+1]; | ||
2915 | unsigned long flags; | 3022 | unsigned long flags; |
2916 | 3023 | ||
2917 | /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it | 3024 | /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it |
2918 | * anyway... - Jean II */ | 3025 | * anyway... - Jean II */ |
2919 | 3026 | ||
2920 | memset(&essidbuf, 0, sizeof(essidbuf)); | 3027 | /* Hum... Should not use Wireless Extension constant (may change), |
2921 | 3028 | * should use our own... - Jean II */ | |
2922 | if (erq->flags) { | 3029 | if (erq->length > IW_ESSID_MAX_SIZE) |
2923 | /* iwconfig includes the NUL in the specified length */ | 3030 | return -E2BIG; |
2924 | if (erq->length > IW_ESSID_MAX_SIZE+1) | ||
2925 | return -E2BIG; | ||
2926 | |||
2927 | if (copy_from_user(&essidbuf, erq->pointer, erq->length)) | ||
2928 | return -EFAULT; | ||
2929 | |||
2930 | essidbuf[IW_ESSID_MAX_SIZE] = '\0'; | ||
2931 | } | ||
2932 | 3031 | ||
2933 | if (orinoco_lock(priv, &flags) != 0) | 3032 | if (orinoco_lock(priv, &flags) != 0) |
2934 | return -EBUSY; | 3033 | return -EBUSY; |
2935 | 3034 | ||
2936 | memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid)); | 3035 | /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */ |
3036 | memset(priv->desired_essid, 0, sizeof(priv->desired_essid)); | ||
3037 | |||
3038 | /* If not ANY, get the new ESSID */ | ||
3039 | if (erq->flags) { | ||
3040 | memcpy(priv->desired_essid, essidbuf, erq->length); | ||
3041 | } | ||
2937 | 3042 | ||
2938 | orinoco_unlock(priv, &flags); | 3043 | orinoco_unlock(priv, &flags); |
2939 | 3044 | ||
2940 | return 0; | 3045 | return -EINPROGRESS; /* Call commit handler */ |
2941 | } | 3046 | } |
2942 | 3047 | ||
2943 | static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) | 3048 | static int orinoco_ioctl_getessid(struct net_device *dev, |
3049 | struct iw_request_info *info, | ||
3050 | struct iw_point *erq, | ||
3051 | char *essidbuf) | ||
2944 | { | 3052 | { |
2945 | struct orinoco_private *priv = netdev_priv(dev); | 3053 | struct orinoco_private *priv = netdev_priv(dev); |
2946 | char essidbuf[IW_ESSID_MAX_SIZE+1]; | ||
2947 | int active; | 3054 | int active; |
2948 | int err = 0; | 3055 | int err = 0; |
2949 | unsigned long flags; | 3056 | unsigned long flags; |
@@ -2957,51 +3064,46 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) | |||
2957 | } else { | 3064 | } else { |
2958 | if (orinoco_lock(priv, &flags) != 0) | 3065 | if (orinoco_lock(priv, &flags) != 0) |
2959 | return -EBUSY; | 3066 | return -EBUSY; |
2960 | memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf)); | 3067 | memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1); |
2961 | orinoco_unlock(priv, &flags); | 3068 | orinoco_unlock(priv, &flags); |
2962 | } | 3069 | } |
2963 | 3070 | ||
2964 | erq->flags = 1; | 3071 | erq->flags = 1; |
2965 | erq->length = strlen(essidbuf) + 1; | 3072 | erq->length = strlen(essidbuf) + 1; |
2966 | if (erq->pointer) | ||
2967 | if (copy_to_user(erq->pointer, essidbuf, erq->length)) | ||
2968 | return -EFAULT; | ||
2969 | 3073 | ||
2970 | TRACE_EXIT(dev->name); | 3074 | TRACE_EXIT(dev->name); |
2971 | 3075 | ||
2972 | return 0; | 3076 | return 0; |
2973 | } | 3077 | } |
2974 | 3078 | ||
2975 | static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq) | 3079 | static int orinoco_ioctl_setnick(struct net_device *dev, |
3080 | struct iw_request_info *info, | ||
3081 | struct iw_point *nrq, | ||
3082 | char *nickbuf) | ||
2976 | { | 3083 | { |
2977 | struct orinoco_private *priv = netdev_priv(dev); | 3084 | struct orinoco_private *priv = netdev_priv(dev); |
2978 | char nickbuf[IW_ESSID_MAX_SIZE+1]; | ||
2979 | unsigned long flags; | 3085 | unsigned long flags; |
2980 | 3086 | ||
2981 | if (nrq->length > IW_ESSID_MAX_SIZE) | 3087 | if (nrq->length > IW_ESSID_MAX_SIZE) |
2982 | return -E2BIG; | 3088 | return -E2BIG; |
2983 | 3089 | ||
2984 | memset(nickbuf, 0, sizeof(nickbuf)); | ||
2985 | |||
2986 | if (copy_from_user(nickbuf, nrq->pointer, nrq->length)) | ||
2987 | return -EFAULT; | ||
2988 | |||
2989 | nickbuf[nrq->length] = '\0'; | ||
2990 | |||
2991 | if (orinoco_lock(priv, &flags) != 0) | 3090 | if (orinoco_lock(priv, &flags) != 0) |
2992 | return -EBUSY; | 3091 | return -EBUSY; |
2993 | 3092 | ||
2994 | memcpy(priv->nick, nickbuf, sizeof(priv->nick)); | 3093 | memset(priv->nick, 0, sizeof(priv->nick)); |
3094 | memcpy(priv->nick, nickbuf, nrq->length); | ||
2995 | 3095 | ||
2996 | orinoco_unlock(priv, &flags); | 3096 | orinoco_unlock(priv, &flags); |
2997 | 3097 | ||
2998 | return 0; | 3098 | return -EINPROGRESS; /* Call commit handler */ |
2999 | } | 3099 | } |
3000 | 3100 | ||
3001 | static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) | 3101 | static int orinoco_ioctl_getnick(struct net_device *dev, |
3102 | struct iw_request_info *info, | ||
3103 | struct iw_point *nrq, | ||
3104 | char *nickbuf) | ||
3002 | { | 3105 | { |
3003 | struct orinoco_private *priv = netdev_priv(dev); | 3106 | struct orinoco_private *priv = netdev_priv(dev); |
3004 | char nickbuf[IW_ESSID_MAX_SIZE+1]; | ||
3005 | unsigned long flags; | 3107 | unsigned long flags; |
3006 | 3108 | ||
3007 | if (orinoco_lock(priv, &flags) != 0) | 3109 | if (orinoco_lock(priv, &flags) != 0) |
@@ -3012,23 +3114,22 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) | |||
3012 | 3114 | ||
3013 | nrq->length = strlen(nickbuf)+1; | 3115 | nrq->length = strlen(nickbuf)+1; |
3014 | 3116 | ||
3015 | if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf))) | ||
3016 | return -EFAULT; | ||
3017 | |||
3018 | return 0; | 3117 | return 0; |
3019 | } | 3118 | } |
3020 | 3119 | ||
3021 | static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) | 3120 | static int orinoco_ioctl_setfreq(struct net_device *dev, |
3121 | struct iw_request_info *info, | ||
3122 | struct iw_freq *frq, | ||
3123 | char *extra) | ||
3022 | { | 3124 | { |
3023 | struct orinoco_private *priv = netdev_priv(dev); | 3125 | struct orinoco_private *priv = netdev_priv(dev); |
3024 | int chan = -1; | 3126 | int chan = -1; |
3025 | unsigned long flags; | 3127 | unsigned long flags; |
3128 | int err = -EINPROGRESS; /* Call commit handler */ | ||
3026 | 3129 | ||
3027 | /* We can only use this in Ad-Hoc demo mode to set the operating | 3130 | /* In infrastructure mode the AP sets the channel */ |
3028 | * frequency, or in IBSS mode to set the frequency where the IBSS | 3131 | if (priv->iw_mode == IW_MODE_INFRA) |
3029 | * will be created - Jean II */ | 3132 | return -EBUSY; |
3030 | if (priv->iw_mode != IW_MODE_ADHOC) | ||
3031 | return -EOPNOTSUPP; | ||
3032 | 3133 | ||
3033 | if ( (frq->e == 0) && (frq->m <= 1000) ) { | 3134 | if ( (frq->e == 0) && (frq->m <= 1000) ) { |
3034 | /* Setting by channel number */ | 3135 | /* Setting by channel number */ |
@@ -3052,13 +3153,44 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) | |||
3052 | 3153 | ||
3053 | if (orinoco_lock(priv, &flags) != 0) | 3154 | if (orinoco_lock(priv, &flags) != 0) |
3054 | return -EBUSY; | 3155 | return -EBUSY; |
3156 | |||
3055 | priv->channel = chan; | 3157 | priv->channel = chan; |
3158 | if (priv->iw_mode == IW_MODE_MONITOR) { | ||
3159 | /* Fast channel change - no commit if successful */ | ||
3160 | hermes_t *hw = &priv->hw; | ||
3161 | err = hermes_docmd_wait(hw, HERMES_CMD_TEST | | ||
3162 | HERMES_TEST_SET_CHANNEL, | ||
3163 | chan, NULL); | ||
3164 | } | ||
3056 | orinoco_unlock(priv, &flags); | 3165 | orinoco_unlock(priv, &flags); |
3057 | 3166 | ||
3167 | return err; | ||
3168 | } | ||
3169 | |||
3170 | static int orinoco_ioctl_getfreq(struct net_device *dev, | ||
3171 | struct iw_request_info *info, | ||
3172 | struct iw_freq *frq, | ||
3173 | char *extra) | ||
3174 | { | ||
3175 | struct orinoco_private *priv = netdev_priv(dev); | ||
3176 | int tmp; | ||
3177 | |||
3178 | /* Locking done in there */ | ||
3179 | tmp = orinoco_hw_get_freq(priv); | ||
3180 | if (tmp < 0) { | ||
3181 | return tmp; | ||
3182 | } | ||
3183 | |||
3184 | frq->m = tmp; | ||
3185 | frq->e = 1; | ||
3186 | |||
3058 | return 0; | 3187 | return 0; |
3059 | } | 3188 | } |
3060 | 3189 | ||
3061 | static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) | 3190 | static int orinoco_ioctl_getsens(struct net_device *dev, |
3191 | struct iw_request_info *info, | ||
3192 | struct iw_param *srq, | ||
3193 | char *extra) | ||
3062 | { | 3194 | { |
3063 | struct orinoco_private *priv = netdev_priv(dev); | 3195 | struct orinoco_private *priv = netdev_priv(dev); |
3064 | hermes_t *hw = &priv->hw; | 3196 | hermes_t *hw = &priv->hw; |
@@ -3084,7 +3216,10 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) | |||
3084 | return 0; | 3216 | return 0; |
3085 | } | 3217 | } |
3086 | 3218 | ||
3087 | static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) | 3219 | static int orinoco_ioctl_setsens(struct net_device *dev, |
3220 | struct iw_request_info *info, | ||
3221 | struct iw_param *srq, | ||
3222 | char *extra) | ||
3088 | { | 3223 | { |
3089 | struct orinoco_private *priv = netdev_priv(dev); | 3224 | struct orinoco_private *priv = netdev_priv(dev); |
3090 | int val = srq->value; | 3225 | int val = srq->value; |
@@ -3101,10 +3236,13 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) | |||
3101 | priv->ap_density = val; | 3236 | priv->ap_density = val; |
3102 | orinoco_unlock(priv, &flags); | 3237 | orinoco_unlock(priv, &flags); |
3103 | 3238 | ||
3104 | return 0; | 3239 | return -EINPROGRESS; /* Call commit handler */ |
3105 | } | 3240 | } |
3106 | 3241 | ||
3107 | static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) | 3242 | static int orinoco_ioctl_setrts(struct net_device *dev, |
3243 | struct iw_request_info *info, | ||
3244 | struct iw_param *rrq, | ||
3245 | char *extra) | ||
3108 | { | 3246 | { |
3109 | struct orinoco_private *priv = netdev_priv(dev); | 3247 | struct orinoco_private *priv = netdev_priv(dev); |
3110 | int val = rrq->value; | 3248 | int val = rrq->value; |
@@ -3122,13 +3260,30 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) | |||
3122 | priv->rts_thresh = val; | 3260 | priv->rts_thresh = val; |
3123 | orinoco_unlock(priv, &flags); | 3261 | orinoco_unlock(priv, &flags); |
3124 | 3262 | ||
3263 | return -EINPROGRESS; /* Call commit handler */ | ||
3264 | } | ||
3265 | |||
3266 | static int orinoco_ioctl_getrts(struct net_device *dev, | ||
3267 | struct iw_request_info *info, | ||
3268 | struct iw_param *rrq, | ||
3269 | char *extra) | ||
3270 | { | ||
3271 | struct orinoco_private *priv = netdev_priv(dev); | ||
3272 | |||
3273 | rrq->value = priv->rts_thresh; | ||
3274 | rrq->disabled = (rrq->value == 2347); | ||
3275 | rrq->fixed = 1; | ||
3276 | |||
3125 | return 0; | 3277 | return 0; |
3126 | } | 3278 | } |
3127 | 3279 | ||
3128 | static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) | 3280 | static int orinoco_ioctl_setfrag(struct net_device *dev, |
3281 | struct iw_request_info *info, | ||
3282 | struct iw_param *frq, | ||
3283 | char *extra) | ||
3129 | { | 3284 | { |
3130 | struct orinoco_private *priv = netdev_priv(dev); | 3285 | struct orinoco_private *priv = netdev_priv(dev); |
3131 | int err = 0; | 3286 | int err = -EINPROGRESS; /* Call commit handler */ |
3132 | unsigned long flags; | 3287 | unsigned long flags; |
3133 | 3288 | ||
3134 | if (orinoco_lock(priv, &flags) != 0) | 3289 | if (orinoco_lock(priv, &flags) != 0) |
@@ -3160,11 +3315,14 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) | |||
3160 | return err; | 3315 | return err; |
3161 | } | 3316 | } |
3162 | 3317 | ||
3163 | static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) | 3318 | static int orinoco_ioctl_getfrag(struct net_device *dev, |
3319 | struct iw_request_info *info, | ||
3320 | struct iw_param *frq, | ||
3321 | char *extra) | ||
3164 | { | 3322 | { |
3165 | struct orinoco_private *priv = netdev_priv(dev); | 3323 | struct orinoco_private *priv = netdev_priv(dev); |
3166 | hermes_t *hw = &priv->hw; | 3324 | hermes_t *hw = &priv->hw; |
3167 | int err = 0; | 3325 | int err; |
3168 | u16 val; | 3326 | u16 val; |
3169 | unsigned long flags; | 3327 | unsigned long flags; |
3170 | 3328 | ||
@@ -3197,10 +3355,12 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) | |||
3197 | return err; | 3355 | return err; |
3198 | } | 3356 | } |
3199 | 3357 | ||
3200 | static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) | 3358 | static int orinoco_ioctl_setrate(struct net_device *dev, |
3359 | struct iw_request_info *info, | ||
3360 | struct iw_param *rrq, | ||
3361 | char *extra) | ||
3201 | { | 3362 | { |
3202 | struct orinoco_private *priv = netdev_priv(dev); | 3363 | struct orinoco_private *priv = netdev_priv(dev); |
3203 | int err = 0; | ||
3204 | int ratemode = -1; | 3364 | int ratemode = -1; |
3205 | int bitrate; /* 100s of kilobits */ | 3365 | int bitrate; /* 100s of kilobits */ |
3206 | int i; | 3366 | int i; |
@@ -3236,10 +3396,13 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) | |||
3236 | priv->bitratemode = ratemode; | 3396 | priv->bitratemode = ratemode; |
3237 | orinoco_unlock(priv, &flags); | 3397 | orinoco_unlock(priv, &flags); |
3238 | 3398 | ||
3239 | return err; | 3399 | return -EINPROGRESS; |
3240 | } | 3400 | } |
3241 | 3401 | ||
3242 | static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) | 3402 | static int orinoco_ioctl_getrate(struct net_device *dev, |
3403 | struct iw_request_info *info, | ||
3404 | struct iw_param *rrq, | ||
3405 | char *extra) | ||
3243 | { | 3406 | { |
3244 | struct orinoco_private *priv = netdev_priv(dev); | 3407 | struct orinoco_private *priv = netdev_priv(dev); |
3245 | hermes_t *hw = &priv->hw; | 3408 | hermes_t *hw = &priv->hw; |
@@ -3304,10 +3467,13 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) | |||
3304 | return err; | 3467 | return err; |
3305 | } | 3468 | } |
3306 | 3469 | ||
3307 | static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) | 3470 | static int orinoco_ioctl_setpower(struct net_device *dev, |
3471 | struct iw_request_info *info, | ||
3472 | struct iw_param *prq, | ||
3473 | char *extra) | ||
3308 | { | 3474 | { |
3309 | struct orinoco_private *priv = netdev_priv(dev); | 3475 | struct orinoco_private *priv = netdev_priv(dev); |
3310 | int err = 0; | 3476 | int err = -EINPROGRESS; /* Call commit handler */ |
3311 | unsigned long flags; | 3477 | unsigned long flags; |
3312 | 3478 | ||
3313 | if (orinoco_lock(priv, &flags) != 0) | 3479 | if (orinoco_lock(priv, &flags) != 0) |
@@ -3356,7 +3522,10 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) | |||
3356 | return err; | 3522 | return err; |
3357 | } | 3523 | } |
3358 | 3524 | ||
3359 | static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) | 3525 | static int orinoco_ioctl_getpower(struct net_device *dev, |
3526 | struct iw_request_info *info, | ||
3527 | struct iw_param *prq, | ||
3528 | char *extra) | ||
3360 | { | 3529 | { |
3361 | struct orinoco_private *priv = netdev_priv(dev); | 3530 | struct orinoco_private *priv = netdev_priv(dev); |
3362 | hermes_t *hw = &priv->hw; | 3531 | hermes_t *hw = &priv->hw; |
@@ -3404,7 +3573,10 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) | |||
3404 | return err; | 3573 | return err; |
3405 | } | 3574 | } |
3406 | 3575 | ||
3407 | static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) | 3576 | static int orinoco_ioctl_getretry(struct net_device *dev, |
3577 | struct iw_request_info *info, | ||
3578 | struct iw_param *rrq, | ||
3579 | char *extra) | ||
3408 | { | 3580 | { |
3409 | struct orinoco_private *priv = netdev_priv(dev); | 3581 | struct orinoco_private *priv = netdev_priv(dev); |
3410 | hermes_t *hw = &priv->hw; | 3582 | hermes_t *hw = &priv->hw; |
@@ -3455,10 +3627,38 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) | |||
3455 | return err; | 3627 | return err; |
3456 | } | 3628 | } |
3457 | 3629 | ||
3458 | static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) | 3630 | static int orinoco_ioctl_reset(struct net_device *dev, |
3631 | struct iw_request_info *info, | ||
3632 | void *wrqu, | ||
3633 | char *extra) | ||
3459 | { | 3634 | { |
3460 | struct orinoco_private *priv = netdev_priv(dev); | 3635 | struct orinoco_private *priv = netdev_priv(dev); |
3461 | int val = *( (int *) wrq->u.name ); | 3636 | |
3637 | if (! capable(CAP_NET_ADMIN)) | ||
3638 | return -EPERM; | ||
3639 | |||
3640 | if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) { | ||
3641 | printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); | ||
3642 | |||
3643 | /* Firmware reset */ | ||
3644 | orinoco_reset(dev); | ||
3645 | } else { | ||
3646 | printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); | ||
3647 | |||
3648 | schedule_work(&priv->reset_work); | ||
3649 | } | ||
3650 | |||
3651 | return 0; | ||
3652 | } | ||
3653 | |||
3654 | static int orinoco_ioctl_setibssport(struct net_device *dev, | ||
3655 | struct iw_request_info *info, | ||
3656 | void *wrqu, | ||
3657 | char *extra) | ||
3658 | |||
3659 | { | ||
3660 | struct orinoco_private *priv = netdev_priv(dev); | ||
3661 | int val = *( (int *) extra ); | ||
3462 | unsigned long flags; | 3662 | unsigned long flags; |
3463 | 3663 | ||
3464 | if (orinoco_lock(priv, &flags) != 0) | 3664 | if (orinoco_lock(priv, &flags) != 0) |
@@ -3470,28 +3670,28 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) | |||
3470 | set_port_type(priv); | 3670 | set_port_type(priv); |
3471 | 3671 | ||
3472 | orinoco_unlock(priv, &flags); | 3672 | orinoco_unlock(priv, &flags); |
3473 | return 0; | 3673 | return -EINPROGRESS; /* Call commit handler */ |
3474 | } | 3674 | } |
3475 | 3675 | ||
3476 | static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq) | 3676 | static int orinoco_ioctl_getibssport(struct net_device *dev, |
3677 | struct iw_request_info *info, | ||
3678 | void *wrqu, | ||
3679 | char *extra) | ||
3477 | { | 3680 | { |
3478 | struct orinoco_private *priv = netdev_priv(dev); | 3681 | struct orinoco_private *priv = netdev_priv(dev); |
3479 | int *val = (int *)wrq->u.name; | 3682 | int *val = (int *) extra; |
3480 | unsigned long flags; | ||
3481 | |||
3482 | if (orinoco_lock(priv, &flags) != 0) | ||
3483 | return -EBUSY; | ||
3484 | 3683 | ||
3485 | *val = priv->ibss_port; | 3684 | *val = priv->ibss_port; |
3486 | orinoco_unlock(priv, &flags); | ||
3487 | |||
3488 | return 0; | 3685 | return 0; |
3489 | } | 3686 | } |
3490 | 3687 | ||
3491 | static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) | 3688 | static int orinoco_ioctl_setport3(struct net_device *dev, |
3689 | struct iw_request_info *info, | ||
3690 | void *wrqu, | ||
3691 | char *extra) | ||
3492 | { | 3692 | { |
3493 | struct orinoco_private *priv = netdev_priv(dev); | 3693 | struct orinoco_private *priv = netdev_priv(dev); |
3494 | int val = *( (int *) wrq->u.name ); | 3694 | int val = *( (int *) extra ); |
3495 | int err = 0; | 3695 | int err = 0; |
3496 | unsigned long flags; | 3696 | unsigned long flags; |
3497 | 3697 | ||
@@ -3520,51 +3720,131 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) | |||
3520 | err = -EINVAL; | 3720 | err = -EINVAL; |
3521 | } | 3721 | } |
3522 | 3722 | ||
3523 | if (! err) | 3723 | if (! err) { |
3524 | /* Actually update the mode we are using */ | 3724 | /* Actually update the mode we are using */ |
3525 | set_port_type(priv); | 3725 | set_port_type(priv); |
3726 | err = -EINPROGRESS; | ||
3727 | } | ||
3526 | 3728 | ||
3527 | orinoco_unlock(priv, &flags); | 3729 | orinoco_unlock(priv, &flags); |
3528 | 3730 | ||
3529 | return err; | 3731 | return err; |
3530 | } | 3732 | } |
3531 | 3733 | ||
3532 | static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq) | 3734 | static int orinoco_ioctl_getport3(struct net_device *dev, |
3735 | struct iw_request_info *info, | ||
3736 | void *wrqu, | ||
3737 | char *extra) | ||
3738 | { | ||
3739 | struct orinoco_private *priv = netdev_priv(dev); | ||
3740 | int *val = (int *) extra; | ||
3741 | |||
3742 | *val = priv->prefer_port3; | ||
3743 | return 0; | ||
3744 | } | ||
3745 | |||
3746 | static int orinoco_ioctl_setpreamble(struct net_device *dev, | ||
3747 | struct iw_request_info *info, | ||
3748 | void *wrqu, | ||
3749 | char *extra) | ||
3533 | { | 3750 | { |
3534 | struct orinoco_private *priv = netdev_priv(dev); | 3751 | struct orinoco_private *priv = netdev_priv(dev); |
3535 | int *val = (int *)wrq->u.name; | ||
3536 | unsigned long flags; | 3752 | unsigned long flags; |
3753 | int val; | ||
3754 | |||
3755 | if (! priv->has_preamble) | ||
3756 | return -EOPNOTSUPP; | ||
3757 | |||
3758 | /* 802.11b has recently defined some short preamble. | ||
3759 | * Basically, the Phy header has been reduced in size. | ||
3760 | * This increase performance, especially at high rates | ||
3761 | * (the preamble is transmitted at 1Mb/s), unfortunately | ||
3762 | * this give compatibility troubles... - Jean II */ | ||
3763 | val = *( (int *) extra ); | ||
3537 | 3764 | ||
3538 | if (orinoco_lock(priv, &flags) != 0) | 3765 | if (orinoco_lock(priv, &flags) != 0) |
3539 | return -EBUSY; | 3766 | return -EBUSY; |
3540 | 3767 | ||
3541 | *val = priv->prefer_port3; | 3768 | if (val) |
3769 | priv->preamble = 1; | ||
3770 | else | ||
3771 | priv->preamble = 0; | ||
3772 | |||
3542 | orinoco_unlock(priv, &flags); | 3773 | orinoco_unlock(priv, &flags); |
3774 | |||
3775 | return -EINPROGRESS; /* Call commit handler */ | ||
3776 | } | ||
3777 | |||
3778 | static int orinoco_ioctl_getpreamble(struct net_device *dev, | ||
3779 | struct iw_request_info *info, | ||
3780 | void *wrqu, | ||
3781 | char *extra) | ||
3782 | { | ||
3783 | struct orinoco_private *priv = netdev_priv(dev); | ||
3784 | int *val = (int *) extra; | ||
3785 | |||
3786 | if (! priv->has_preamble) | ||
3787 | return -EOPNOTSUPP; | ||
3788 | |||
3789 | *val = priv->preamble; | ||
3543 | return 0; | 3790 | return 0; |
3544 | } | 3791 | } |
3545 | 3792 | ||
3793 | /* ioctl interface to hermes_read_ltv() | ||
3794 | * To use with iwpriv, pass the RID as the token argument, e.g. | ||
3795 | * iwpriv get_rid [0xfc00] | ||
3796 | * At least Wireless Tools 25 is required to use iwpriv. | ||
3797 | * For Wireless Tools 25 and 26 append "dummy" are the end. */ | ||
3798 | static int orinoco_ioctl_getrid(struct net_device *dev, | ||
3799 | struct iw_request_info *info, | ||
3800 | struct iw_point *data, | ||
3801 | char *extra) | ||
3802 | { | ||
3803 | struct orinoco_private *priv = netdev_priv(dev); | ||
3804 | hermes_t *hw = &priv->hw; | ||
3805 | int rid = data->flags; | ||
3806 | u16 length; | ||
3807 | int err; | ||
3808 | unsigned long flags; | ||
3809 | |||
3810 | /* It's a "get" function, but we don't want users to access the | ||
3811 | * WEP key and other raw firmware data */ | ||
3812 | if (! capable(CAP_NET_ADMIN)) | ||
3813 | return -EPERM; | ||
3814 | |||
3815 | if (rid < 0xfc00 || rid > 0xffff) | ||
3816 | return -EINVAL; | ||
3817 | |||
3818 | if (orinoco_lock(priv, &flags) != 0) | ||
3819 | return -EBUSY; | ||
3820 | |||
3821 | err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, | ||
3822 | extra); | ||
3823 | if (err) | ||
3824 | goto out; | ||
3825 | |||
3826 | data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length), | ||
3827 | MAX_RID_LEN); | ||
3828 | |||
3829 | out: | ||
3830 | orinoco_unlock(priv, &flags); | ||
3831 | return err; | ||
3832 | } | ||
3833 | |||
3546 | /* Spy is used for link quality/strength measurements in Ad-Hoc mode | 3834 | /* Spy is used for link quality/strength measurements in Ad-Hoc mode |
3547 | * Jean II */ | 3835 | * Jean II */ |
3548 | static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) | 3836 | static int orinoco_ioctl_setspy(struct net_device *dev, |
3837 | struct iw_request_info *info, | ||
3838 | struct iw_point *srq, | ||
3839 | char *extra) | ||
3840 | |||
3549 | { | 3841 | { |
3550 | struct orinoco_private *priv = netdev_priv(dev); | 3842 | struct orinoco_private *priv = netdev_priv(dev); |
3551 | struct sockaddr address[IW_MAX_SPY]; | 3843 | struct sockaddr *address = (struct sockaddr *) extra; |
3552 | int number = srq->length; | 3844 | int number = srq->length; |
3553 | int i; | 3845 | int i; |
3554 | int err = 0; | ||
3555 | unsigned long flags; | 3846 | unsigned long flags; |
3556 | 3847 | ||
3557 | /* Check the number of addresses */ | ||
3558 | if (number > IW_MAX_SPY) | ||
3559 | return -E2BIG; | ||
3560 | |||
3561 | /* Get the data in the driver */ | ||
3562 | if (srq->pointer) { | ||
3563 | if (copy_from_user(address, srq->pointer, | ||
3564 | sizeof(struct sockaddr) * number)) | ||
3565 | return -EFAULT; | ||
3566 | } | ||
3567 | |||
3568 | /* Make sure nobody mess with the structure while we do */ | 3848 | /* Make sure nobody mess with the structure while we do */ |
3569 | if (orinoco_lock(priv, &flags) != 0) | 3849 | if (orinoco_lock(priv, &flags) != 0) |
3570 | return -EBUSY; | 3850 | return -EBUSY; |
@@ -3588,14 +3868,17 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) | |||
3588 | /* Now, let the others play */ | 3868 | /* Now, let the others play */ |
3589 | orinoco_unlock(priv, &flags); | 3869 | orinoco_unlock(priv, &flags); |
3590 | 3870 | ||
3591 | return err; | 3871 | /* Do NOT call commit handler */ |
3872 | return 0; | ||
3592 | } | 3873 | } |
3593 | 3874 | ||
3594 | static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) | 3875 | static int orinoco_ioctl_getspy(struct net_device *dev, |
3876 | struct iw_request_info *info, | ||
3877 | struct iw_point *srq, | ||
3878 | char *extra) | ||
3595 | { | 3879 | { |
3596 | struct orinoco_private *priv = netdev_priv(dev); | 3880 | struct orinoco_private *priv = netdev_priv(dev); |
3597 | struct sockaddr address[IW_MAX_SPY]; | 3881 | struct sockaddr *address = (struct sockaddr *) extra; |
3598 | struct iw_quality spy_stat[IW_MAX_SPY]; | ||
3599 | int number; | 3882 | int number; |
3600 | int i; | 3883 | int i; |
3601 | unsigned long flags; | 3884 | unsigned long flags; |
@@ -3604,7 +3887,12 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) | |||
3604 | return -EBUSY; | 3887 | return -EBUSY; |
3605 | 3888 | ||
3606 | number = priv->spy_number; | 3889 | number = priv->spy_number; |
3607 | if ((number > 0) && (srq->pointer)) { | 3890 | /* Create address struct */ |
3891 | for (i = 0; i < number; i++) { | ||
3892 | memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN); | ||
3893 | address[i].sa_family = AF_UNIX; | ||
3894 | } | ||
3895 | if (number > 0) { | ||
3608 | /* Create address struct */ | 3896 | /* Create address struct */ |
3609 | for (i = 0; i < number; i++) { | 3897 | for (i = 0; i < number; i++) { |
3610 | memcpy(address[i].sa_data, priv->spy_address[i], | 3898 | memcpy(address[i].sa_data, priv->spy_address[i], |
@@ -3615,344 +3903,503 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) | |||
3615 | /* In theory, we should disable irqs while copying the stats | 3903 | /* In theory, we should disable irqs while copying the stats |
3616 | * because the rx path might update it in the middle... | 3904 | * because the rx path might update it in the middle... |
3617 | * Bah, who care ? - Jean II */ | 3905 | * Bah, who care ? - Jean II */ |
3618 | memcpy(&spy_stat, priv->spy_stat, | 3906 | memcpy(extra + (sizeof(struct sockaddr) * number), |
3619 | sizeof(struct iw_quality) * IW_MAX_SPY); | 3907 | priv->spy_stat, sizeof(struct iw_quality) * number); |
3620 | for (i=0; i < number; i++) | ||
3621 | priv->spy_stat[i].updated = 0; | ||
3622 | } | 3908 | } |
3909 | /* Reset updated flags. */ | ||
3910 | for (i = 0; i < number; i++) | ||
3911 | priv->spy_stat[i].updated = 0; | ||
3623 | 3912 | ||
3624 | orinoco_unlock(priv, &flags); | 3913 | orinoco_unlock(priv, &flags); |
3625 | 3914 | ||
3626 | /* Push stuff to user space */ | ||
3627 | srq->length = number; | 3915 | srq->length = number; |
3628 | if(copy_to_user(srq->pointer, address, | ||
3629 | sizeof(struct sockaddr) * number)) | ||
3630 | return -EFAULT; | ||
3631 | if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number), | ||
3632 | &spy_stat, sizeof(struct iw_quality) * number)) | ||
3633 | return -EFAULT; | ||
3634 | 3916 | ||
3635 | return 0; | 3917 | return 0; |
3636 | } | 3918 | } |
3637 | 3919 | ||
3638 | static int | 3920 | /* Trigger a scan (look for other cells in the vicinity */ |
3639 | orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 3921 | static int orinoco_ioctl_setscan(struct net_device *dev, |
3922 | struct iw_request_info *info, | ||
3923 | struct iw_param *srq, | ||
3924 | char *extra) | ||
3640 | { | 3925 | { |
3641 | struct orinoco_private *priv = netdev_priv(dev); | 3926 | struct orinoco_private *priv = netdev_priv(dev); |
3642 | struct iwreq *wrq = (struct iwreq *)rq; | 3927 | hermes_t *hw = &priv->hw; |
3643 | int err = 0; | 3928 | int err = 0; |
3644 | int tmp; | ||
3645 | int changed = 0; | ||
3646 | unsigned long flags; | 3929 | unsigned long flags; |
3647 | 3930 | ||
3648 | TRACE_ENTER(dev->name); | 3931 | /* Note : you may have realised that, as this is a SET operation, |
3932 | * this is priviledged and therefore a normal user can't | ||
3933 | * perform scanning. | ||
3934 | * This is not an error, while the device perform scanning, | ||
3935 | * traffic doesn't flow, so it's a perfect DoS... | ||
3936 | * Jean II */ | ||
3649 | 3937 | ||
3650 | /* In theory, we could allow most of the the SET stuff to be | 3938 | if (orinoco_lock(priv, &flags) != 0) |
3651 | * done. In practice, the lapse of time at startup when the | 3939 | return -EBUSY; |
3652 | * card is not ready is very short, so why bother... Note | ||
3653 | * that netif_device_present is different from up/down | ||
3654 | * (ifconfig), when the device is not yet up, it is usually | ||
3655 | * already ready... Jean II */ | ||
3656 | if (! netif_device_present(dev)) | ||
3657 | return -ENODEV; | ||
3658 | 3940 | ||
3659 | switch (cmd) { | 3941 | /* Scanning with port 0 disabled would fail */ |
3660 | case SIOCGIWNAME: | 3942 | if (!netif_running(dev)) { |
3661 | strcpy(wrq->u.name, "IEEE 802.11-DS"); | 3943 | err = -ENETDOWN; |
3662 | break; | 3944 | goto out; |
3663 | 3945 | } | |
3664 | case SIOCGIWAP: | ||
3665 | wrq->u.ap_addr.sa_family = ARPHRD_ETHER; | ||
3666 | err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data); | ||
3667 | break; | ||
3668 | 3946 | ||
3669 | case SIOCGIWRANGE: | 3947 | /* In monitor mode, the scan results are always empty. |
3670 | err = orinoco_ioctl_getiwrange(dev, &wrq->u.data); | 3948 | * Probe responses are passed to the driver as received |
3671 | break; | 3949 | * frames and could be processed in software. */ |
3950 | if (priv->iw_mode == IW_MODE_MONITOR) { | ||
3951 | err = -EOPNOTSUPP; | ||
3952 | goto out; | ||
3953 | } | ||
3672 | 3954 | ||
3673 | case SIOCSIWMODE: | 3955 | /* Note : because we don't lock out the irq handler, the way |
3674 | if (orinoco_lock(priv, &flags) != 0) | 3956 | * we access scan variables in priv is critical. |
3675 | return -EBUSY; | 3957 | * o scan_inprogress : not touched by irq handler |
3676 | switch (wrq->u.mode) { | 3958 | * o scan_mode : not touched by irq handler |
3677 | case IW_MODE_ADHOC: | 3959 | * o scan_result : irq is strict producer, non-irq is strict |
3678 | if (! (priv->has_ibss || priv->has_port3) ) | 3960 | * consumer. |
3679 | err = -EINVAL; | 3961 | * o scan_len : synchronised with scan_result |
3680 | else { | 3962 | * Before modifying anything on those variables, please think hard ! |
3681 | priv->iw_mode = IW_MODE_ADHOC; | 3963 | * Jean II */ |
3682 | changed = 1; | ||
3683 | } | ||
3684 | break; | ||
3685 | 3964 | ||
3686 | case IW_MODE_INFRA: | 3965 | /* If there is still some left-over scan results, get rid of it */ |
3687 | priv->iw_mode = IW_MODE_INFRA; | 3966 | if (priv->scan_result != NULL) { |
3688 | changed = 1; | 3967 | /* What's likely is that a client did crash or was killed |
3689 | break; | 3968 | * between triggering the scan request and reading the |
3969 | * results, so we need to reset everything. | ||
3970 | * Some clients that are too slow may suffer from that... | ||
3971 | * Jean II */ | ||
3972 | kfree(priv->scan_result); | ||
3973 | priv->scan_result = NULL; | ||
3974 | } | ||
3690 | 3975 | ||
3691 | default: | 3976 | /* Save flags */ |
3692 | err = -EINVAL; | 3977 | priv->scan_mode = srq->flags; |
3693 | break; | ||
3694 | } | ||
3695 | set_port_type(priv); | ||
3696 | orinoco_unlock(priv, &flags); | ||
3697 | break; | ||
3698 | 3978 | ||
3699 | case SIOCGIWMODE: | 3979 | /* Always trigger scanning, even if it's in progress. |
3700 | if (orinoco_lock(priv, &flags) != 0) | 3980 | * This way, if the info frame get lost, we will recover somewhat |
3701 | return -EBUSY; | 3981 | * gracefully - Jean II */ |
3702 | wrq->u.mode = priv->iw_mode; | ||
3703 | orinoco_unlock(priv, &flags); | ||
3704 | break; | ||
3705 | 3982 | ||
3706 | case SIOCSIWENCODE: | 3983 | if (priv->has_hostscan) { |
3707 | err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding); | 3984 | switch (priv->firmware_type) { |
3708 | if (! err) | 3985 | case FIRMWARE_TYPE_SYMBOL: |
3709 | changed = 1; | 3986 | err = hermes_write_wordrec(hw, USER_BAP, |
3987 | HERMES_RID_CNFHOSTSCAN_SYMBOL, | ||
3988 | HERMES_HOSTSCAN_SYMBOL_ONCE | | ||
3989 | HERMES_HOSTSCAN_SYMBOL_BCAST); | ||
3990 | break; | ||
3991 | case FIRMWARE_TYPE_INTERSIL: { | ||
3992 | u16 req[3]; | ||
3993 | |||
3994 | req[0] = cpu_to_le16(0x3fff); /* All channels */ | ||
3995 | req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ | ||
3996 | req[2] = 0; /* Any ESSID */ | ||
3997 | err = HERMES_WRITE_RECORD(hw, USER_BAP, | ||
3998 | HERMES_RID_CNFHOSTSCAN, &req); | ||
3999 | } | ||
3710 | break; | 4000 | break; |
4001 | case FIRMWARE_TYPE_AGERE: | ||
4002 | err = hermes_write_wordrec(hw, USER_BAP, | ||
4003 | HERMES_RID_CNFSCANSSID_AGERE, | ||
4004 | 0); /* Any ESSID */ | ||
4005 | if (err) | ||
4006 | break; | ||
3711 | 4007 | ||
3712 | case SIOCGIWENCODE: | 4008 | err = hermes_inquire(hw, HERMES_INQ_SCAN); |
3713 | if (! capable(CAP_NET_ADMIN)) { | ||
3714 | err = -EPERM; | ||
3715 | break; | 4009 | break; |
3716 | } | 4010 | } |
4011 | } else | ||
4012 | err = hermes_inquire(hw, HERMES_INQ_SCAN); | ||
3717 | 4013 | ||
3718 | err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding); | 4014 | /* One more client */ |
3719 | break; | 4015 | if (! err) |
3720 | 4016 | priv->scan_inprogress = 1; | |
3721 | case SIOCSIWESSID: | ||
3722 | err = orinoco_ioctl_setessid(dev, &wrq->u.essid); | ||
3723 | if (! err) | ||
3724 | changed = 1; | ||
3725 | break; | ||
3726 | 4017 | ||
3727 | case SIOCGIWESSID: | 4018 | out: |
3728 | err = orinoco_ioctl_getessid(dev, &wrq->u.essid); | 4019 | orinoco_unlock(priv, &flags); |
3729 | break; | 4020 | return err; |
4021 | } | ||
3730 | 4022 | ||
3731 | case SIOCSIWNICKN: | 4023 | /* Translate scan data returned from the card to a card independant |
3732 | err = orinoco_ioctl_setnick(dev, &wrq->u.data); | 4024 | * format that the Wireless Tools will understand - Jean II */ |
3733 | if (! err) | 4025 | static inline int orinoco_translate_scan(struct net_device *dev, |
3734 | changed = 1; | 4026 | char *buffer, |
3735 | break; | 4027 | char *scan, |
4028 | int scan_len) | ||
4029 | { | ||
4030 | struct orinoco_private *priv = netdev_priv(dev); | ||
4031 | int offset; /* In the scan data */ | ||
4032 | union hermes_scan_info *atom; | ||
4033 | int atom_len; | ||
4034 | u16 capabilities; | ||
4035 | u16 channel; | ||
4036 | struct iw_event iwe; /* Temporary buffer */ | ||
4037 | char * current_ev = buffer; | ||
4038 | char * end_buf = buffer + IW_SCAN_MAX_DATA; | ||
3736 | 4039 | ||
3737 | case SIOCGIWNICKN: | 4040 | switch (priv->firmware_type) { |
3738 | err = orinoco_ioctl_getnick(dev, &wrq->u.data); | 4041 | case FIRMWARE_TYPE_AGERE: |
4042 | atom_len = sizeof(struct agere_scan_apinfo); | ||
4043 | offset = 0; | ||
3739 | break; | 4044 | break; |
3740 | 4045 | case FIRMWARE_TYPE_SYMBOL: | |
3741 | case SIOCGIWFREQ: | 4046 | /* Lack of documentation necessitates this hack. |
3742 | tmp = orinoco_hw_get_freq(priv); | 4047 | * Different firmwares have 68 or 76 byte long atoms. |
3743 | if (tmp < 0) { | 4048 | * We try modulo first. If the length divides by both, |
3744 | err = tmp; | 4049 | * we check what would be the channel in the second |
3745 | } else { | 4050 | * frame for a 68-byte atom. 76-byte atoms have 0 there. |
3746 | wrq->u.freq.m = tmp; | 4051 | * Valid channel cannot be 0. */ |
3747 | wrq->u.freq.e = 1; | 4052 | if (scan_len % 76) |
3748 | } | 4053 | atom_len = 68; |
4054 | else if (scan_len % 68) | ||
4055 | atom_len = 76; | ||
4056 | else if (scan_len >= 1292 && scan[68] == 0) | ||
4057 | atom_len = 76; | ||
4058 | else | ||
4059 | atom_len = 68; | ||
4060 | offset = 0; | ||
3749 | break; | 4061 | break; |
3750 | 4062 | case FIRMWARE_TYPE_INTERSIL: | |
3751 | case SIOCSIWFREQ: | 4063 | offset = 4; |
3752 | err = orinoco_ioctl_setfreq(dev, &wrq->u.freq); | 4064 | if (priv->has_hostscan) |
3753 | if (! err) | 4065 | atom_len = scan[0] + (scan[1] << 8); |
3754 | changed = 1; | 4066 | else |
4067 | atom_len = offsetof(struct prism2_scan_apinfo, atim); | ||
3755 | break; | 4068 | break; |
4069 | default: | ||
4070 | return 0; | ||
4071 | } | ||
3756 | 4072 | ||
3757 | case SIOCGIWSENS: | 4073 | /* Check that we got an whole number of atoms */ |
3758 | err = orinoco_ioctl_getsens(dev, &wrq->u.sens); | 4074 | if ((scan_len - offset) % atom_len) { |
3759 | break; | 4075 | printk(KERN_ERR "%s: Unexpected scan data length %d, " |
4076 | "atom_len %d, offset %d\n", dev->name, scan_len, | ||
4077 | atom_len, offset); | ||
4078 | return 0; | ||
4079 | } | ||
3760 | 4080 | ||
3761 | case SIOCSIWSENS: | 4081 | /* Read the entries one by one */ |
3762 | err = orinoco_ioctl_setsens(dev, &wrq->u.sens); | 4082 | for (; offset + atom_len <= scan_len; offset += atom_len) { |
3763 | if (! err) | 4083 | /* Get next atom */ |
3764 | changed = 1; | 4084 | atom = (union hermes_scan_info *) (scan + offset); |
3765 | break; | 4085 | |
4086 | /* First entry *MUST* be the AP MAC address */ | ||
4087 | iwe.cmd = SIOCGIWAP; | ||
4088 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
4089 | memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN); | ||
4090 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); | ||
4091 | |||
4092 | /* Other entries will be displayed in the order we give them */ | ||
4093 | |||
4094 | /* Add the ESSID */ | ||
4095 | iwe.u.data.length = le16_to_cpu(atom->a.essid_len); | ||
4096 | if (iwe.u.data.length > 32) | ||
4097 | iwe.u.data.length = 32; | ||
4098 | iwe.cmd = SIOCGIWESSID; | ||
4099 | iwe.u.data.flags = 1; | ||
4100 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid); | ||
4101 | |||
4102 | /* Add mode */ | ||
4103 | iwe.cmd = SIOCGIWMODE; | ||
4104 | capabilities = le16_to_cpu(atom->a.capabilities); | ||
4105 | if (capabilities & 0x3) { | ||
4106 | if (capabilities & 0x1) | ||
4107 | iwe.u.mode = IW_MODE_MASTER; | ||
4108 | else | ||
4109 | iwe.u.mode = IW_MODE_ADHOC; | ||
4110 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); | ||
4111 | } | ||
3766 | 4112 | ||
3767 | case SIOCGIWRTS: | 4113 | channel = atom->s.channel; |
3768 | wrq->u.rts.value = priv->rts_thresh; | 4114 | if ( (channel >= 1) && (channel <= NUM_CHANNELS) ) { |
3769 | wrq->u.rts.disabled = (wrq->u.rts.value == 2347); | 4115 | /* Add frequency */ |
3770 | wrq->u.rts.fixed = 1; | 4116 | iwe.cmd = SIOCGIWFREQ; |
3771 | break; | 4117 | iwe.u.freq.m = channel_frequency[channel-1] * 100000; |
4118 | iwe.u.freq.e = 1; | ||
4119 | current_ev = iwe_stream_add_event(current_ev, end_buf, | ||
4120 | &iwe, IW_EV_FREQ_LEN); | ||
4121 | } | ||
3772 | 4122 | ||
3773 | case SIOCSIWRTS: | 4123 | /* Add quality statistics */ |
3774 | err = orinoco_ioctl_setrts(dev, &wrq->u.rts); | 4124 | iwe.cmd = IWEVQUAL; |
3775 | if (! err) | 4125 | iwe.u.qual.updated = 0x10; /* no link quality */ |
3776 | changed = 1; | 4126 | iwe.u.qual.level = (__u8) le16_to_cpu(atom->a.level) - 0x95; |
3777 | break; | 4127 | iwe.u.qual.noise = (__u8) le16_to_cpu(atom->a.noise) - 0x95; |
4128 | /* Wireless tools prior to 27.pre22 will show link quality | ||
4129 | * anyway, so we provide a reasonable value. */ | ||
4130 | if (iwe.u.qual.level > iwe.u.qual.noise) | ||
4131 | iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; | ||
4132 | else | ||
4133 | iwe.u.qual.qual = 0; | ||
4134 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); | ||
3778 | 4135 | ||
3779 | case SIOCSIWFRAG: | 4136 | /* Add encryption capability */ |
3780 | err = orinoco_ioctl_setfrag(dev, &wrq->u.frag); | 4137 | iwe.cmd = SIOCGIWENCODE; |
3781 | if (! err) | 4138 | if (capabilities & 0x10) |
3782 | changed = 1; | 4139 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; |
3783 | break; | 4140 | else |
4141 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
4142 | iwe.u.data.length = 0; | ||
4143 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid); | ||
4144 | |||
4145 | /* Bit rate is not available in Lucent/Agere firmwares */ | ||
4146 | if (priv->firmware_type != FIRMWARE_TYPE_AGERE) { | ||
4147 | char * current_val = current_ev + IW_EV_LCP_LEN; | ||
4148 | int i; | ||
4149 | int step; | ||
4150 | |||
4151 | if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) | ||
4152 | step = 2; | ||
4153 | else | ||
4154 | step = 1; | ||
4155 | |||
4156 | iwe.cmd = SIOCGIWRATE; | ||
4157 | /* Those two flags are ignored... */ | ||
4158 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | ||
4159 | /* Max 10 values */ | ||
4160 | for (i = 0; i < 10; i += step) { | ||
4161 | /* NULL terminated */ | ||
4162 | if (atom->p.rates[i] == 0x0) | ||
4163 | break; | ||
4164 | /* Bit rate given in 500 kb/s units (+ 0x80) */ | ||
4165 | iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000); | ||
4166 | current_val = iwe_stream_add_value(current_ev, current_val, | ||
4167 | end_buf, &iwe, | ||
4168 | IW_EV_PARAM_LEN); | ||
4169 | } | ||
4170 | /* Check if we added any event */ | ||
4171 | if ((current_val - current_ev) > IW_EV_LCP_LEN) | ||
4172 | current_ev = current_val; | ||
4173 | } | ||
3784 | 4174 | ||
3785 | case SIOCGIWFRAG: | 4175 | /* The other data in the scan result are not really |
3786 | err = orinoco_ioctl_getfrag(dev, &wrq->u.frag); | 4176 | * interesting, so for now drop it - Jean II */ |
3787 | break; | 4177 | } |
4178 | return current_ev - buffer; | ||
4179 | } | ||
3788 | 4180 | ||
3789 | case SIOCSIWRATE: | 4181 | /* Return results of a scan */ |
3790 | err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate); | 4182 | static int orinoco_ioctl_getscan(struct net_device *dev, |
3791 | if (! err) | 4183 | struct iw_request_info *info, |
3792 | changed = 1; | 4184 | struct iw_point *srq, |
3793 | break; | 4185 | char *extra) |
4186 | { | ||
4187 | struct orinoco_private *priv = netdev_priv(dev); | ||
4188 | int err = 0; | ||
4189 | unsigned long flags; | ||
3794 | 4190 | ||
3795 | case SIOCGIWRATE: | 4191 | if (orinoco_lock(priv, &flags) != 0) |
3796 | err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate); | 4192 | return -EBUSY; |
3797 | break; | ||
3798 | 4193 | ||
3799 | case SIOCSIWPOWER: | 4194 | /* If no results yet, ask to try again later */ |
3800 | err = orinoco_ioctl_setpower(dev, &wrq->u.power); | 4195 | if (priv->scan_result == NULL) { |
3801 | if (! err) | 4196 | if (priv->scan_inprogress) |
3802 | changed = 1; | 4197 | /* Important note : we don't want to block the caller |
3803 | break; | 4198 | * until results are ready for various reasons. |
4199 | * First, managing wait queues is complex and racy. | ||
4200 | * Second, we grab some rtnetlink lock before comming | ||
4201 | * here (in dev_ioctl()). | ||
4202 | * Third, we generate an Wireless Event, so the | ||
4203 | * caller can wait itself on that - Jean II */ | ||
4204 | err = -EAGAIN; | ||
4205 | else | ||
4206 | /* Client error, no scan results... | ||
4207 | * The caller need to restart the scan. */ | ||
4208 | err = -ENODATA; | ||
4209 | } else { | ||
4210 | /* We have some results to push back to user space */ | ||
4211 | |||
4212 | /* Translate to WE format */ | ||
4213 | srq->length = orinoco_translate_scan(dev, extra, | ||
4214 | priv->scan_result, | ||
4215 | priv->scan_len); | ||
4216 | |||
4217 | /* Return flags */ | ||
4218 | srq->flags = (__u16) priv->scan_mode; | ||
4219 | |||
4220 | /* Results are here, so scan no longer in progress */ | ||
4221 | priv->scan_inprogress = 0; | ||
4222 | |||
4223 | /* In any case, Scan results will be cleaned up in the | ||
4224 | * reset function and when exiting the driver. | ||
4225 | * The person triggering the scanning may never come to | ||
4226 | * pick the results, so we need to do it in those places. | ||
4227 | * Jean II */ | ||
4228 | |||
4229 | #ifdef SCAN_SINGLE_READ | ||
4230 | /* If you enable this option, only one client (the first | ||
4231 | * one) will be able to read the result (and only one | ||
4232 | * time). If there is multiple concurent clients that | ||
4233 | * want to read scan results, this behavior is not | ||
4234 | * advisable - Jean II */ | ||
4235 | kfree(priv->scan_result); | ||
4236 | priv->scan_result = NULL; | ||
4237 | #endif /* SCAN_SINGLE_READ */ | ||
4238 | /* Here, if too much time has elapsed since last scan, | ||
4239 | * we may want to clean up scan results... - Jean II */ | ||
4240 | } | ||
4241 | |||
4242 | orinoco_unlock(priv, &flags); | ||
4243 | return err; | ||
4244 | } | ||
3804 | 4245 | ||
3805 | case SIOCGIWPOWER: | 4246 | /* Commit handler, called after set operations */ |
3806 | err = orinoco_ioctl_getpower(dev, &wrq->u.power); | 4247 | static int orinoco_ioctl_commit(struct net_device *dev, |
3807 | break; | 4248 | struct iw_request_info *info, |
4249 | void *wrqu, | ||
4250 | char *extra) | ||
4251 | { | ||
4252 | struct orinoco_private *priv = netdev_priv(dev); | ||
4253 | struct hermes *hw = &priv->hw; | ||
4254 | unsigned long flags; | ||
4255 | int err = 0; | ||
3808 | 4256 | ||
3809 | case SIOCGIWTXPOW: | 4257 | if (!priv->open) |
3810 | /* The card only supports one tx power, so this is easy */ | 4258 | return 0; |
3811 | wrq->u.txpower.value = 15; /* dBm */ | ||
3812 | wrq->u.txpower.fixed = 1; | ||
3813 | wrq->u.txpower.disabled = 0; | ||
3814 | wrq->u.txpower.flags = IW_TXPOW_DBM; | ||
3815 | break; | ||
3816 | 4259 | ||
3817 | case SIOCSIWRETRY: | 4260 | if (priv->broken_disableport) { |
3818 | err = -EOPNOTSUPP; | 4261 | orinoco_reset(dev); |
3819 | break; | 4262 | return 0; |
4263 | } | ||
3820 | 4264 | ||
3821 | case SIOCGIWRETRY: | 4265 | if (orinoco_lock(priv, &flags) != 0) |
3822 | err = orinoco_ioctl_getretry(dev, &wrq->u.retry); | 4266 | return err; |
3823 | break; | ||
3824 | 4267 | ||
3825 | case SIOCSIWSPY: | 4268 | err = hermes_disable_port(hw, 0); |
3826 | err = orinoco_ioctl_setspy(dev, &wrq->u.data); | 4269 | if (err) { |
3827 | break; | 4270 | printk(KERN_WARNING "%s: Unable to disable port " |
4271 | "while reconfiguring card\n", dev->name); | ||
4272 | priv->broken_disableport = 1; | ||
4273 | goto out; | ||
4274 | } | ||
3828 | 4275 | ||
3829 | case SIOCGIWSPY: | 4276 | err = __orinoco_program_rids(dev); |
3830 | err = orinoco_ioctl_getspy(dev, &wrq->u.data); | 4277 | if (err) { |
3831 | break; | 4278 | printk(KERN_WARNING "%s: Unable to reconfigure card\n", |
4279 | dev->name); | ||
4280 | goto out; | ||
4281 | } | ||
3832 | 4282 | ||
3833 | case SIOCGIWPRIV: | 4283 | err = hermes_enable_port(hw, 0); |
3834 | if (wrq->u.data.pointer) { | 4284 | if (err) { |
3835 | struct iw_priv_args privtab[] = { | 4285 | printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", |
3836 | { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, | 4286 | dev->name); |
3837 | { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, | 4287 | goto out; |
3838 | { SIOCIWFIRSTPRIV + 0x2, | 4288 | } |
3839 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3840 | 0, "set_port3" }, | ||
3841 | { SIOCIWFIRSTPRIV + 0x3, 0, | ||
3842 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3843 | "get_port3" }, | ||
3844 | { SIOCIWFIRSTPRIV + 0x4, | ||
3845 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3846 | 0, "set_preamble" }, | ||
3847 | { SIOCIWFIRSTPRIV + 0x5, 0, | ||
3848 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3849 | "get_preamble" }, | ||
3850 | { SIOCIWFIRSTPRIV + 0x6, | ||
3851 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3852 | 0, "set_ibssport" }, | ||
3853 | { SIOCIWFIRSTPRIV + 0x7, 0, | ||
3854 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3855 | "get_ibssport" }, | ||
3856 | }; | ||
3857 | |||
3858 | wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); | ||
3859 | if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab))) | ||
3860 | err = -EFAULT; | ||
3861 | } | ||
3862 | break; | ||
3863 | |||
3864 | case SIOCIWFIRSTPRIV + 0x0: /* force_reset */ | ||
3865 | case SIOCIWFIRSTPRIV + 0x1: /* card_reset */ | ||
3866 | if (! capable(CAP_NET_ADMIN)) { | ||
3867 | err = -EPERM; | ||
3868 | break; | ||
3869 | } | ||
3870 | |||
3871 | printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); | ||
3872 | 4289 | ||
4290 | out: | ||
4291 | if (err) { | ||
4292 | printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); | ||
3873 | schedule_work(&priv->reset_work); | 4293 | schedule_work(&priv->reset_work); |
3874 | break; | 4294 | err = 0; |
3875 | 4295 | } | |
3876 | case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */ | ||
3877 | if (! capable(CAP_NET_ADMIN)) { | ||
3878 | err = -EPERM; | ||
3879 | break; | ||
3880 | } | ||
3881 | |||
3882 | err = orinoco_ioctl_setport3(dev, wrq); | ||
3883 | if (! err) | ||
3884 | changed = 1; | ||
3885 | break; | ||
3886 | 4296 | ||
3887 | case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */ | 4297 | orinoco_unlock(priv, &flags); |
3888 | err = orinoco_ioctl_getport3(dev, wrq); | 4298 | return err; |
3889 | break; | 4299 | } |
3890 | 4300 | ||
3891 | case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */ | 4301 | static const struct iw_priv_args orinoco_privtab[] = { |
3892 | if (! capable(CAP_NET_ADMIN)) { | 4302 | { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, |
3893 | err = -EPERM; | 4303 | { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, |
3894 | break; | 4304 | { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
3895 | } | 4305 | 0, "set_port3" }, |
4306 | { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4307 | "get_port3" }, | ||
4308 | { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4309 | 0, "set_preamble" }, | ||
4310 | { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4311 | "get_preamble" }, | ||
4312 | { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4313 | 0, "set_ibssport" }, | ||
4314 | { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4315 | "get_ibssport" }, | ||
4316 | { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN, | ||
4317 | "get_rid" }, | ||
4318 | }; | ||
3896 | 4319 | ||
3897 | /* 802.11b has recently defined some short preamble. | ||
3898 | * Basically, the Phy header has been reduced in size. | ||
3899 | * This increase performance, especially at high rates | ||
3900 | * (the preamble is transmitted at 1Mb/s), unfortunately | ||
3901 | * this give compatibility troubles... - Jean II */ | ||
3902 | if(priv->has_preamble) { | ||
3903 | int val = *( (int *) wrq->u.name ); | ||
3904 | |||
3905 | if (orinoco_lock(priv, &flags) != 0) | ||
3906 | return -EBUSY; | ||
3907 | if (val) | ||
3908 | priv->preamble = 1; | ||
3909 | else | ||
3910 | priv->preamble = 0; | ||
3911 | orinoco_unlock(priv, &flags); | ||
3912 | changed = 1; | ||
3913 | } else | ||
3914 | err = -EOPNOTSUPP; | ||
3915 | break; | ||
3916 | 4320 | ||
3917 | case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */ | 4321 | /* |
3918 | if(priv->has_preamble) { | 4322 | * Structures to export the Wireless Handlers |
3919 | int *val = (int *)wrq->u.name; | 4323 | */ |
3920 | 4324 | ||
3921 | if (orinoco_lock(priv, &flags) != 0) | 4325 | static const iw_handler orinoco_handler[] = { |
3922 | return -EBUSY; | 4326 | [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit, |
3923 | *val = priv->preamble; | 4327 | [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname, |
3924 | orinoco_unlock(priv, &flags); | 4328 | [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq, |
3925 | } else | 4329 | [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq, |
3926 | err = -EOPNOTSUPP; | 4330 | [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode, |
3927 | break; | 4331 | [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode, |
3928 | case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */ | 4332 | [SIOCSIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens, |
3929 | if (! capable(CAP_NET_ADMIN)) { | 4333 | [SIOCGIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens, |
3930 | err = -EPERM; | 4334 | [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange, |
3931 | break; | 4335 | [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy, |
3932 | } | 4336 | [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy, |
4337 | [SIOCSIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setwap, | ||
4338 | [SIOCGIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap, | ||
4339 | [SIOCSIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setscan, | ||
4340 | [SIOCGIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getscan, | ||
4341 | [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid, | ||
4342 | [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid, | ||
4343 | [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick, | ||
4344 | [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick, | ||
4345 | [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate, | ||
4346 | [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate, | ||
4347 | [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts, | ||
4348 | [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts, | ||
4349 | [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag, | ||
4350 | [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag, | ||
4351 | [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry, | ||
4352 | [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode, | ||
4353 | [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode, | ||
4354 | [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower, | ||
4355 | [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower, | ||
4356 | }; | ||
3933 | 4357 | ||
3934 | err = orinoco_ioctl_setibssport(dev, wrq); | ||
3935 | if (! err) | ||
3936 | changed = 1; | ||
3937 | break; | ||
3938 | 4358 | ||
3939 | case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */ | 4359 | /* |
3940 | err = orinoco_ioctl_getibssport(dev, wrq); | 4360 | Added typecasting since we no longer use iwreq_data -- Moustafa |
3941 | break; | 4361 | */ |
4362 | static const iw_handler orinoco_private_handler[] = { | ||
4363 | [0] (iw_handler) orinoco_ioctl_reset, | ||
4364 | [1] (iw_handler) orinoco_ioctl_reset, | ||
4365 | [2] (iw_handler) orinoco_ioctl_setport3, | ||
4366 | [3] (iw_handler) orinoco_ioctl_getport3, | ||
4367 | [4] (iw_handler) orinoco_ioctl_setpreamble, | ||
4368 | [5] (iw_handler) orinoco_ioctl_getpreamble, | ||
4369 | [6] (iw_handler) orinoco_ioctl_setibssport, | ||
4370 | [7] (iw_handler) orinoco_ioctl_getibssport, | ||
4371 | [9] (iw_handler) orinoco_ioctl_getrid, | ||
4372 | }; | ||
3942 | 4373 | ||
3943 | default: | 4374 | static const struct iw_handler_def orinoco_handler_def = { |
3944 | err = -EOPNOTSUPP; | 4375 | .num_standard = ARRAY_SIZE(orinoco_handler), |
3945 | } | 4376 | .num_private = ARRAY_SIZE(orinoco_private_handler), |
3946 | 4377 | .num_private_args = ARRAY_SIZE(orinoco_privtab), | |
3947 | if (! err && changed && netif_running(dev)) { | 4378 | .standard = orinoco_handler, |
3948 | err = orinoco_reconfigure(dev); | 4379 | .private = orinoco_private_handler, |
3949 | } | 4380 | .private_args = orinoco_privtab, |
4381 | }; | ||
3950 | 4382 | ||
3951 | TRACE_EXIT(dev->name); | 4383 | static void orinoco_get_drvinfo(struct net_device *dev, |
4384 | struct ethtool_drvinfo *info) | ||
4385 | { | ||
4386 | struct orinoco_private *priv = netdev_priv(dev); | ||
3952 | 4387 | ||
3953 | return err; | 4388 | strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1); |
4389 | strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1); | ||
4390 | strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1); | ||
4391 | if (dev->class_dev.dev) | ||
4392 | strncpy(info->bus_info, dev->class_dev.dev->bus_id, | ||
4393 | sizeof(info->bus_info) - 1); | ||
4394 | else | ||
4395 | snprintf(info->bus_info, sizeof(info->bus_info) - 1, | ||
4396 | "PCMCIA %p", priv->hw.iobase); | ||
3954 | } | 4397 | } |
3955 | 4398 | ||
4399 | static struct ethtool_ops orinoco_ethtool_ops = { | ||
4400 | .get_drvinfo = orinoco_get_drvinfo, | ||
4401 | .get_link = ethtool_op_get_link, | ||
4402 | }; | ||
3956 | 4403 | ||
3957 | /********************************************************************/ | 4404 | /********************************************************************/ |
3958 | /* Debugging */ | 4405 | /* Debugging */ |
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index f749b50d1088..2f213a7103fe 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #ifndef _ORINOCO_H | 7 | #ifndef _ORINOCO_H |
8 | #define _ORINOCO_H | 8 | #define _ORINOCO_H |
9 | 9 | ||
10 | #define DRIVER_VERSION "0.14alpha2" | 10 | #define DRIVER_VERSION "0.15rc2" |
11 | 11 | ||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
@@ -22,6 +22,8 @@ | |||
22 | 22 | ||
23 | #define WIRELESS_SPY // enable iwspy support | 23 | #define WIRELESS_SPY // enable iwspy support |
24 | 24 | ||
25 | #define MAX_SCAN_LEN 4096 | ||
26 | |||
25 | #define ORINOCO_MAX_KEY_SIZE 14 | 27 | #define ORINOCO_MAX_KEY_SIZE 14 |
26 | #define ORINOCO_MAX_KEYS 4 | 28 | #define ORINOCO_MAX_KEYS 4 |
27 | 29 | ||
@@ -30,6 +32,20 @@ struct orinoco_key { | |||
30 | char data[ORINOCO_MAX_KEY_SIZE]; | 32 | char data[ORINOCO_MAX_KEY_SIZE]; |
31 | } __attribute__ ((packed)); | 33 | } __attribute__ ((packed)); |
32 | 34 | ||
35 | struct header_struct { | ||
36 | /* 802.3 */ | ||
37 | u8 dest[ETH_ALEN]; | ||
38 | u8 src[ETH_ALEN]; | ||
39 | u16 len; | ||
40 | /* 802.2 */ | ||
41 | u8 dsap; | ||
42 | u8 ssap; | ||
43 | u8 ctrl; | ||
44 | /* SNAP */ | ||
45 | u8 oui[3]; | ||
46 | u16 ethertype; | ||
47 | } __attribute__ ((packed)); | ||
48 | |||
33 | typedef enum { | 49 | typedef enum { |
34 | FIRMWARE_TYPE_AGERE, | 50 | FIRMWARE_TYPE_AGERE, |
35 | FIRMWARE_TYPE_INTERSIL, | 51 | FIRMWARE_TYPE_INTERSIL, |
@@ -48,6 +64,8 @@ struct orinoco_private { | |||
48 | /* driver state */ | 64 | /* driver state */ |
49 | int open; | 65 | int open; |
50 | u16 last_linkstatus; | 66 | u16 last_linkstatus; |
67 | struct work_struct join_work; | ||
68 | struct work_struct wevent_work; | ||
51 | 69 | ||
52 | /* Net device stuff */ | 70 | /* Net device stuff */ |
53 | struct net_device *ndev; | 71 | struct net_device *ndev; |
@@ -74,7 +92,9 @@ struct orinoco_private { | |||
74 | unsigned int has_pm:1; | 92 | unsigned int has_pm:1; |
75 | unsigned int has_preamble:1; | 93 | unsigned int has_preamble:1; |
76 | unsigned int has_sensitivity:1; | 94 | unsigned int has_sensitivity:1; |
95 | unsigned int has_hostscan:1; | ||
77 | unsigned int broken_disableport:1; | 96 | unsigned int broken_disableport:1; |
97 | unsigned int broken_monitor:1; | ||
78 | 98 | ||
79 | /* Configuration paramaters */ | 99 | /* Configuration paramaters */ |
80 | u32 iw_mode; | 100 | u32 iw_mode; |
@@ -84,6 +104,8 @@ struct orinoco_private { | |||
84 | int bitratemode; | 104 | int bitratemode; |
85 | char nick[IW_ESSID_MAX_SIZE+1]; | 105 | char nick[IW_ESSID_MAX_SIZE+1]; |
86 | char desired_essid[IW_ESSID_MAX_SIZE+1]; | 106 | char desired_essid[IW_ESSID_MAX_SIZE+1]; |
107 | char desired_bssid[ETH_ALEN]; | ||
108 | int bssid_fixed; | ||
87 | u16 frag_thresh, mwo_robust; | 109 | u16 frag_thresh, mwo_robust; |
88 | u16 channel; | 110 | u16 channel; |
89 | u16 ap_density, rts_thresh; | 111 | u16 ap_density, rts_thresh; |
@@ -98,6 +120,12 @@ struct orinoco_private { | |||
98 | /* Configuration dependent variables */ | 120 | /* Configuration dependent variables */ |
99 | int port_type, createibss; | 121 | int port_type, createibss; |
100 | int promiscuous, mc_count; | 122 | int promiscuous, mc_count; |
123 | |||
124 | /* Scanning support */ | ||
125 | int scan_inprogress; /* Scan pending... */ | ||
126 | u32 scan_mode; /* Type of scan done */ | ||
127 | char * scan_result; /* Result of previous scan */ | ||
128 | int scan_len; /* Lenght of result */ | ||
101 | }; | 129 | }; |
102 | 130 | ||
103 | #ifdef ORINOCO_DEBUG | 131 | #ifdef ORINOCO_DEBUG |
diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index 4481ec18c5a0..adc7499136dc 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c | |||
@@ -112,10 +112,10 @@ isl38xx_handle_wakeup(isl38xx_control_block *control_block, | |||
112 | void | 112 | void |
113 | isl38xx_trigger_device(int asleep, void __iomem *device_base) | 113 | isl38xx_trigger_device(int asleep, void __iomem *device_base) |
114 | { | 114 | { |
115 | struct timeval current_time; | ||
116 | u32 reg, counter = 0; | 115 | u32 reg, counter = 0; |
117 | 116 | ||
118 | #if VERBOSE > SHOW_ERROR_MESSAGES | 117 | #if VERBOSE > SHOW_ERROR_MESSAGES |
118 | struct timeval current_time; | ||
119 | DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n"); | 119 | DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n"); |
120 | #endif | 120 | #endif |
121 | 121 | ||
@@ -126,11 +126,11 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) | |||
126 | do_gettimeofday(¤t_time); | 126 | do_gettimeofday(¤t_time); |
127 | DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n", | 127 | DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n", |
128 | current_time.tv_sec, (long)current_time.tv_usec); | 128 | current_time.tv_sec, (long)current_time.tv_usec); |
129 | #endif | ||
130 | 129 | ||
131 | DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", | 130 | DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", |
132 | current_time.tv_sec, (long)current_time.tv_usec, | 131 | current_time.tv_sec, (long)current_time.tv_usec, |
133 | readl(device_base + ISL38XX_CTRL_STAT_REG)); | 132 | readl(device_base + ISL38XX_CTRL_STAT_REG)); |
133 | #endif | ||
134 | udelay(ISL38XX_WRITEIO_DELAY); | 134 | udelay(ISL38XX_WRITEIO_DELAY); |
135 | 135 | ||
136 | reg = readl(device_base + ISL38XX_INT_IDENT_REG); | 136 | reg = readl(device_base + ISL38XX_INT_IDENT_REG); |
@@ -148,10 +148,12 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) | |||
148 | counter++; | 148 | counter++; |
149 | } | 149 | } |
150 | 150 | ||
151 | #if VERBOSE > SHOW_ERROR_MESSAGES | ||
151 | DEBUG(SHOW_TRACING, | 152 | DEBUG(SHOW_TRACING, |
152 | "%08li.%08li Device register read %08x\n", | 153 | "%08li.%08li Device register read %08x\n", |
153 | current_time.tv_sec, (long)current_time.tv_usec, | 154 | current_time.tv_sec, (long)current_time.tv_usec, |
154 | readl(device_base + ISL38XX_CTRL_STAT_REG)); | 155 | readl(device_base + ISL38XX_CTRL_STAT_REG)); |
156 | #endif | ||
155 | udelay(ISL38XX_WRITEIO_DELAY); | 157 | udelay(ISL38XX_WRITEIO_DELAY); |
156 | 158 | ||
157 | #if VERBOSE > SHOW_ERROR_MESSAGES | 159 | #if VERBOSE > SHOW_ERROR_MESSAGES |
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 7a4adc4c8f09..794fb559efb0 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -1176,8 +1176,12 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, | |||
1176 | n_sectors = ata_id_u32(args->id, 60); | 1176 | n_sectors = ata_id_u32(args->id, 60); |
1177 | n_sectors--; /* ATA TotalUserSectors - 1 */ | 1177 | n_sectors--; /* ATA TotalUserSectors - 1 */ |
1178 | 1178 | ||
1179 | tmp = n_sectors; /* note: truncates, if lba48 */ | ||
1180 | if (args->cmd->cmnd[0] == READ_CAPACITY) { | 1179 | if (args->cmd->cmnd[0] == READ_CAPACITY) { |
1180 | if( n_sectors >= 0xffffffffULL ) | ||
1181 | tmp = 0xffffffff ; /* Return max count on overflow */ | ||
1182 | else | ||
1183 | tmp = n_sectors ; | ||
1184 | |||
1181 | /* sector count, 32-bit */ | 1185 | /* sector count, 32-bit */ |
1182 | rbuf[0] = tmp >> (8 * 3); | 1186 | rbuf[0] = tmp >> (8 * 3); |
1183 | rbuf[1] = tmp >> (8 * 2); | 1187 | rbuf[1] = tmp >> (8 * 2); |
@@ -1191,10 +1195,12 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, | |||
1191 | 1195 | ||
1192 | } else { | 1196 | } else { |
1193 | /* sector count, 64-bit */ | 1197 | /* sector count, 64-bit */ |
1194 | rbuf[2] = n_sectors >> (8 * 7); | 1198 | tmp = n_sectors >> (8 * 4); |
1195 | rbuf[3] = n_sectors >> (8 * 6); | 1199 | rbuf[2] = tmp >> (8 * 3); |
1196 | rbuf[4] = n_sectors >> (8 * 5); | 1200 | rbuf[3] = tmp >> (8 * 2); |
1197 | rbuf[5] = n_sectors >> (8 * 4); | 1201 | rbuf[4] = tmp >> (8 * 1); |
1202 | rbuf[5] = tmp; | ||
1203 | tmp = n_sectors; | ||
1198 | rbuf[6] = tmp >> (8 * 3); | 1204 | rbuf[6] = tmp >> (8 * 3); |
1199 | rbuf[7] = tmp >> (8 * 2); | 1205 | rbuf[7] = tmp >> (8 * 2); |
1200 | rbuf[8] = tmp >> (8 * 1); | 1206 | rbuf[8] = tmp >> (8 * 1); |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index feb8e73fc1c9..d27fb4c881d2 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -1497,23 +1497,6 @@ rs68328_init(void) | |||
1497 | return 0; | 1497 | return 0; |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | |||
1501 | |||
1502 | /* | ||
1503 | * register_serial and unregister_serial allows for serial ports to be | ||
1504 | * configured at run-time, to support PCMCIA modems. | ||
1505 | */ | ||
1506 | /* SPARC: Unused at this time, just here to make things link. */ | ||
1507 | int register_serial(struct serial_struct *req) | ||
1508 | { | ||
1509 | return -1; | ||
1510 | } | ||
1511 | |||
1512 | void unregister_serial(int line) | ||
1513 | { | ||
1514 | return; | ||
1515 | } | ||
1516 | |||
1517 | module_init(rs68328_init); | 1500 | module_init(rs68328_init); |
1518 | 1501 | ||
1519 | 1502 | ||
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index d8b9d2b8c200..34e75bc8f4cc 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -77,23 +77,9 @@ static unsigned int share_irqs = SERIAL8250_SHARE_IRQS; | |||
77 | */ | 77 | */ |
78 | #define is_real_interrupt(irq) ((irq) != 0) | 78 | #define is_real_interrupt(irq) ((irq) != 0) |
79 | 79 | ||
80 | /* | ||
81 | * This converts from our new CONFIG_ symbols to the symbols | ||
82 | * that asm/serial.h expects. You _NEED_ to comment out the | ||
83 | * linux/config.h include contained inside asm/serial.h for | ||
84 | * this to work. | ||
85 | */ | ||
86 | #undef CONFIG_SERIAL_MANY_PORTS | ||
87 | #undef CONFIG_SERIAL_DETECT_IRQ | ||
88 | #undef CONFIG_SERIAL_MULTIPORT | ||
89 | #undef CONFIG_HUB6 | ||
90 | |||
91 | #ifdef CONFIG_SERIAL_8250_DETECT_IRQ | 80 | #ifdef CONFIG_SERIAL_8250_DETECT_IRQ |
92 | #define CONFIG_SERIAL_DETECT_IRQ 1 | 81 | #define CONFIG_SERIAL_DETECT_IRQ 1 |
93 | #endif | 82 | #endif |
94 | #ifdef CONFIG_SERIAL_8250_MULTIPORT | ||
95 | #define CONFIG_SERIAL_MULTIPORT 1 | ||
96 | #endif | ||
97 | #ifdef CONFIG_SERIAL_8250_MANY_PORTS | 83 | #ifdef CONFIG_SERIAL_8250_MANY_PORTS |
98 | #define CONFIG_SERIAL_MANY_PORTS 1 | 84 | #define CONFIG_SERIAL_MANY_PORTS 1 |
99 | #endif | 85 | #endif |
@@ -2323,10 +2309,11 @@ static int __devinit serial8250_probe(struct device *dev) | |||
2323 | { | 2309 | { |
2324 | struct plat_serial8250_port *p = dev->platform_data; | 2310 | struct plat_serial8250_port *p = dev->platform_data; |
2325 | struct uart_port port; | 2311 | struct uart_port port; |
2312 | int ret, i; | ||
2326 | 2313 | ||
2327 | memset(&port, 0, sizeof(struct uart_port)); | 2314 | memset(&port, 0, sizeof(struct uart_port)); |
2328 | 2315 | ||
2329 | for (; p && p->flags != 0; p++) { | 2316 | for (i = 0; p && p->flags != 0; p++, i++) { |
2330 | port.iobase = p->iobase; | 2317 | port.iobase = p->iobase; |
2331 | port.membase = p->membase; | 2318 | port.membase = p->membase; |
2332 | port.irq = p->irq; | 2319 | port.irq = p->irq; |
@@ -2335,10 +2322,16 @@ static int __devinit serial8250_probe(struct device *dev) | |||
2335 | port.iotype = p->iotype; | 2322 | port.iotype = p->iotype; |
2336 | port.flags = p->flags; | 2323 | port.flags = p->flags; |
2337 | port.mapbase = p->mapbase; | 2324 | port.mapbase = p->mapbase; |
2325 | port.hub6 = p->hub6; | ||
2338 | port.dev = dev; | 2326 | port.dev = dev; |
2339 | if (share_irqs) | 2327 | if (share_irqs) |
2340 | port.flags |= UPF_SHARE_IRQ; | 2328 | port.flags |= UPF_SHARE_IRQ; |
2341 | serial8250_register_port(&port); | 2329 | ret = serial8250_register_port(&port); |
2330 | if (ret < 0) { | ||
2331 | dev_err(dev, "unable to register port at index %d " | ||
2332 | "(IO%lx MEM%lx IRQ%d): %d\n", i, | ||
2333 | p->iobase, p->mapbase, p->irq, ret); | ||
2334 | } | ||
2342 | } | 2335 | } |
2343 | return 0; | 2336 | return 0; |
2344 | } | 2337 | } |
diff --git a/drivers/serial/8250_accent.c b/drivers/serial/8250_accent.c new file mode 100644 index 000000000000..1f2c276063ef --- /dev/null +++ b/drivers/serial/8250_accent.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * linux/drivers/serial/8250_accent.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | ||
5 | * Data taken from include/asm-i386/serial.h | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/serial_8250.h> | ||
14 | |||
15 | #define PORT(_base,_irq) \ | ||
16 | { \ | ||
17 | .iobase = _base, \ | ||
18 | .irq = _irq, \ | ||
19 | .uartclk = 1843200, \ | ||
20 | .iotype = UPIO_PORT, \ | ||
21 | .flags = UPF_BOOT_AUTOCONF, \ | ||
22 | } | ||
23 | |||
24 | static struct plat_serial8250_port accent_data[] = { | ||
25 | PORT(0x330, 4), | ||
26 | PORT(0x338, 4), | ||
27 | { }, | ||
28 | }; | ||
29 | |||
30 | static struct platform_device accent_device = { | ||
31 | .name = "serial8250", | ||
32 | .id = 2, | ||
33 | .dev = { | ||
34 | .platform_data = accent_data, | ||
35 | }, | ||
36 | }; | ||
37 | |||
38 | static int __init accent_init(void) | ||
39 | { | ||
40 | return platform_device_register(&accent_device); | ||
41 | } | ||
42 | |||
43 | module_init(accent_init); | ||
44 | |||
45 | MODULE_AUTHOR("Russell King"); | ||
46 | MODULE_DESCRIPTION("8250 serial probe module for Accent Async cards"); | ||
47 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/8250_boca.c b/drivers/serial/8250_boca.c new file mode 100644 index 000000000000..465c9ea1e7a3 --- /dev/null +++ b/drivers/serial/8250_boca.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * linux/drivers/serial/8250_boca.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | ||
5 | * Data taken from include/asm-i386/serial.h | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/serial_8250.h> | ||
14 | |||
15 | #define PORT(_base,_irq) \ | ||
16 | { \ | ||
17 | .iobase = _base, \ | ||
18 | .irq = _irq, \ | ||
19 | .uartclk = 1843200, \ | ||
20 | .iotype = UPIO_PORT, \ | ||
21 | .flags = UPF_BOOT_AUTOCONF, \ | ||
22 | } | ||
23 | |||
24 | static struct plat_serial8250_port boca_data[] = { | ||
25 | PORT(0x100, 12), | ||
26 | PORT(0x108, 12), | ||
27 | PORT(0x110, 12), | ||
28 | PORT(0x118, 12), | ||
29 | PORT(0x120, 12), | ||
30 | PORT(0x128, 12), | ||
31 | PORT(0x130, 12), | ||
32 | PORT(0x138, 12), | ||
33 | PORT(0x140, 12), | ||
34 | PORT(0x148, 12), | ||
35 | PORT(0x150, 12), | ||
36 | PORT(0x158, 12), | ||
37 | PORT(0x160, 12), | ||
38 | PORT(0x168, 12), | ||
39 | PORT(0x170, 12), | ||
40 | PORT(0x178, 12), | ||
41 | { }, | ||
42 | }; | ||
43 | |||
44 | static struct platform_device boca_device = { | ||
45 | .name = "serial8250", | ||
46 | .id = 3, | ||
47 | .dev = { | ||
48 | .platform_data = boca_data, | ||
49 | }, | ||
50 | }; | ||
51 | |||
52 | static int __init boca_init(void) | ||
53 | { | ||
54 | return platform_device_register(&boca_device); | ||
55 | } | ||
56 | |||
57 | module_init(boca_init); | ||
58 | |||
59 | MODULE_AUTHOR("Russell King"); | ||
60 | MODULE_DESCRIPTION("8250 serial probe module for Boca cards"); | ||
61 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/8250_fourport.c b/drivers/serial/8250_fourport.c new file mode 100644 index 000000000000..e9b4d908ef42 --- /dev/null +++ b/drivers/serial/8250_fourport.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * linux/drivers/serial/8250_fourport.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | ||
5 | * Data taken from include/asm-i386/serial.h | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/serial_8250.h> | ||
14 | |||
15 | #define PORT(_base,_irq) \ | ||
16 | { \ | ||
17 | .iobase = _base, \ | ||
18 | .irq = _irq, \ | ||
19 | .uartclk = 1843200, \ | ||
20 | .iotype = UPIO_PORT, \ | ||
21 | .flags = UPF_BOOT_AUTOCONF | UPF_FOURPORT, \ | ||
22 | } | ||
23 | |||
24 | static struct plat_serial8250_port fourport_data[] = { | ||
25 | PORT(0x1a0, 9), | ||
26 | PORT(0x1a8, 9), | ||
27 | PORT(0x1b0, 9), | ||
28 | PORT(0x1b8, 9), | ||
29 | PORT(0x2a0, 5), | ||
30 | PORT(0x2a8, 5), | ||
31 | PORT(0x2b0, 5), | ||
32 | PORT(0x2b8, 5), | ||
33 | { }, | ||
34 | }; | ||
35 | |||
36 | static struct platform_device fourport_device = { | ||
37 | .name = "serial8250", | ||
38 | .id = 1, | ||
39 | .dev = { | ||
40 | .platform_data = fourport_data, | ||
41 | }, | ||
42 | }; | ||
43 | |||
44 | static int __init fourport_init(void) | ||
45 | { | ||
46 | return platform_device_register(&fourport_device); | ||
47 | } | ||
48 | |||
49 | module_init(fourport_init); | ||
50 | |||
51 | MODULE_AUTHOR("Russell King"); | ||
52 | MODULE_DESCRIPTION("8250 serial probe module for AST Fourport cards"); | ||
53 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/8250_hub6.c b/drivers/serial/8250_hub6.c new file mode 100644 index 000000000000..77f396f84b4c --- /dev/null +++ b/drivers/serial/8250_hub6.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * linux/drivers/serial/8250_hub6.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | ||
5 | * Data taken from include/asm-i386/serial.h | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/serial_8250.h> | ||
14 | |||
15 | #define HUB6(card,port) \ | ||
16 | { \ | ||
17 | .iobase = 0x302, \ | ||
18 | .irq = 3, \ | ||
19 | .uartclk = 1843200, \ | ||
20 | .iotype = UPIO_HUB6, \ | ||
21 | .flags = UPF_BOOT_AUTOCONF, \ | ||
22 | .hub6 = (card) << 6 | (port) << 3 | 1, \ | ||
23 | } | ||
24 | |||
25 | static struct plat_serial8250_port hub6_data[] = { | ||
26 | HUB6(0,0), | ||
27 | HUB6(0,1), | ||
28 | HUB6(0,2), | ||
29 | HUB6(0,3), | ||
30 | HUB6(0,4), | ||
31 | HUB6(0,5), | ||
32 | HUB6(1,0), | ||
33 | HUB6(1,1), | ||
34 | HUB6(1,2), | ||
35 | HUB6(1,3), | ||
36 | HUB6(1,4), | ||
37 | HUB6(1,5), | ||
38 | { }, | ||
39 | }; | ||
40 | |||
41 | static struct platform_device hub6_device = { | ||
42 | .name = "serial8250", | ||
43 | .id = 4, | ||
44 | .dev = { | ||
45 | .platform_data = hub6_data, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | static int __init hub6_init(void) | ||
50 | { | ||
51 | return platform_device_register(&hub6_device); | ||
52 | } | ||
53 | |||
54 | module_init(hub6_init); | ||
55 | |||
56 | MODULE_AUTHOR("Russell King"); | ||
57 | MODULE_DESCRIPTION("8250 serial probe module for Hub6 cards"); | ||
58 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/8250_mca.c b/drivers/serial/8250_mca.c new file mode 100644 index 000000000000..f0c40d68b8c1 --- /dev/null +++ b/drivers/serial/8250_mca.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * linux/drivers/serial/8250_mca.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | ||
5 | * Data taken from include/asm-i386/serial.h | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/config.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/mca.h> | ||
15 | #include <linux/serial_8250.h> | ||
16 | |||
17 | /* | ||
18 | * FIXME: Should we be doing AUTO_IRQ here? | ||
19 | */ | ||
20 | #ifdef CONFIG_SERIAL_8250_DETECT_IRQ | ||
21 | #define MCA_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ | ||
22 | #else | ||
23 | #define MCA_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | ||
24 | #endif | ||
25 | |||
26 | #define PORT(_base,_irq) \ | ||
27 | { \ | ||
28 | .iobase = _base, \ | ||
29 | .irq = _irq, \ | ||
30 | .uartclk = 1843200, \ | ||
31 | .iotype = UPIO_PORT, \ | ||
32 | .flags = MCA_FLAGS, \ | ||
33 | } | ||
34 | |||
35 | static struct plat_serial8250_port mca_data[] = { | ||
36 | PORT(0x3220, 3), | ||
37 | PORT(0x3228, 3), | ||
38 | PORT(0x4220, 3), | ||
39 | PORT(0x4228, 3), | ||
40 | PORT(0x5220, 3), | ||
41 | PORT(0x5228, 3), | ||
42 | { }, | ||
43 | }; | ||
44 | |||
45 | static struct platform_device mca_device = { | ||
46 | .name = "serial8250", | ||
47 | .id = 5, | ||
48 | .dev = { | ||
49 | .platform_data = mca_data, | ||
50 | }, | ||
51 | }; | ||
52 | |||
53 | static int __init mca_init(void) | ||
54 | { | ||
55 | if (!MCA_bus) | ||
56 | return -ENODEV; | ||
57 | return platform_device_register(&mca_device); | ||
58 | } | ||
59 | |||
60 | module_init(mca_init); | ||
61 | |||
62 | MODULE_AUTHOR("Russell King"); | ||
63 | MODULE_DESCRIPTION("8250 serial probe module for MCA ports"); | ||
64 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 25fcef2c42de..e879bce160df 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -89,11 +89,11 @@ config SERIAL_8250_NR_UARTS | |||
89 | int "Maximum number of non-legacy 8250/16550 serial ports" | 89 | int "Maximum number of non-legacy 8250/16550 serial ports" |
90 | depends on SERIAL_8250 | 90 | depends on SERIAL_8250 |
91 | default "4" | 91 | default "4" |
92 | ---help--- | 92 | help |
93 | Set this to the number of non-legacy serial ports you want | 93 | Set this to the number of serial ports you want the driver |
94 | the driver to support. This includes any ports discovered | 94 | to support. This includes any ports discovered via ACPI or |
95 | via ACPI or PCI enumeration and any ports that may be added | 95 | PCI enumeration and any ports that may be added at run-time |
96 | at run-time via hot-plug. | 96 | via hot-plug, or any ISA multi-port serial cards. |
97 | 97 | ||
98 | config SERIAL_8250_EXTENDED | 98 | config SERIAL_8250_EXTENDED |
99 | bool "Extended 8250/16550 serial driver options" | 99 | bool "Extended 8250/16550 serial driver options" |
@@ -141,31 +141,74 @@ config SERIAL_8250_DETECT_IRQ | |||
141 | 141 | ||
142 | If unsure, say N. | 142 | If unsure, say N. |
143 | 143 | ||
144 | config SERIAL_8250_MULTIPORT | ||
145 | bool "Support special multiport boards" | ||
146 | depends on SERIAL_8250_EXTENDED | ||
147 | help | ||
148 | Some multiport serial ports have special ports which are used to | ||
149 | signal when there are any serial ports on the board which need | ||
150 | servicing. Say Y here to enable the serial driver to take advantage | ||
151 | of those special I/O ports. | ||
152 | |||
153 | config SERIAL_8250_RSA | 144 | config SERIAL_8250_RSA |
154 | bool "Support RSA serial ports" | 145 | bool "Support RSA serial ports" |
155 | depends on SERIAL_8250_EXTENDED | 146 | depends on SERIAL_8250_EXTENDED |
156 | help | 147 | help |
157 | ::: To be written ::: | 148 | ::: To be written ::: |
158 | 149 | ||
159 | comment "Non-8250 serial port support" | 150 | # |
151 | # Multi-port serial cards | ||
152 | # | ||
153 | |||
154 | config SERIAL_8250_FOURPORT | ||
155 | tristate "Support Fourport cards" | ||
156 | depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS | ||
157 | help | ||
158 | Say Y here if you have an AST FourPort serial board. | ||
159 | |||
160 | To compile this driver as a module, choose M here: the module | ||
161 | will be called 8250_fourport. | ||
162 | |||
163 | config SERIAL_8250_ACCENT | ||
164 | tristate "Support Accent cards" | ||
165 | depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS | ||
166 | help | ||
167 | Say Y here if you have an Accent Async serial board. | ||
168 | |||
169 | To compile this driver as a module, choose M here: the module | ||
170 | will be called 8250_accent. | ||
171 | |||
172 | |||
173 | config SERIAL_8250_BOCA | ||
174 | tristate "Support Boca cards" | ||
175 | depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS | ||
176 | help | ||
177 | Say Y here if you have a Boca serial board. Please read the Boca | ||
178 | mini-HOWTO, avaialble from <http://www.tldp.org/docs.html#howto> | ||
179 | |||
180 | To compile this driver as a module, choose M here: the module | ||
181 | will be called 8250_boca. | ||
182 | |||
183 | |||
184 | config SERIAL_8250_HUB6 | ||
185 | tristate "Support Hub6 cards" | ||
186 | depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS | ||
187 | help | ||
188 | Say Y here if you have a HUB6 serial board. | ||
189 | |||
190 | To compile this driver as a module, choose M here: the module | ||
191 | will be called 8250_hub6. | ||
192 | |||
193 | config SERIAL_8250_MCA | ||
194 | tristate "Support 8250-type ports on MCA buses" | ||
195 | depends on SERIAL_8250 != n && MCA | ||
196 | help | ||
197 | Say Y here if you have a MCA serial ports. | ||
198 | |||
199 | To compile this driver as a module, choose M here: the module | ||
200 | will be called 8250_mca. | ||
160 | 201 | ||
161 | config SERIAL_8250_ACORN | 202 | config SERIAL_8250_ACORN |
162 | tristate "Acorn expansion card serial port support" | 203 | tristate "Acorn expansion card serial port support" |
163 | depends on ARM && ARCH_ACORN && SERIAL_8250 | 204 | depends on ARCH_ACORN && SERIAL_8250 |
164 | help | 205 | help |
165 | If you have an Atomwide Serial card or Serial Port card for an Acorn | 206 | If you have an Atomwide Serial card or Serial Port card for an Acorn |
166 | system, say Y to this option. The driver can handle 1, 2, or 3 port | 207 | system, say Y to this option. The driver can handle 1, 2, or 3 port |
167 | cards. If unsure, say N. | 208 | cards. If unsure, say N. |
168 | 209 | ||
210 | comment "Non-8250 serial port support" | ||
211 | |||
169 | config SERIAL_AMBA_PL010 | 212 | config SERIAL_AMBA_PL010 |
170 | tristate "ARM AMBA PL010 serial port support" | 213 | tristate "ARM AMBA PL010 serial port support" |
171 | depends on ARM_AMBA | 214 | depends on ARM_AMBA |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 8f1cdde7dbed..65bd4381685e 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -17,6 +17,11 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) | |||
17 | obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o | 17 | obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o |
18 | obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o | 18 | obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o |
19 | obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o | 19 | obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o |
20 | obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o | ||
21 | obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o | ||
22 | obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o | ||
23 | obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o | ||
24 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o | ||
20 | obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o | 25 | obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o |
21 | obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o | 26 | obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o |
22 | obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o | 27 | obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o |
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index a61d4433a989..d79cd218a551 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_USB) += core/ | |||
9 | obj-$(CONFIG_USB_MON) += mon/ | 9 | obj-$(CONFIG_USB_MON) += mon/ |
10 | 10 | ||
11 | obj-$(CONFIG_USB_EHCI_HCD) += host/ | 11 | obj-$(CONFIG_USB_EHCI_HCD) += host/ |
12 | obj-$(CONFIG_USB_ISP116X_HCD) += host/ | ||
12 | obj-$(CONFIG_USB_OHCI_HCD) += host/ | 13 | obj-$(CONFIG_USB_OHCI_HCD) += host/ |
13 | obj-$(CONFIG_USB_UHCI_HCD) += host/ | 14 | obj-$(CONFIG_USB_UHCI_HCD) += host/ |
14 | obj-$(CONFIG_USB_SL811_HCD) += host/ | 15 | obj-$(CONFIG_USB_SL811_HCD) += host/ |
@@ -31,6 +32,7 @@ obj-$(CONFIG_USB_MOUSE) += input/ | |||
31 | obj-$(CONFIG_USB_MTOUCH) += input/ | 32 | obj-$(CONFIG_USB_MTOUCH) += input/ |
32 | obj-$(CONFIG_USB_POWERMATE) += input/ | 33 | obj-$(CONFIG_USB_POWERMATE) += input/ |
33 | obj-$(CONFIG_USB_WACOM) += input/ | 34 | obj-$(CONFIG_USB_WACOM) += input/ |
35 | obj-$(CONFIG_USB_ACECAD) += input/ | ||
34 | obj-$(CONFIG_USB_XPAD) += input/ | 36 | obj-$(CONFIG_USB_XPAD) += input/ |
35 | 37 | ||
36 | obj-$(CONFIG_USB_DABUSB) += media/ | 38 | obj-$(CONFIG_USB_DABUSB) += media/ |
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig index 0d9f5379b8cf..f429862e0974 100644 --- a/drivers/usb/atm/Kconfig +++ b/drivers/usb/atm/Kconfig | |||
@@ -1,30 +1,60 @@ | |||
1 | # | 1 | # |
2 | # USB ATM driver configuration | 2 | # USB/ATM DSL configuration |
3 | # | 3 | # |
4 | comment "USB ATM/DSL drivers" | 4 | |
5 | menu "USB DSL modem support" | ||
5 | depends on USB | 6 | depends on USB |
6 | 7 | ||
7 | config USB_ATM | 8 | config USB_ATM |
8 | tristate "Generic USB ATM/DSL core I/O support" | 9 | tristate "USB DSL modem support" |
9 | depends on USB && ATM | 10 | depends on USB && ATM |
10 | select CRC32 | 11 | select CRC32 |
11 | default n | 12 | default n |
12 | help | 13 | help |
13 | This provides a library which is used for packet I/O by USB DSL | 14 | Say Y here if you want to connect a USB Digital Subscriber Line (DSL) |
14 | modems, such as the SpeedTouch driver below. | 15 | modem to your computer's USB port. You will then need to choose your |
16 | modem from the list below. | ||
15 | 17 | ||
16 | To compile this driver as a module, choose M here: the | 18 | To compile this driver as a module, choose M here: the |
17 | module will be called usb_atm. | 19 | module will be called usbatm. |
18 | 20 | ||
19 | config USB_SPEEDTOUCH | 21 | config USB_SPEEDTOUCH |
20 | tristate "Alcatel Speedtouch USB support" | 22 | tristate "Speedtouch USB support" |
21 | depends on USB && ATM | 23 | depends on USB_ATM |
22 | select USB_ATM | 24 | select FW_LOADER |
23 | help | 25 | help |
24 | Say Y here if you have an Alcatel SpeedTouch USB or SpeedTouch 330 | 26 | Say Y here if you have an SpeedTouch USB or SpeedTouch 330 |
25 | modem. In order to use your modem you will need to install the | 27 | modem. In order to use your modem you will need to install the |
26 | two parts of the firmware, extracted by the user space tools; see | 28 | two parts of the firmware, extracted by the user space tools; see |
27 | <http://www.linux-usb.org/SpeedTouch/> for details. | 29 | <http://www.linux-usb.org/SpeedTouch/> for details. |
28 | 30 | ||
29 | To compile this driver as a module, choose M here: the | 31 | To compile this driver as a module, choose M here: the |
30 | module will be called speedtch. | 32 | module will be called speedtch. |
33 | |||
34 | config USB_CXACRU | ||
35 | tristate "Conexant AccessRunner USB support" | ||
36 | depends on USB_ATM | ||
37 | select FW_LOADER | ||
38 | help | ||
39 | Say Y here if you have an ADSL USB modem based on the Conexant | ||
40 | AccessRunner chipset. In order to use your modem you will need to | ||
41 | install the firmware, extracted by the user space tools; see | ||
42 | <http://accessrunner.sourceforge.net/> for details. | ||
43 | |||
44 | To compile this driver as a module, choose M here: the | ||
45 | module will be called cxacru. | ||
46 | |||
47 | config USB_XUSBATM | ||
48 | tristate "Other USB DSL modem support" | ||
49 | depends on USB_ATM | ||
50 | help | ||
51 | Say Y here if you have a DSL USB modem not explicitly supported by | ||
52 | another USB DSL drivers. In order to use your modem you will need to | ||
53 | pass the vendor ID, product ID, and endpoint numbers for transmission | ||
54 | and reception as module parameters. You may need to initialize the | ||
55 | the modem using a user space utility (a firmware loader for example). | ||
56 | |||
57 | To compile this driver as a module, choose M here: the | ||
58 | module will be called xusbatm. | ||
59 | |||
60 | endmenu | ||
diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile index 9213b8b97587..751f297be2ef 100644 --- a/drivers/usb/atm/Makefile +++ b/drivers/usb/atm/Makefile | |||
@@ -1,7 +1,8 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the rest of the USB drivers | 2 | # Makefile for USB ATM/xDSL drivers |
3 | # (the ones that don't fit into any other categories) | ||
4 | # | 3 | # |
5 | 4 | ||
6 | obj-$(CONFIG_USB_ATM) += usb_atm.o | 5 | obj-$(CONFIG_USB_CXACRU) += cxacru.o |
7 | obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o | 6 | obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o |
7 | obj-$(CONFIG_USB_ATM) += usbatm.o | ||
8 | obj-$(CONFIG_USB_XUSBATM) += xusbatm.o | ||
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c new file mode 100644 index 000000000000..cbd4a7d25d0b --- /dev/null +++ b/drivers/usb/atm/cxacru.c | |||
@@ -0,0 +1,878 @@ | |||
1 | /****************************************************************************** | ||
2 | * cxacru.c - driver for USB ADSL modems based on | ||
3 | * Conexant AccessRunner chipset | ||
4 | * | ||
5 | * Copyright (C) 2004 David Woodhouse, Duncan Sands, Roman Kagan | ||
6 | * Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | /* | ||
25 | * Credit is due for Josep Comas, who created the original patch to speedtch.c | ||
26 | * to support the different padding used by the AccessRunner (now generalized | ||
27 | * into usbatm), and the userspace firmware loading utility. | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/errno.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/device.h> /* FIXME: linux/firmware.h should include it itself */ | ||
38 | #include <linux/firmware.h> | ||
39 | |||
40 | #include "usbatm.h" | ||
41 | |||
42 | #define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands" | ||
43 | #define DRIVER_VERSION "0.2" | ||
44 | #define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver" | ||
45 | |||
46 | static const char cxacru_driver_name[] = "cxacru"; | ||
47 | |||
48 | #define CXACRU_EP_CMD 0x01 /* Bulk/interrupt in/out */ | ||
49 | #define CXACRU_EP_DATA 0x02 /* Bulk in/out */ | ||
50 | |||
51 | #define CMD_PACKET_SIZE 64 /* Should be maxpacket(ep)? */ | ||
52 | |||
53 | /* Addresses */ | ||
54 | #define PLLFCLK_ADDR 0x00350068 | ||
55 | #define PLLBCLK_ADDR 0x0035006c | ||
56 | #define SDRAMEN_ADDR 0x00350010 | ||
57 | #define FW_ADDR 0x00801000 | ||
58 | #define BR_ADDR 0x00180600 | ||
59 | #define SIG_ADDR 0x00180500 | ||
60 | #define BR_STACK_ADDR 0x00187f10 | ||
61 | |||
62 | /* Values */ | ||
63 | #define SDRAM_ENA 0x1 | ||
64 | |||
65 | #define CMD_TIMEOUT 2000 /* msecs */ | ||
66 | #define POLL_INTERVAL 5000 /* msecs */ | ||
67 | |||
68 | /* commands for interaction with the modem through the control channel before | ||
69 | * firmware is loaded */ | ||
70 | enum cxacru_fw_request { | ||
71 | FW_CMD_ERR, | ||
72 | FW_GET_VER, | ||
73 | FW_READ_MEM, | ||
74 | FW_WRITE_MEM, | ||
75 | FW_RMW_MEM, | ||
76 | FW_CHECKSUM_MEM, | ||
77 | FW_GOTO_MEM, | ||
78 | }; | ||
79 | |||
80 | /* commands for interaction with the modem through the control channel once | ||
81 | * firmware is loaded */ | ||
82 | enum cxacru_cm_request { | ||
83 | CM_REQUEST_UNDEFINED = 0x80, | ||
84 | CM_REQUEST_TEST, | ||
85 | CM_REQUEST_CHIP_GET_MAC_ADDRESS, | ||
86 | CM_REQUEST_CHIP_GET_DP_VERSIONS, | ||
87 | CM_REQUEST_CHIP_ADSL_LINE_START, | ||
88 | CM_REQUEST_CHIP_ADSL_LINE_STOP, | ||
89 | CM_REQUEST_CHIP_ADSL_LINE_GET_STATUS, | ||
90 | CM_REQUEST_CHIP_ADSL_LINE_GET_SPEED, | ||
91 | CM_REQUEST_CARD_INFO_GET, | ||
92 | CM_REQUEST_CARD_DATA_GET, | ||
93 | CM_REQUEST_CARD_DATA_SET, | ||
94 | CM_REQUEST_COMMAND_HW_IO, | ||
95 | CM_REQUEST_INTERFACE_HW_IO, | ||
96 | CM_REQUEST_CARD_SERIAL_DATA_PATH_GET, | ||
97 | CM_REQUEST_CARD_SERIAL_DATA_PATH_SET, | ||
98 | CM_REQUEST_CARD_CONTROLLER_VERSION_GET, | ||
99 | CM_REQUEST_CARD_GET_STATUS, | ||
100 | CM_REQUEST_CARD_GET_MAC_ADDRESS, | ||
101 | CM_REQUEST_CARD_GET_DATA_LINK_STATUS, | ||
102 | CM_REQUEST_MAX, | ||
103 | }; | ||
104 | |||
105 | /* reply codes to the commands above */ | ||
106 | enum cxacru_cm_status { | ||
107 | CM_STATUS_UNDEFINED, | ||
108 | CM_STATUS_SUCCESS, | ||
109 | CM_STATUS_ERROR, | ||
110 | CM_STATUS_UNSUPPORTED, | ||
111 | CM_STATUS_UNIMPLEMENTED, | ||
112 | CM_STATUS_PARAMETER_ERROR, | ||
113 | CM_STATUS_DBG_LOOPBACK, | ||
114 | CM_STATUS_MAX, | ||
115 | }; | ||
116 | |||
117 | /* indices into CARD_INFO_GET return array */ | ||
118 | enum cxacru_info_idx { | ||
119 | CXINF_DOWNSTREAM_RATE, | ||
120 | CXINF_UPSTREAM_RATE, | ||
121 | CXINF_LINK_STATUS, | ||
122 | CXINF_LINE_STATUS, | ||
123 | CXINF_MAC_ADDRESS_HIGH, | ||
124 | CXINF_MAC_ADDRESS_LOW, | ||
125 | CXINF_UPSTREAM_SNR_MARGIN, | ||
126 | CXINF_DOWNSTREAM_SNR_MARGIN, | ||
127 | CXINF_UPSTREAM_ATTENUATION, | ||
128 | CXINF_DOWNSTREAM_ATTENUATION, | ||
129 | CXINF_TRANSMITTER_POWER, | ||
130 | CXINF_UPSTREAM_BITS_PER_FRAME, | ||
131 | CXINF_DOWNSTREAM_BITS_PER_FRAME, | ||
132 | CXINF_STARTUP_ATTEMPTS, | ||
133 | CXINF_UPSTREAM_CRC_ERRORS, | ||
134 | CXINF_DOWNSTREAM_CRC_ERRORS, | ||
135 | CXINF_UPSTREAM_FEC_ERRORS, | ||
136 | CXINF_DOWNSTREAM_FEC_ERRORS, | ||
137 | CXINF_UPSTREAM_HEC_ERRORS, | ||
138 | CXINF_DOWNSTREAM_HEC_ERRORS, | ||
139 | CXINF_LINE_STARTABLE, | ||
140 | CXINF_MODULATION, | ||
141 | CXINF_ADSL_HEADEND, | ||
142 | CXINF_ADSL_HEADEND_ENVIRONMENT, | ||
143 | CXINF_CONTROLLER_VERSION, | ||
144 | /* dunno what the missing two mean */ | ||
145 | CXINF_MAX = 0x1c, | ||
146 | }; | ||
147 | |||
148 | struct cxacru_modem_type { | ||
149 | u32 pll_f_clk; | ||
150 | u32 pll_b_clk; | ||
151 | int boot_rom_patch; | ||
152 | }; | ||
153 | |||
154 | struct cxacru_data { | ||
155 | struct usbatm_data *usbatm; | ||
156 | |||
157 | const struct cxacru_modem_type *modem_type; | ||
158 | |||
159 | int line_status; | ||
160 | struct work_struct poll_work; | ||
161 | |||
162 | /* contol handles */ | ||
163 | struct semaphore cm_serialize; | ||
164 | u8 *rcv_buf; | ||
165 | u8 *snd_buf; | ||
166 | struct urb *rcv_urb; | ||
167 | struct urb *snd_urb; | ||
168 | struct completion rcv_done; | ||
169 | struct completion snd_done; | ||
170 | }; | ||
171 | |||
172 | /* the following three functions are stolen from drivers/usb/core/message.c */ | ||
173 | static void cxacru_blocking_completion(struct urb *urb, struct pt_regs *regs) | ||
174 | { | ||
175 | complete((struct completion *)urb->context); | ||
176 | } | ||
177 | |||
178 | static void cxacru_timeout_kill(unsigned long data) | ||
179 | { | ||
180 | usb_unlink_urb((struct urb *) data); | ||
181 | } | ||
182 | |||
183 | static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, | ||
184 | int* actual_length) | ||
185 | { | ||
186 | struct timer_list timer; | ||
187 | int status; | ||
188 | |||
189 | init_timer(&timer); | ||
190 | timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT); | ||
191 | timer.data = (unsigned long) urb; | ||
192 | timer.function = cxacru_timeout_kill; | ||
193 | add_timer(&timer); | ||
194 | wait_for_completion(done); | ||
195 | status = urb->status; | ||
196 | if (status == -ECONNRESET) | ||
197 | status = -ETIMEDOUT; | ||
198 | del_timer_sync(&timer); | ||
199 | |||
200 | if (actual_length) | ||
201 | *actual_length = urb->actual_length; | ||
202 | return status; | ||
203 | } | ||
204 | |||
205 | static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, | ||
206 | u8 *wdata, int wsize, u8 *rdata, int rsize) | ||
207 | { | ||
208 | int ret, actlen; | ||
209 | int offb, offd; | ||
210 | const int stride = CMD_PACKET_SIZE - 4; | ||
211 | u8 *wbuf = instance->snd_buf; | ||
212 | u8 *rbuf = instance->rcv_buf; | ||
213 | int wbuflen = ((wsize - 1) / stride + 1) * CMD_PACKET_SIZE; | ||
214 | int rbuflen = ((rsize - 1) / stride + 1) * CMD_PACKET_SIZE; | ||
215 | |||
216 | if (wbuflen > PAGE_SIZE || rbuflen > PAGE_SIZE) { | ||
217 | dbg("too big transfer requested"); | ||
218 | ret = -ENOMEM; | ||
219 | goto fail; | ||
220 | } | ||
221 | |||
222 | down(&instance->cm_serialize); | ||
223 | |||
224 | /* submit reading urb before the writing one */ | ||
225 | init_completion(&instance->rcv_done); | ||
226 | ret = usb_submit_urb(instance->rcv_urb, GFP_KERNEL); | ||
227 | if (ret < 0) { | ||
228 | dbg("submitting read urb for cm %#x failed", cm); | ||
229 | ret = ret; | ||
230 | goto fail; | ||
231 | } | ||
232 | |||
233 | memset(wbuf, 0, wbuflen); | ||
234 | /* handle wsize == 0 */ | ||
235 | wbuf[0] = cm; | ||
236 | for (offb = offd = 0; offd < wsize; offd += stride, offb += CMD_PACKET_SIZE) { | ||
237 | wbuf[offb] = cm; | ||
238 | memcpy(wbuf + offb + 4, wdata + offd, min_t(int, stride, wsize - offd)); | ||
239 | } | ||
240 | |||
241 | instance->snd_urb->transfer_buffer_length = wbuflen; | ||
242 | init_completion(&instance->snd_done); | ||
243 | ret = usb_submit_urb(instance->snd_urb, GFP_KERNEL); | ||
244 | if (ret < 0) { | ||
245 | dbg("submitting write urb for cm %#x failed", cm); | ||
246 | ret = ret; | ||
247 | goto fail; | ||
248 | } | ||
249 | |||
250 | ret = cxacru_start_wait_urb(instance->snd_urb, &instance->snd_done, NULL); | ||
251 | if (ret < 0) { | ||
252 | dbg("sending cm %#x failed", cm); | ||
253 | ret = ret; | ||
254 | goto fail; | ||
255 | } | ||
256 | |||
257 | ret = cxacru_start_wait_urb(instance->rcv_urb, &instance->rcv_done, &actlen); | ||
258 | if (ret < 0) { | ||
259 | dbg("receiving cm %#x failed", cm); | ||
260 | ret = ret; | ||
261 | goto fail; | ||
262 | } | ||
263 | if (actlen % CMD_PACKET_SIZE || !actlen) { | ||
264 | dbg("response is not a positive multiple of %d: %#x", | ||
265 | CMD_PACKET_SIZE, actlen); | ||
266 | ret = -EIO; | ||
267 | goto fail; | ||
268 | } | ||
269 | |||
270 | /* check the return status and copy the data to the output buffer, if needed */ | ||
271 | for (offb = offd = 0; offd < rsize && offb < actlen; offb += CMD_PACKET_SIZE) { | ||
272 | if (rbuf[offb] != cm) { | ||
273 | dbg("wrong cm %#x in response", rbuf[offb]); | ||
274 | ret = -EIO; | ||
275 | goto fail; | ||
276 | } | ||
277 | if (rbuf[offb + 1] != CM_STATUS_SUCCESS) { | ||
278 | dbg("response failed: %#x", rbuf[offb + 1]); | ||
279 | ret = -EIO; | ||
280 | goto fail; | ||
281 | } | ||
282 | if (offd >= rsize) | ||
283 | break; | ||
284 | memcpy(rdata + offd, rbuf + offb + 4, min_t(int, stride, rsize - offd)); | ||
285 | offd += stride; | ||
286 | } | ||
287 | |||
288 | ret = offd; | ||
289 | dbg("cm %#x", cm); | ||
290 | fail: | ||
291 | up(&instance->cm_serialize); | ||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_request cm, | ||
296 | u32 *data, int size) | ||
297 | { | ||
298 | int ret, len; | ||
299 | u32 *buf; | ||
300 | int offb, offd; | ||
301 | const int stride = CMD_PACKET_SIZE / (4 * 2) - 1; | ||
302 | int buflen = ((size - 1) / stride + 1 + size * 2) * 4; | ||
303 | |||
304 | buf = kmalloc(buflen, GFP_KERNEL); | ||
305 | if (!buf) | ||
306 | return -ENOMEM; | ||
307 | |||
308 | ret = cxacru_cm(instance, cm, NULL, 0, (u8 *) buf, buflen); | ||
309 | if (ret < 0) | ||
310 | goto cleanup; | ||
311 | |||
312 | /* len > 0 && len % 4 == 0 guaranteed by cxacru_cm() */ | ||
313 | len = ret / 4; | ||
314 | for (offb = 0; offb < len; ) { | ||
315 | int l = le32_to_cpu(buf[offb++]); | ||
316 | if (l > stride || l > (len - offb) / 2) { | ||
317 | dbg("wrong data length %#x in response", l); | ||
318 | ret = -EIO; | ||
319 | goto cleanup; | ||
320 | } | ||
321 | while (l--) { | ||
322 | offd = le32_to_cpu(buf[offb++]); | ||
323 | if (offd >= size) { | ||
324 | dbg("wrong index %#x in response", offd); | ||
325 | ret = -EIO; | ||
326 | goto cleanup; | ||
327 | } | ||
328 | data[offd] = le32_to_cpu(buf[offb++]); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | ret = 0; | ||
333 | |||
334 | cleanup: | ||
335 | kfree(buf); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static int cxacru_card_status(struct cxacru_data *instance) | ||
340 | { | ||
341 | int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); | ||
342 | if (ret < 0) { /* firmware not loaded */ | ||
343 | dbg("cxacru_adsl_start: CARD_GET_STATUS returned %d", ret); | ||
344 | return ret; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static void cxacru_poll_status(struct cxacru_data *instance); | ||
350 | |||
351 | static int cxacru_atm_start(struct usbatm_data *usbatm_instance, | ||
352 | struct atm_dev *atm_dev) | ||
353 | { | ||
354 | struct cxacru_data *instance = usbatm_instance->driver_data; | ||
355 | struct device *dev = &usbatm_instance->usb_intf->dev; | ||
356 | /* | ||
357 | struct atm_dev *atm_dev = usbatm_instance->atm_dev; | ||
358 | */ | ||
359 | int ret; | ||
360 | |||
361 | dbg("cxacru_atm_start"); | ||
362 | |||
363 | /* Read MAC address */ | ||
364 | ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0, | ||
365 | atm_dev->esi, sizeof(atm_dev->esi)); | ||
366 | if (ret < 0) { | ||
367 | dev_err(dev, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | /* start ADSL */ | ||
372 | ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); | ||
373 | if (ret < 0) { | ||
374 | dev_err(dev, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret); | ||
375 | return ret; | ||
376 | } | ||
377 | |||
378 | /* Start status polling */ | ||
379 | cxacru_poll_status(instance); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static void cxacru_poll_status(struct cxacru_data *instance) | ||
384 | { | ||
385 | u32 buf[CXINF_MAX] = {}; | ||
386 | struct device *dev = &instance->usbatm->usb_intf->dev; | ||
387 | struct atm_dev *atm_dev = instance->usbatm->atm_dev; | ||
388 | int ret; | ||
389 | |||
390 | ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX); | ||
391 | if (ret < 0) { | ||
392 | dev_warn(dev, "poll status: error %d\n", ret); | ||
393 | goto reschedule; | ||
394 | } | ||
395 | |||
396 | if (instance->line_status == buf[CXINF_LINE_STATUS]) | ||
397 | goto reschedule; | ||
398 | |||
399 | instance->line_status = buf[CXINF_LINE_STATUS]; | ||
400 | switch (instance->line_status) { | ||
401 | case 0: | ||
402 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
403 | dev_info(dev, "ADSL line: down\n"); | ||
404 | break; | ||
405 | |||
406 | case 1: | ||
407 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
408 | dev_info(dev, "ADSL line: attemtping to activate\n"); | ||
409 | break; | ||
410 | |||
411 | case 2: | ||
412 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
413 | dev_info(dev, "ADSL line: training\n"); | ||
414 | break; | ||
415 | |||
416 | case 3: | ||
417 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
418 | dev_info(dev, "ADSL line: channel analysis\n"); | ||
419 | break; | ||
420 | |||
421 | case 4: | ||
422 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
423 | dev_info(dev, "ADSL line: exchange\n"); | ||
424 | break; | ||
425 | |||
426 | case 5: | ||
427 | atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424; | ||
428 | atm_dev->signal = ATM_PHY_SIG_FOUND; | ||
429 | |||
430 | dev_info(dev, "ADSL line: up (%d Kib/s down | %d Kib/s up)\n", | ||
431 | buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]); | ||
432 | break; | ||
433 | |||
434 | case 6: | ||
435 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
436 | dev_info(dev, "ADSL line: waiting\n"); | ||
437 | break; | ||
438 | |||
439 | case 7: | ||
440 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
441 | dev_info(dev, "ADSL line: initializing\n"); | ||
442 | break; | ||
443 | |||
444 | default: | ||
445 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | ||
446 | dev_info(dev, "Unknown line state %02x\n", instance->line_status); | ||
447 | break; | ||
448 | } | ||
449 | reschedule: | ||
450 | schedule_delayed_work(&instance->poll_work, msecs_to_jiffies(POLL_INTERVAL)); | ||
451 | } | ||
452 | |||
453 | static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw, | ||
454 | u8 code1, u8 code2, u32 addr, u8 *data, int size) | ||
455 | { | ||
456 | int ret; | ||
457 | u8 *buf; | ||
458 | int offd, offb; | ||
459 | const int stride = CMD_PACKET_SIZE - 8; | ||
460 | |||
461 | buf = (u8 *) __get_free_page(GFP_KERNEL); | ||
462 | if (!buf) | ||
463 | return -ENOMEM; | ||
464 | |||
465 | offb = offd = 0; | ||
466 | do { | ||
467 | int l = min_t(int, stride, size - offd); | ||
468 | buf[offb++] = fw; | ||
469 | buf[offb++] = l; | ||
470 | buf[offb++] = code1; | ||
471 | buf[offb++] = code2; | ||
472 | *((u32 *) (buf + offb)) = cpu_to_le32(addr); | ||
473 | offb += 4; | ||
474 | addr += l; | ||
475 | if(l) | ||
476 | memcpy(buf + offb, data + offd, l); | ||
477 | if (l < stride) | ||
478 | memset(buf + offb + l, 0, stride - l); | ||
479 | offb += stride; | ||
480 | offd += stride; | ||
481 | if ((offb >= PAGE_SIZE) || (offd >= size)) { | ||
482 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD), | ||
483 | buf, offb, NULL, CMD_TIMEOUT); | ||
484 | if (ret < 0) { | ||
485 | dbg("sending fw %#x failed", fw); | ||
486 | goto cleanup; | ||
487 | } | ||
488 | offb = 0; | ||
489 | } | ||
490 | } while(offd < size); | ||
491 | dbg("sent fw %#x", fw); | ||
492 | |||
493 | ret = 0; | ||
494 | |||
495 | cleanup: | ||
496 | free_page((unsigned long) buf); | ||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | static void cxacru_upload_firmware(struct cxacru_data *instance, | ||
501 | const struct firmware *fw, | ||
502 | const struct firmware *bp, | ||
503 | const struct firmware *cf) | ||
504 | { | ||
505 | int ret; | ||
506 | int off; | ||
507 | struct usb_device *usb_dev = instance->usbatm->usb_dev; | ||
508 | struct device *dev = &instance->usbatm->usb_intf->dev; | ||
509 | u16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct }; | ||
510 | u32 val; | ||
511 | |||
512 | dbg("cxacru_upload_firmware"); | ||
513 | |||
514 | /* FirmwarePllFClkValue */ | ||
515 | val = cpu_to_le32(instance->modem_type->pll_f_clk); | ||
516 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4); | ||
517 | if (ret) { | ||
518 | dev_err(dev, "FirmwarePllFClkValue failed: %d\n", ret); | ||
519 | return; | ||
520 | } | ||
521 | |||
522 | /* FirmwarePllBClkValue */ | ||
523 | val = cpu_to_le32(instance->modem_type->pll_b_clk); | ||
524 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4); | ||
525 | if (ret) { | ||
526 | dev_err(dev, "FirmwarePllBClkValue failed: %d\n", ret); | ||
527 | return; | ||
528 | } | ||
529 | |||
530 | /* Enable SDRAM */ | ||
531 | val = cpu_to_le32(SDRAM_ENA); | ||
532 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4); | ||
533 | if (ret) { | ||
534 | dev_err(dev, "Enable SDRAM failed: %d\n", ret); | ||
535 | return; | ||
536 | } | ||
537 | |||
538 | /* Firmware */ | ||
539 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size); | ||
540 | if (ret) { | ||
541 | dev_err(dev, "Firmware upload failed: %d\n", ret); | ||
542 | return; | ||
543 | } | ||
544 | |||
545 | /* Boot ROM patch */ | ||
546 | if (instance->modem_type->boot_rom_patch) { | ||
547 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size); | ||
548 | if (ret) { | ||
549 | dev_err(dev, "Boot ROM patching failed: %d\n", ret); | ||
550 | return; | ||
551 | } | ||
552 | } | ||
553 | |||
554 | /* Signature */ | ||
555 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4); | ||
556 | if (ret) { | ||
557 | dev_err(dev, "Signature storing failed: %d\n", ret); | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | if (instance->modem_type->boot_rom_patch) { | ||
562 | val = cpu_to_le32(BR_ADDR); | ||
563 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4); | ||
564 | } | ||
565 | else { | ||
566 | ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0); | ||
567 | } | ||
568 | if (ret) { | ||
569 | dev_err(dev, "Passing control to firmware failed: %d\n", ret); | ||
570 | return; | ||
571 | } | ||
572 | |||
573 | /* Delay to allow firmware to start up. */ | ||
574 | msleep_interruptible(1000); | ||
575 | |||
576 | usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD)); | ||
577 | usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD)); | ||
578 | usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA)); | ||
579 | usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA)); | ||
580 | |||
581 | ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); | ||
582 | if (ret < 0) { | ||
583 | dev_err(dev, "modem failed to initialize: %d\n", ret); | ||
584 | return; | ||
585 | } | ||
586 | |||
587 | /* Load config data (le32), doing one packet at a time */ | ||
588 | if (cf) | ||
589 | for (off = 0; off < cf->size / 4; ) { | ||
590 | u32 buf[CMD_PACKET_SIZE / 4 - 1]; | ||
591 | int i, len = min_t(int, cf->size / 4 - off, CMD_PACKET_SIZE / 4 / 2 - 1); | ||
592 | buf[0] = cpu_to_le32(len); | ||
593 | for (i = 0; i < len; i++, off++) { | ||
594 | buf[i * 2 + 1] = cpu_to_le32(off); | ||
595 | memcpy(buf + i * 2 + 2, cf->data + off * 4, 4); | ||
596 | } | ||
597 | ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET, | ||
598 | (u8 *) buf, len, NULL, 0); | ||
599 | if (ret < 0) { | ||
600 | dev_err(dev, "load config data failed: %d\n", ret); | ||
601 | return; | ||
602 | } | ||
603 | } | ||
604 | |||
605 | msleep_interruptible(4000); | ||
606 | } | ||
607 | |||
608 | static int cxacru_find_firmware(struct cxacru_data *instance, | ||
609 | char* phase, const struct firmware **fw_p) | ||
610 | { | ||
611 | struct device *dev = &instance->usbatm->usb_intf->dev; | ||
612 | char buf[16]; | ||
613 | |||
614 | sprintf(buf, "cxacru-%s.bin", phase); | ||
615 | dbg("cxacru_find_firmware: looking for %s", buf); | ||
616 | |||
617 | if (request_firmware(fw_p, buf, dev)) { | ||
618 | dev_dbg(dev, "no stage %s firmware found\n", phase); | ||
619 | return -ENOENT; | ||
620 | } | ||
621 | |||
622 | dev_info(dev, "found firmware %s\n", buf); | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, | ||
628 | struct usb_interface *usb_intf) | ||
629 | { | ||
630 | struct device *dev = &usbatm_instance->usb_intf->dev; | ||
631 | const struct firmware *fw, *bp, *cf; | ||
632 | struct cxacru_data *instance = usbatm_instance->driver_data; | ||
633 | |||
634 | int ret = cxacru_find_firmware(instance, "fw", &fw); | ||
635 | if (ret) { | ||
636 | dev_warn(dev, "firmware (cxacru-fw.bin) unavailable (hotplug misconfiguration?)\n"); | ||
637 | return ret; | ||
638 | } | ||
639 | |||
640 | if (instance->modem_type->boot_rom_patch) { | ||
641 | ret = cxacru_find_firmware(instance, "bp", &bp); | ||
642 | if (ret) { | ||
643 | dev_warn(dev, "boot ROM patch (cxacru-bp.bin) unavailable (hotplug misconfiguration?)\n"); | ||
644 | release_firmware(fw); | ||
645 | return ret; | ||
646 | } | ||
647 | } | ||
648 | |||
649 | if (cxacru_find_firmware(instance, "cf", &cf)) /* optional */ | ||
650 | cf = NULL; | ||
651 | |||
652 | cxacru_upload_firmware(instance, fw, bp, cf); | ||
653 | |||
654 | if (cf) | ||
655 | release_firmware(cf); | ||
656 | if (instance->modem_type->boot_rom_patch) | ||
657 | release_firmware(bp); | ||
658 | release_firmware(fw); | ||
659 | |||
660 | ret = cxacru_card_status(instance); | ||
661 | if (ret) | ||
662 | dbg("modem initialisation failed"); | ||
663 | else | ||
664 | dbg("done setting up the modem"); | ||
665 | |||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | static int cxacru_bind(struct usbatm_data *usbatm_instance, | ||
670 | struct usb_interface *intf, const struct usb_device_id *id, | ||
671 | int *need_heavy_init) | ||
672 | { | ||
673 | struct cxacru_data *instance; | ||
674 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
675 | int ret; | ||
676 | |||
677 | /* instance init */ | ||
678 | instance = kmalloc(sizeof(*instance), GFP_KERNEL); | ||
679 | if (!instance) { | ||
680 | dbg("cxacru_bind: no memory for instance data"); | ||
681 | return -ENOMEM; | ||
682 | } | ||
683 | |||
684 | memset(instance, 0, sizeof(*instance)); | ||
685 | |||
686 | instance->usbatm = usbatm_instance; | ||
687 | instance->modem_type = (struct cxacru_modem_type *) id->driver_info; | ||
688 | |||
689 | instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL); | ||
690 | if (!instance->rcv_buf) { | ||
691 | dbg("cxacru_bind: no memory for rcv_buf"); | ||
692 | ret = -ENOMEM; | ||
693 | goto fail; | ||
694 | } | ||
695 | instance->snd_buf = (u8 *) __get_free_page(GFP_KERNEL); | ||
696 | if (!instance->snd_buf) { | ||
697 | dbg("cxacru_bind: no memory for snd_buf"); | ||
698 | ret = -ENOMEM; | ||
699 | goto fail; | ||
700 | } | ||
701 | instance->rcv_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
702 | if (!instance->rcv_urb) { | ||
703 | dbg("cxacru_bind: no memory for rcv_urb"); | ||
704 | ret = -ENOMEM; | ||
705 | goto fail; | ||
706 | } | ||
707 | instance->snd_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
708 | if (!instance->snd_urb) { | ||
709 | dbg("cxacru_bind: no memory for snd_urb"); | ||
710 | ret = -ENOMEM; | ||
711 | goto fail; | ||
712 | } | ||
713 | |||
714 | usb_fill_int_urb(instance->rcv_urb, | ||
715 | usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), | ||
716 | instance->rcv_buf, PAGE_SIZE, | ||
717 | cxacru_blocking_completion, &instance->rcv_done, 1); | ||
718 | instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK; | ||
719 | |||
720 | usb_fill_int_urb(instance->snd_urb, | ||
721 | usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD), | ||
722 | instance->snd_buf, PAGE_SIZE, | ||
723 | cxacru_blocking_completion, &instance->snd_done, 4); | ||
724 | instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK; | ||
725 | |||
726 | init_MUTEX(&instance->cm_serialize); | ||
727 | |||
728 | INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance); | ||
729 | |||
730 | usbatm_instance->driver_data = instance; | ||
731 | |||
732 | *need_heavy_init = cxacru_card_status(instance); | ||
733 | |||
734 | return 0; | ||
735 | |||
736 | fail: | ||
737 | free_page((unsigned long) instance->snd_buf); | ||
738 | free_page((unsigned long) instance->rcv_buf); | ||
739 | usb_free_urb(instance->snd_urb); | ||
740 | usb_free_urb(instance->rcv_urb); | ||
741 | kfree(instance); | ||
742 | |||
743 | return ret; | ||
744 | } | ||
745 | |||
746 | static void cxacru_unbind(struct usbatm_data *usbatm_instance, | ||
747 | struct usb_interface *intf) | ||
748 | { | ||
749 | struct cxacru_data *instance = usbatm_instance->driver_data; | ||
750 | |||
751 | dbg("cxacru_unbind entered"); | ||
752 | |||
753 | if (!instance) { | ||
754 | dbg("cxacru_unbind: NULL instance!"); | ||
755 | return; | ||
756 | } | ||
757 | |||
758 | while (!cancel_delayed_work(&instance->poll_work)) | ||
759 | flush_scheduled_work(); | ||
760 | |||
761 | usb_kill_urb(instance->snd_urb); | ||
762 | usb_kill_urb(instance->rcv_urb); | ||
763 | usb_free_urb(instance->snd_urb); | ||
764 | usb_free_urb(instance->rcv_urb); | ||
765 | |||
766 | free_page((unsigned long) instance->snd_buf); | ||
767 | free_page((unsigned long) instance->rcv_buf); | ||
768 | kfree(instance); | ||
769 | |||
770 | usbatm_instance->driver_data = NULL; | ||
771 | } | ||
772 | |||
773 | static const struct cxacru_modem_type cxacru_cafe = { | ||
774 | .pll_f_clk = 0x02d874df, | ||
775 | .pll_b_clk = 0x0196a51a, | ||
776 | .boot_rom_patch = 1, | ||
777 | }; | ||
778 | |||
779 | static const struct cxacru_modem_type cxacru_cb00 = { | ||
780 | .pll_f_clk = 0x5, | ||
781 | .pll_b_clk = 0x3, | ||
782 | .boot_rom_patch = 0, | ||
783 | }; | ||
784 | |||
785 | static const struct usb_device_id cxacru_usb_ids[] = { | ||
786 | { /* V = Conexant P = ADSL modem (Euphrates project) */ | ||
787 | USB_DEVICE(0x0572, 0xcafe), .driver_info = (unsigned long) &cxacru_cafe | ||
788 | }, | ||
789 | { /* V = Conexant P = ADSL modem (Hasbani project) */ | ||
790 | USB_DEVICE(0x0572, 0xcb00), .driver_info = (unsigned long) &cxacru_cb00 | ||
791 | }, | ||
792 | { /* V = Conexant P = ADSL modem */ | ||
793 | USB_DEVICE(0x0572, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00 | ||
794 | }, | ||
795 | { /* V = Conexant P = ADSL modem */ | ||
796 | USB_DEVICE(0x0572, 0xcb06), .driver_info = (unsigned long) &cxacru_cb00 | ||
797 | }, | ||
798 | { /* V = Olitec P = ADSL modem version 2 */ | ||
799 | USB_DEVICE(0x08e3, 0x0100), .driver_info = (unsigned long) &cxacru_cafe | ||
800 | }, | ||
801 | { /* V = Olitec P = ADSL modem version 3 */ | ||
802 | USB_DEVICE(0x08e3, 0x0102), .driver_info = (unsigned long) &cxacru_cb00 | ||
803 | }, | ||
804 | { /* V = Trust/Amigo Technology Co. P = AMX-CA86U */ | ||
805 | USB_DEVICE(0x0eb0, 0x3457), .driver_info = (unsigned long) &cxacru_cafe | ||
806 | }, | ||
807 | { /* V = Zoom P = 5510 */ | ||
808 | USB_DEVICE(0x1803, 0x5510), .driver_info = (unsigned long) &cxacru_cb00 | ||
809 | }, | ||
810 | { /* V = Draytek P = Vigor 318 */ | ||
811 | USB_DEVICE(0x0675, 0x0200), .driver_info = (unsigned long) &cxacru_cb00 | ||
812 | }, | ||
813 | { /* V = Zyxel P = 630-C1 aka OMNI ADSL USB (Annex A) */ | ||
814 | USB_DEVICE(0x0586, 0x330a), .driver_info = (unsigned long) &cxacru_cb00 | ||
815 | }, | ||
816 | { /* V = Zyxel P = 630-C3 aka OMNI ADSL USB (Annex B) */ | ||
817 | USB_DEVICE(0x0586, 0x330b), .driver_info = (unsigned long) &cxacru_cb00 | ||
818 | }, | ||
819 | { /* V = Aethra P = Starmodem UM1020 */ | ||
820 | USB_DEVICE(0x0659, 0x0020), .driver_info = (unsigned long) &cxacru_cb00 | ||
821 | }, | ||
822 | { /* V = Aztech Systems P = ? AKA Pirelli AUA-010 */ | ||
823 | USB_DEVICE(0x0509, 0x0812), .driver_info = (unsigned long) &cxacru_cb00 | ||
824 | }, | ||
825 | { /* V = Netopia P = Cayman 3341(Annex A)/3351(Annex B) */ | ||
826 | USB_DEVICE(0x100d, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00 | ||
827 | }, | ||
828 | { /* V = Netopia P = Cayman 3342(Annex A)/3352(Annex B) */ | ||
829 | USB_DEVICE(0x100d, 0x3342), .driver_info = (unsigned long) &cxacru_cb00 | ||
830 | }, | ||
831 | {} | ||
832 | }; | ||
833 | |||
834 | MODULE_DEVICE_TABLE(usb, cxacru_usb_ids); | ||
835 | |||
836 | static struct usbatm_driver cxacru_driver = { | ||
837 | .owner = THIS_MODULE, | ||
838 | .driver_name = cxacru_driver_name, | ||
839 | .bind = cxacru_bind, | ||
840 | .heavy_init = cxacru_heavy_init, | ||
841 | .unbind = cxacru_unbind, | ||
842 | .atm_start = cxacru_atm_start, | ||
843 | .in = CXACRU_EP_DATA, | ||
844 | .out = CXACRU_EP_DATA, | ||
845 | .rx_padding = 3, | ||
846 | .tx_padding = 11, | ||
847 | }; | ||
848 | |||
849 | static int cxacru_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
850 | { | ||
851 | return usbatm_usb_probe(intf, id, &cxacru_driver); | ||
852 | } | ||
853 | |||
854 | static struct usb_driver cxacru_usb_driver = { | ||
855 | .owner = THIS_MODULE, | ||
856 | .name = cxacru_driver_name, | ||
857 | .probe = cxacru_usb_probe, | ||
858 | .disconnect = usbatm_usb_disconnect, | ||
859 | .id_table = cxacru_usb_ids | ||
860 | }; | ||
861 | |||
862 | static int __init cxacru_init(void) | ||
863 | { | ||
864 | return usb_register(&cxacru_usb_driver); | ||
865 | } | ||
866 | |||
867 | static void __exit cxacru_cleanup(void) | ||
868 | { | ||
869 | usb_deregister(&cxacru_usb_driver); | ||
870 | } | ||
871 | |||
872 | module_init(cxacru_init); | ||
873 | module_exit(cxacru_cleanup); | ||
874 | |||
875 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
876 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
877 | MODULE_LICENSE("GPL"); | ||
878 | MODULE_VERSION(DRIVER_VERSION); | ||
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 2a1697bfd695..6a6eaa2a3b1c 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * Copyright (C) 2003, Duncan Sands | 5 | * Copyright (C) 2003, Duncan Sands |
6 | * Copyright (C) 2004, David Woodhouse | 6 | * Copyright (C) 2004, David Woodhouse |
7 | * | 7 | * |
8 | * Based on "modem_run.c", copyright (C) 2001, Benoit Papillault | ||
9 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the Free | 11 | * under the terms of the GNU General Public License as published by the Free |
10 | * Software Foundation; either version 2 of the License, or (at your option) | 12 | * Software Foundation; either version 2 of the License, or (at your option) |
@@ -21,821 +23,798 @@ | |||
21 | * | 23 | * |
22 | ******************************************************************************/ | 24 | ******************************************************************************/ |
23 | 25 | ||
24 | #include <linux/module.h> | 26 | #include <asm/page.h> |
25 | #include <linux/moduleparam.h> | 27 | #include <linux/device.h> |
28 | #include <linux/errno.h> | ||
29 | #include <linux/firmware.h> | ||
26 | #include <linux/gfp.h> | 30 | #include <linux/gfp.h> |
31 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
28 | #include <linux/sched.h> | 33 | #include <linux/module.h> |
29 | #include <linux/timer.h> | 34 | #include <linux/moduleparam.h> |
30 | #include <linux/errno.h> | ||
31 | #include <linux/proc_fs.h> | ||
32 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
33 | #include <linux/wait.h> | 36 | #include <linux/stat.h> |
34 | #include <linux/list.h> | 37 | #include <linux/timer.h> |
35 | #include <asm/processor.h> | 38 | #include <linux/workqueue.h> |
36 | #include <asm/uaccess.h> | ||
37 | #include <linux/smp_lock.h> | ||
38 | #include <linux/interrupt.h> | ||
39 | #include <linux/atm.h> | ||
40 | #include <linux/atmdev.h> | ||
41 | #include <linux/crc32.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/firmware.h> | ||
44 | |||
45 | #include "usb_atm.h" | ||
46 | 39 | ||
47 | #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) | 40 | #include "usbatm.h" |
48 | # define USE_FW_LOADER | ||
49 | #endif | ||
50 | 41 | ||
51 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" | 42 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" |
52 | #define DRIVER_VERSION "1.8" | 43 | #define DRIVER_VERSION "1.9" |
53 | #define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION | 44 | #define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION |
54 | 45 | ||
55 | static const char speedtch_driver_name[] = "speedtch"; | 46 | static const char speedtch_driver_name[] = "speedtch"; |
56 | 47 | ||
57 | #define SPEEDTOUCH_VENDORID 0x06b9 | 48 | #define CTRL_TIMEOUT 2000 /* milliseconds */ |
58 | #define SPEEDTOUCH_PRODUCTID 0x4061 | 49 | #define DATA_TIMEOUT 2000 /* milliseconds */ |
59 | 50 | ||
60 | /* Timeout in jiffies */ | 51 | #define OFFSET_7 0 /* size 1 */ |
61 | #define CTRL_TIMEOUT 2000 | 52 | #define OFFSET_b 1 /* size 8 */ |
62 | #define DATA_TIMEOUT 2000 | 53 | #define OFFSET_d 9 /* size 4 */ |
54 | #define OFFSET_e 13 /* size 1 */ | ||
55 | #define OFFSET_f 14 /* size 1 */ | ||
56 | #define TOTAL 15 | ||
63 | 57 | ||
64 | #define OFFSET_7 0 /* size 1 */ | 58 | #define SIZE_7 1 |
65 | #define OFFSET_b 1 /* size 8 */ | 59 | #define SIZE_b 8 |
66 | #define OFFSET_d 9 /* size 4 */ | 60 | #define SIZE_d 4 |
67 | #define OFFSET_e 13 /* size 1 */ | 61 | #define SIZE_e 1 |
68 | #define OFFSET_f 14 /* size 1 */ | 62 | #define SIZE_f 1 |
69 | #define TOTAL 15 | ||
70 | 63 | ||
71 | #define SIZE_7 1 | 64 | #define MIN_POLL_DELAY 5000 /* milliseconds */ |
72 | #define SIZE_b 8 | 65 | #define MAX_POLL_DELAY 60000 /* milliseconds */ |
73 | #define SIZE_d 4 | ||
74 | #define SIZE_e 1 | ||
75 | #define SIZE_f 1 | ||
76 | 66 | ||
77 | static int dl_512_first = 0; | 67 | #define RESUBMIT_DELAY 1000 /* milliseconds */ |
78 | static int sw_buffering = 0; | ||
79 | 68 | ||
80 | module_param(dl_512_first, bool, 0444); | 69 | #define DEFAULT_ALTSETTING 1 |
81 | MODULE_PARM_DESC(dl_512_first, "Read 512 bytes before sending firmware"); | 70 | #define DEFAULT_DL_512_FIRST 0 |
71 | #define DEFAULT_SW_BUFFERING 0 | ||
82 | 72 | ||
83 | module_param(sw_buffering, uint, 0444); | 73 | static int altsetting = DEFAULT_ALTSETTING; |
84 | MODULE_PARM_DESC(sw_buffering, "Enable software buffering"); | 74 | static int dl_512_first = DEFAULT_DL_512_FIRST; |
75 | static int sw_buffering = DEFAULT_SW_BUFFERING; | ||
85 | 76 | ||
86 | #define UDSL_IOCTL_LINE_UP 1 | 77 | module_param(altsetting, int, S_IRUGO | S_IWUSR); |
87 | #define UDSL_IOCTL_LINE_DOWN 2 | 78 | MODULE_PARM_DESC(altsetting, |
79 | "Alternative setting for data interface (default: " | ||
80 | __MODULE_STRING(DEFAULT_ALTSETTING) ")"); | ||
88 | 81 | ||
89 | #define SPEEDTCH_ENDPOINT_INT 0x81 | 82 | module_param(dl_512_first, bool, S_IRUGO | S_IWUSR); |
90 | #define SPEEDTCH_ENDPOINT_DATA 0x07 | 83 | MODULE_PARM_DESC(dl_512_first, |
91 | #define SPEEDTCH_ENDPOINT_FIRMWARE 0x05 | 84 | "Read 512 bytes before sending firmware (default: " |
85 | __MODULE_STRING(DEFAULT_DL_512_FIRST) ")"); | ||
92 | 86 | ||
93 | #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) | 87 | module_param(sw_buffering, bool, S_IRUGO | S_IWUSR); |
88 | MODULE_PARM_DESC(sw_buffering, | ||
89 | "Enable software buffering (default: " | ||
90 | __MODULE_STRING(DEFAULT_SW_BUFFERING) ")"); | ||
94 | 91 | ||
95 | static struct usb_device_id speedtch_usb_ids[] = { | 92 | #define ENDPOINT_INT 0x81 |
96 | {USB_DEVICE(SPEEDTOUCH_VENDORID, SPEEDTOUCH_PRODUCTID)}, | 93 | #define ENDPOINT_DATA 0x07 |
97 | {} | 94 | #define ENDPOINT_FIRMWARE 0x05 |
98 | }; | ||
99 | 95 | ||
100 | MODULE_DEVICE_TABLE(usb, speedtch_usb_ids); | 96 | #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) |
101 | 97 | ||
102 | struct speedtch_instance_data { | 98 | struct speedtch_instance_data { |
103 | struct udsl_instance_data u; | 99 | struct usbatm_data *usbatm; |
100 | |||
101 | struct work_struct status_checker; | ||
104 | 102 | ||
105 | /* Status */ | 103 | int poll_delay; /* milliseconds */ |
104 | |||
105 | struct timer_list resubmit_timer; | ||
106 | struct urb *int_urb; | 106 | struct urb *int_urb; |
107 | unsigned char int_data[16]; | 107 | unsigned char int_data[16]; |
108 | struct work_struct poll_work; | ||
109 | struct timer_list poll_timer; | ||
110 | }; | ||
111 | /* USB */ | ||
112 | |||
113 | static int speedtch_usb_probe(struct usb_interface *intf, | ||
114 | const struct usb_device_id *id); | ||
115 | static void speedtch_usb_disconnect(struct usb_interface *intf); | ||
116 | static int speedtch_usb_ioctl(struct usb_interface *intf, unsigned int code, | ||
117 | void *user_data); | ||
118 | static void speedtch_handle_int(struct urb *urb, struct pt_regs *regs); | ||
119 | static void speedtch_poll_status(struct speedtch_instance_data *instance); | ||
120 | 108 | ||
121 | static struct usb_driver speedtch_usb_driver = { | 109 | unsigned char scratch_buffer[TOTAL]; |
122 | .owner = THIS_MODULE, | ||
123 | .name = speedtch_driver_name, | ||
124 | .probe = speedtch_usb_probe, | ||
125 | .disconnect = speedtch_usb_disconnect, | ||
126 | .ioctl = speedtch_usb_ioctl, | ||
127 | .id_table = speedtch_usb_ids, | ||
128 | }; | 110 | }; |
129 | 111 | ||
130 | /*************** | 112 | /*************** |
131 | ** firmware ** | 113 | ** firmware ** |
132 | ***************/ | 114 | ***************/ |
133 | 115 | ||
134 | static void speedtch_got_firmware(struct speedtch_instance_data *instance, | 116 | static void speedtch_set_swbuff(struct speedtch_instance_data *instance, int state) |
135 | int got_it) | ||
136 | { | 117 | { |
137 | int err; | 118 | struct usbatm_data *usbatm = instance->usbatm; |
138 | struct usb_interface *intf; | 119 | struct usb_device *usb_dev = usbatm->usb_dev; |
139 | |||
140 | down(&instance->u.serialize); /* vs self, speedtch_firmware_start */ | ||
141 | if (instance->u.status == UDSL_LOADED_FIRMWARE) | ||
142 | goto out; | ||
143 | if (!got_it) { | ||
144 | instance->u.status = UDSL_NO_FIRMWARE; | ||
145 | goto out; | ||
146 | } | ||
147 | if ((err = usb_set_interface(instance->u.usb_dev, 1, 1)) < 0) { | ||
148 | dbg("speedtch_got_firmware: usb_set_interface returned %d!", err); | ||
149 | instance->u.status = UDSL_NO_FIRMWARE; | ||
150 | goto out; | ||
151 | } | ||
152 | |||
153 | /* Set up interrupt endpoint */ | ||
154 | intf = usb_ifnum_to_if(instance->u.usb_dev, 0); | ||
155 | if (intf && !usb_driver_claim_interface(&speedtch_usb_driver, intf, NULL)) { | ||
156 | |||
157 | instance->int_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
158 | if (instance->int_urb) { | ||
159 | |||
160 | usb_fill_int_urb(instance->int_urb, instance->u.usb_dev, | ||
161 | usb_rcvintpipe(instance->u.usb_dev, SPEEDTCH_ENDPOINT_INT), | ||
162 | instance->int_data, | ||
163 | sizeof(instance->int_data), | ||
164 | speedtch_handle_int, instance, 50); | ||
165 | err = usb_submit_urb(instance->int_urb, GFP_KERNEL); | ||
166 | if (err) { | ||
167 | /* Doesn't matter; we'll poll anyway */ | ||
168 | dbg("speedtch_got_firmware: Submission of interrupt URB failed %d", err); | ||
169 | usb_free_urb(instance->int_urb); | ||
170 | instance->int_urb = NULL; | ||
171 | usb_driver_release_interface(&speedtch_usb_driver, intf); | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | /* Start status polling */ | ||
176 | mod_timer(&instance->poll_timer, jiffies + (1 * HZ)); | ||
177 | |||
178 | instance->u.status = UDSL_LOADED_FIRMWARE; | ||
179 | tasklet_schedule(&instance->u.receive_tasklet); | ||
180 | out: | ||
181 | up(&instance->u.serialize); | ||
182 | wake_up_interruptible(&instance->u.firmware_waiters); | ||
183 | } | ||
184 | |||
185 | static int speedtch_set_swbuff(struct speedtch_instance_data *instance, | ||
186 | int state) | ||
187 | { | ||
188 | struct usb_device *dev = instance->u.usb_dev; | ||
189 | int ret; | 120 | int ret; |
190 | 121 | ||
191 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 122 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
192 | 0x32, 0x40, state ? 0x01 : 0x00, | 123 | 0x32, 0x40, state ? 0x01 : 0x00, 0x00, NULL, 0, CTRL_TIMEOUT); |
193 | 0x00, NULL, 0, 100); | 124 | if (ret < 0) |
194 | if (ret < 0) { | 125 | usb_warn(usbatm, |
195 | printk("Warning: %sabling SW buffering: usb_control_msg returned %d\n", | 126 | "%sabling SW buffering: usb_control_msg returned %d\n", |
196 | state ? "En" : "Dis", ret); | 127 | state ? "En" : "Dis", ret); |
197 | return ret; | 128 | else |
198 | } | 129 | dbg("speedtch_set_swbuff: %sbled SW buffering", state ? "En" : "Dis"); |
199 | |||
200 | dbg("speedtch_set_swbuff: %sbled SW buffering", state ? "En" : "Dis"); | ||
201 | return 0; | ||
202 | } | 130 | } |
203 | 131 | ||
204 | static void speedtch_test_sequence(struct speedtch_instance_data *instance) | 132 | static void speedtch_test_sequence(struct speedtch_instance_data *instance) |
205 | { | 133 | { |
206 | struct usb_device *dev = instance->u.usb_dev; | 134 | struct usbatm_data *usbatm = instance->usbatm; |
207 | unsigned char buf[10]; | 135 | struct usb_device *usb_dev = usbatm->usb_dev; |
136 | unsigned char *buf = instance->scratch_buffer; | ||
208 | int ret; | 137 | int ret; |
209 | 138 | ||
210 | /* URB 147 */ | 139 | /* URB 147 */ |
211 | buf[0] = 0x1c; | 140 | buf[0] = 0x1c; |
212 | buf[1] = 0x50; | 141 | buf[1] = 0x50; |
213 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 142 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
214 | 0x01, 0x40, 0x0b, 0x00, buf, 2, 100); | 143 | 0x01, 0x40, 0x0b, 0x00, buf, 2, CTRL_TIMEOUT); |
215 | if (ret < 0) | 144 | if (ret < 0) |
216 | printk(KERN_WARNING "%s failed on URB147: %d\n", __func__, ret); | 145 | usb_warn(usbatm, "%s failed on URB147: %d\n", __func__, ret); |
217 | 146 | ||
218 | /* URB 148 */ | 147 | /* URB 148 */ |
219 | buf[0] = 0x32; | 148 | buf[0] = 0x32; |
220 | buf[1] = 0x00; | 149 | buf[1] = 0x00; |
221 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 150 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
222 | 0x01, 0x40, 0x02, 0x00, buf, 2, 100); | 151 | 0x01, 0x40, 0x02, 0x00, buf, 2, CTRL_TIMEOUT); |
223 | if (ret < 0) | 152 | if (ret < 0) |
224 | printk(KERN_WARNING "%s failed on URB148: %d\n", __func__, ret); | 153 | usb_warn(usbatm, "%s failed on URB148: %d\n", __func__, ret); |
225 | 154 | ||
226 | /* URB 149 */ | 155 | /* URB 149 */ |
227 | buf[0] = 0x01; | 156 | buf[0] = 0x01; |
228 | buf[1] = 0x00; | 157 | buf[1] = 0x00; |
229 | buf[2] = 0x01; | 158 | buf[2] = 0x01; |
230 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 159 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
231 | 0x01, 0x40, 0x03, 0x00, buf, 3, 100); | 160 | 0x01, 0x40, 0x03, 0x00, buf, 3, CTRL_TIMEOUT); |
232 | if (ret < 0) | 161 | if (ret < 0) |
233 | printk(KERN_WARNING "%s failed on URB149: %d\n", __func__, ret); | 162 | usb_warn(usbatm, "%s failed on URB149: %d\n", __func__, ret); |
234 | 163 | ||
235 | /* URB 150 */ | 164 | /* URB 150 */ |
236 | buf[0] = 0x01; | 165 | buf[0] = 0x01; |
237 | buf[1] = 0x00; | 166 | buf[1] = 0x00; |
238 | buf[2] = 0x01; | 167 | buf[2] = 0x01; |
239 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 168 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
240 | 0x01, 0x40, 0x04, 0x00, buf, 3, 100); | 169 | 0x01, 0x40, 0x04, 0x00, buf, 3, CTRL_TIMEOUT); |
241 | if (ret < 0) | 170 | if (ret < 0) |
242 | printk(KERN_WARNING "%s failed on URB150: %d\n", __func__, ret); | 171 | usb_warn(usbatm, "%s failed on URB150: %d\n", __func__, ret); |
243 | } | 172 | } |
244 | 173 | ||
245 | static int speedtch_start_synchro(struct speedtch_instance_data *instance) | 174 | static int speedtch_upload_firmware(struct speedtch_instance_data *instance, |
175 | const struct firmware *fw1, | ||
176 | const struct firmware *fw2) | ||
246 | { | 177 | { |
247 | struct usb_device *dev = instance->u.usb_dev; | 178 | unsigned char *buffer; |
248 | unsigned char buf[2]; | 179 | struct usbatm_data *usbatm = instance->usbatm; |
249 | int ret; | 180 | struct usb_interface *intf; |
181 | struct usb_device *usb_dev = usbatm->usb_dev; | ||
182 | int actual_length; | ||
183 | int ret = 0; | ||
184 | int offset; | ||
185 | |||
186 | usb_dbg(usbatm, "%s entered\n", __func__); | ||
187 | |||
188 | if (!(buffer = (unsigned char *)__get_free_page(GFP_KERNEL))) { | ||
189 | ret = -ENOMEM; | ||
190 | usb_dbg(usbatm, "%s: no memory for buffer!\n", __func__); | ||
191 | goto out; | ||
192 | } | ||
193 | |||
194 | if (!(intf = usb_ifnum_to_if(usb_dev, 2))) { | ||
195 | ret = -ENODEV; | ||
196 | usb_dbg(usbatm, "%s: interface not found!\n", __func__); | ||
197 | goto out_free; | ||
198 | } | ||
199 | |||
200 | /* URB 7 */ | ||
201 | if (dl_512_first) { /* some modems need a read before writing the firmware */ | ||
202 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
203 | buffer, 0x200, &actual_length, 2000); | ||
204 | |||
205 | if (ret < 0 && ret != -ETIMEDOUT) | ||
206 | usb_dbg(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret); | ||
207 | else | ||
208 | usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret); | ||
209 | } | ||
210 | |||
211 | /* URB 8 : both leds are static green */ | ||
212 | for (offset = 0; offset < fw1->size; offset += PAGE_SIZE) { | ||
213 | int thislen = min_t(int, PAGE_SIZE, fw1->size - offset); | ||
214 | memcpy(buffer, fw1->data + offset, thislen); | ||
215 | |||
216 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
217 | buffer, thislen, &actual_length, DATA_TIMEOUT); | ||
218 | |||
219 | if (ret < 0) { | ||
220 | usb_dbg(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret); | ||
221 | goto out_free; | ||
222 | } | ||
223 | usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size); | ||
224 | } | ||
225 | |||
226 | /* USB led blinking green, ADSL led off */ | ||
227 | |||
228 | /* URB 11 */ | ||
229 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
230 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | ||
250 | 231 | ||
251 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
252 | 0x12, 0xc0, 0x04, 0x00, | ||
253 | buf, sizeof(buf), CTRL_TIMEOUT); | ||
254 | if (ret < 0) { | 232 | if (ret < 0) { |
255 | printk(KERN_WARNING "SpeedTouch: Failed to start ADSL synchronisation: %d\n", ret); | 233 | usb_dbg(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret); |
256 | return ret; | 234 | goto out_free; |
257 | } | 235 | } |
236 | usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length); | ||
258 | 237 | ||
259 | dbg("speedtch_start_synchro: modem prodded. %d Bytes returned: %02x %02x", ret, buf[0], buf[1]); | 238 | /* URBs 12 to 139 - USB led blinking green, ADSL led off */ |
260 | return 0; | 239 | for (offset = 0; offset < fw2->size; offset += PAGE_SIZE) { |
240 | int thislen = min_t(int, PAGE_SIZE, fw2->size - offset); | ||
241 | memcpy(buffer, fw2->data + offset, thislen); | ||
242 | |||
243 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
244 | buffer, thislen, &actual_length, DATA_TIMEOUT); | ||
245 | |||
246 | if (ret < 0) { | ||
247 | usb_dbg(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret); | ||
248 | goto out_free; | ||
249 | } | ||
250 | } | ||
251 | usb_dbg(usbatm, "%s: BLOCK3 uploaded (%zu bytes)\n", __func__, fw2->size); | ||
252 | |||
253 | /* USB led static green, ADSL led static red */ | ||
254 | |||
255 | /* URB 142 */ | ||
256 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
257 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | ||
258 | |||
259 | if (ret < 0) { | ||
260 | usb_dbg(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret); | ||
261 | goto out_free; | ||
262 | } | ||
263 | |||
264 | /* success */ | ||
265 | usb_dbg(usbatm, "%s: BLOCK4 downloaded (%d bytes)\n", __func__, actual_length); | ||
266 | |||
267 | /* Delay to allow firmware to start up. We can do this here | ||
268 | because we're in our own kernel thread anyway. */ | ||
269 | msleep_interruptible(1000); | ||
270 | |||
271 | /* Enable software buffering, if requested */ | ||
272 | if (sw_buffering) | ||
273 | speedtch_set_swbuff(instance, 1); | ||
274 | |||
275 | /* Magic spell; don't ask us what this does */ | ||
276 | speedtch_test_sequence(instance); | ||
277 | |||
278 | ret = 0; | ||
279 | |||
280 | out_free: | ||
281 | free_page((unsigned long)buffer); | ||
282 | out: | ||
283 | return ret; | ||
261 | } | 284 | } |
262 | 285 | ||
263 | static void speedtch_handle_int(struct urb *urb, struct pt_regs *regs) | 286 | static int speedtch_find_firmware(struct usb_interface *intf, int phase, |
287 | const struct firmware **fw_p) | ||
264 | { | 288 | { |
265 | struct speedtch_instance_data *instance = urb->context; | 289 | struct device *dev = &intf->dev; |
266 | unsigned int count = urb->actual_length; | 290 | const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice); |
267 | int ret; | 291 | const u8 major_revision = bcdDevice >> 8; |
292 | const u8 minor_revision = bcdDevice & 0xff; | ||
293 | char buf[24]; | ||
268 | 294 | ||
269 | /* The magic interrupt for "up state" */ | 295 | sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision); |
270 | const static unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 }; | 296 | dev_dbg(dev, "%s: looking for %s\n", __func__, buf); |
271 | /* The magic interrupt for "down state" */ | ||
272 | const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
273 | 297 | ||
274 | switch (urb->status) { | 298 | if (request_firmware(fw_p, buf, dev)) { |
275 | case 0: | 299 | sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision); |
276 | /* success */ | 300 | dev_dbg(dev, "%s: looking for %s\n", __func__, buf); |
277 | break; | ||
278 | case -ECONNRESET: | ||
279 | case -ENOENT: | ||
280 | case -ESHUTDOWN: | ||
281 | /* this urb is terminated; clean up */ | ||
282 | dbg("%s - urb shutting down with status: %d", __func__, urb->status); | ||
283 | return; | ||
284 | default: | ||
285 | dbg("%s - nonzero urb status received: %d", __func__, urb->status); | ||
286 | goto exit; | ||
287 | } | ||
288 | 301 | ||
289 | if (count < 6) { | 302 | if (request_firmware(fw_p, buf, dev)) { |
290 | dbg("%s - int packet too short", __func__); | 303 | sprintf(buf, "speedtch-%d.bin", phase); |
291 | goto exit; | 304 | dev_dbg(dev, "%s: looking for %s\n", __func__, buf); |
305 | |||
306 | if (request_firmware(fw_p, buf, dev)) { | ||
307 | dev_warn(dev, "no stage %d firmware found!\n", phase); | ||
308 | return -ENOENT; | ||
309 | } | ||
310 | } | ||
292 | } | 311 | } |
293 | 312 | ||
294 | if (!memcmp(up_int, instance->int_data, 6)) { | 313 | dev_info(dev, "found stage %d firmware %s\n", phase, buf); |
295 | del_timer(&instance->poll_timer); | ||
296 | printk(KERN_NOTICE "DSL line goes up\n"); | ||
297 | } else if (!memcmp(down_int, instance->int_data, 6)) { | ||
298 | printk(KERN_NOTICE "DSL line goes down\n"); | ||
299 | } else { | ||
300 | int i; | ||
301 | 314 | ||
302 | printk(KERN_DEBUG "Unknown interrupt packet of %d bytes:", count); | 315 | return 0; |
303 | for (i = 0; i < count; i++) | 316 | } |
304 | printk(" %02x", instance->int_data[i]); | 317 | |
305 | printk("\n"); | 318 | static int speedtch_heavy_init(struct usbatm_data *usbatm, struct usb_interface *intf) |
319 | { | ||
320 | const struct firmware *fw1, *fw2; | ||
321 | struct speedtch_instance_data *instance = usbatm->driver_data; | ||
322 | int ret; | ||
323 | |||
324 | if ((ret = speedtch_find_firmware(intf, 1, &fw1)) < 0) | ||
325 | return ret; | ||
326 | |||
327 | if ((ret = speedtch_find_firmware(intf, 2, &fw2)) < 0) { | ||
328 | release_firmware(fw1); | ||
329 | return ret; | ||
306 | } | 330 | } |
307 | schedule_work(&instance->poll_work); | ||
308 | 331 | ||
309 | exit: | 332 | ret = speedtch_upload_firmware(instance, fw1, fw2); |
310 | rmb(); | 333 | |
311 | if (!instance->int_urb) | 334 | release_firmware(fw2); |
312 | return; | 335 | release_firmware(fw1); |
313 | 336 | ||
314 | ret = usb_submit_urb(urb, GFP_ATOMIC); | 337 | return ret; |
315 | if (ret) | ||
316 | err("%s - usb_submit_urb failed with result %d", __func__, ret); | ||
317 | } | 338 | } |
318 | 339 | ||
319 | static int speedtch_get_status(struct speedtch_instance_data *instance, | 340 | |
320 | unsigned char *buf) | 341 | /********** |
342 | ** ATM ** | ||
343 | **********/ | ||
344 | |||
345 | static int speedtch_read_status(struct speedtch_instance_data *instance) | ||
321 | { | 346 | { |
322 | struct usb_device *dev = instance->u.usb_dev; | 347 | struct usbatm_data *usbatm = instance->usbatm; |
348 | struct usb_device *usb_dev = usbatm->usb_dev; | ||
349 | unsigned char *buf = instance->scratch_buffer; | ||
323 | int ret; | 350 | int ret; |
324 | 351 | ||
325 | memset(buf, 0, TOTAL); | 352 | memset(buf, 0, TOTAL); |
326 | 353 | ||
327 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 354 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
328 | 0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7, | 355 | 0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7, |
329 | CTRL_TIMEOUT); | 356 | CTRL_TIMEOUT); |
330 | if (ret < 0) { | 357 | if (ret < 0) { |
331 | dbg("MSG 7 failed"); | 358 | atm_dbg(usbatm, "%s: MSG 7 failed\n", __func__); |
332 | return ret; | 359 | return ret; |
333 | } | 360 | } |
334 | 361 | ||
335 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 362 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
336 | 0x12, 0xc0, 0x0b, 0x00, buf + OFFSET_b, SIZE_b, | 363 | 0x12, 0xc0, 0x0b, 0x00, buf + OFFSET_b, SIZE_b, |
337 | CTRL_TIMEOUT); | 364 | CTRL_TIMEOUT); |
338 | if (ret < 0) { | 365 | if (ret < 0) { |
339 | dbg("MSG B failed"); | 366 | atm_dbg(usbatm, "%s: MSG B failed\n", __func__); |
340 | return ret; | 367 | return ret; |
341 | } | 368 | } |
342 | 369 | ||
343 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 370 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
344 | 0x12, 0xc0, 0x0d, 0x00, buf + OFFSET_d, SIZE_d, | 371 | 0x12, 0xc0, 0x0d, 0x00, buf + OFFSET_d, SIZE_d, |
345 | CTRL_TIMEOUT); | 372 | CTRL_TIMEOUT); |
346 | if (ret < 0) { | 373 | if (ret < 0) { |
347 | dbg("MSG D failed"); | 374 | atm_dbg(usbatm, "%s: MSG D failed\n", __func__); |
348 | return ret; | 375 | return ret; |
349 | } | 376 | } |
350 | 377 | ||
351 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 378 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
352 | 0x01, 0xc0, 0x0e, 0x00, buf + OFFSET_e, SIZE_e, | 379 | 0x01, 0xc0, 0x0e, 0x00, buf + OFFSET_e, SIZE_e, |
353 | CTRL_TIMEOUT); | 380 | CTRL_TIMEOUT); |
354 | if (ret < 0) { | 381 | if (ret < 0) { |
355 | dbg("MSG E failed"); | 382 | atm_dbg(usbatm, "%s: MSG E failed\n", __func__); |
356 | return ret; | 383 | return ret; |
357 | } | 384 | } |
358 | 385 | ||
359 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 386 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
360 | 0x01, 0xc0, 0x0f, 0x00, buf + OFFSET_f, SIZE_f, | 387 | 0x01, 0xc0, 0x0f, 0x00, buf + OFFSET_f, SIZE_f, |
361 | CTRL_TIMEOUT); | 388 | CTRL_TIMEOUT); |
362 | if (ret < 0) { | 389 | if (ret < 0) { |
363 | dbg("MSG F failed"); | 390 | atm_dbg(usbatm, "%s: MSG F failed\n", __func__); |
364 | return ret; | 391 | return ret; |
365 | } | 392 | } |
366 | 393 | ||
367 | return 0; | 394 | return 0; |
368 | } | 395 | } |
369 | 396 | ||
370 | static void speedtch_poll_status(struct speedtch_instance_data *instance) | 397 | static int speedtch_start_synchro(struct speedtch_instance_data *instance) |
371 | { | 398 | { |
372 | unsigned char buf[TOTAL]; | 399 | struct usbatm_data *usbatm = instance->usbatm; |
400 | struct usb_device *usb_dev = usbatm->usb_dev; | ||
401 | unsigned char *buf = instance->scratch_buffer; | ||
373 | int ret; | 402 | int ret; |
374 | 403 | ||
375 | ret = speedtch_get_status(instance, buf); | 404 | atm_dbg(usbatm, "%s entered\n", __func__); |
376 | if (ret) { | 405 | |
377 | printk(KERN_WARNING | 406 | memset(buf, 0, 2); |
378 | "SpeedTouch: Error %d fetching device status\n", ret); | 407 | |
408 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
409 | 0x12, 0xc0, 0x04, 0x00, | ||
410 | buf, 2, CTRL_TIMEOUT); | ||
411 | |||
412 | if (ret < 0) | ||
413 | atm_warn(usbatm, "failed to start ADSL synchronisation: %d\n", ret); | ||
414 | else | ||
415 | atm_dbg(usbatm, "%s: modem prodded. %d bytes returned: %02x %02x\n", | ||
416 | __func__, ret, buf[0], buf[1]); | ||
417 | |||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | static void speedtch_check_status(struct speedtch_instance_data *instance) | ||
422 | { | ||
423 | struct usbatm_data *usbatm = instance->usbatm; | ||
424 | struct atm_dev *atm_dev = usbatm->atm_dev; | ||
425 | unsigned char *buf = instance->scratch_buffer; | ||
426 | int ret; | ||
427 | |||
428 | atm_dbg(usbatm, "%s entered\n", __func__); | ||
429 | |||
430 | ret = speedtch_read_status(instance); | ||
431 | if (ret < 0) { | ||
432 | atm_warn(usbatm, "error %d fetching device status\n", ret); | ||
433 | if (instance->poll_delay < MAX_POLL_DELAY) | ||
434 | instance->poll_delay *= 2; | ||
379 | return; | 435 | return; |
380 | } | 436 | } |
381 | 437 | ||
382 | dbg("Line state %02x", buf[OFFSET_7]); | 438 | if (instance->poll_delay > MIN_POLL_DELAY) |
439 | instance->poll_delay /= 2; | ||
440 | |||
441 | atm_dbg(usbatm, "%s: line state %02x\n", __func__, buf[OFFSET_7]); | ||
383 | 442 | ||
384 | switch (buf[OFFSET_7]) { | 443 | switch (buf[OFFSET_7]) { |
385 | case 0: | 444 | case 0: |
386 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_LOST) { | 445 | if (atm_dev->signal != ATM_PHY_SIG_LOST) { |
387 | instance->u.atm_dev->signal = ATM_PHY_SIG_LOST; | 446 | atm_dev->signal = ATM_PHY_SIG_LOST; |
388 | printk(KERN_NOTICE "ADSL line is down\n"); | 447 | atm_info(usbatm, "ADSL line is down\n"); |
389 | /* It'll never resync again unless we ask it to... */ | 448 | /* It'll never resync again unless we ask it to... */ |
390 | speedtch_start_synchro(instance); | 449 | ret = speedtch_start_synchro(instance); |
391 | } | 450 | } |
392 | break; | 451 | break; |
393 | 452 | ||
394 | case 0x08: | 453 | case 0x08: |
395 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { | 454 | if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { |
396 | instance->u.atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | 455 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; |
397 | printk(KERN_NOTICE "ADSL line is blocked?\n"); | 456 | atm_info(usbatm, "ADSL line is blocked?\n"); |
398 | } | 457 | } |
399 | break; | 458 | break; |
400 | 459 | ||
401 | case 0x10: | 460 | case 0x10: |
402 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_LOST) { | 461 | if (atm_dev->signal != ATM_PHY_SIG_LOST) { |
403 | instance->u.atm_dev->signal = ATM_PHY_SIG_LOST; | 462 | atm_dev->signal = ATM_PHY_SIG_LOST; |
404 | printk(KERN_NOTICE "ADSL line is synchronising\n"); | 463 | atm_info(usbatm, "ADSL line is synchronising\n"); |
405 | } | 464 | } |
406 | break; | 465 | break; |
407 | 466 | ||
408 | case 0x20: | 467 | case 0x20: |
409 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_FOUND) { | 468 | if (atm_dev->signal != ATM_PHY_SIG_FOUND) { |
410 | int down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8) | 469 | int down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8) |
411 | | (buf[OFFSET_b + 2] << 16) | (buf[OFFSET_b + 3] << 24); | 470 | | (buf[OFFSET_b + 2] << 16) | (buf[OFFSET_b + 3] << 24); |
412 | int up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8) | 471 | int up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8) |
413 | | (buf[OFFSET_b + 6] << 16) | (buf[OFFSET_b + 7] << 24); | 472 | | (buf[OFFSET_b + 6] << 16) | (buf[OFFSET_b + 7] << 24); |
414 | 473 | ||
415 | if (!(down_speed & 0x0000ffff) && | 474 | if (!(down_speed & 0x0000ffff) && !(up_speed & 0x0000ffff)) { |
416 | !(up_speed & 0x0000ffff)) { | ||
417 | down_speed >>= 16; | 475 | down_speed >>= 16; |
418 | up_speed >>= 16; | 476 | up_speed >>= 16; |
419 | } | 477 | } |
420 | instance->u.atm_dev->link_rate = down_speed * 1000 / 424; | ||
421 | instance->u.atm_dev->signal = ATM_PHY_SIG_FOUND; | ||
422 | 478 | ||
423 | printk(KERN_NOTICE | 479 | atm_dev->link_rate = down_speed * 1000 / 424; |
424 | "ADSL line is up (%d Kib/s down | %d Kib/s up)\n", | 480 | atm_dev->signal = ATM_PHY_SIG_FOUND; |
425 | down_speed, up_speed); | 481 | |
482 | atm_info(usbatm, | ||
483 | "ADSL line is up (%d Kib/s down | %d Kib/s up)\n", | ||
484 | down_speed, up_speed); | ||
426 | } | 485 | } |
427 | break; | 486 | break; |
428 | 487 | ||
429 | default: | 488 | default: |
430 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { | 489 | if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { |
431 | instance->u.atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | 490 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; |
432 | printk(KERN_NOTICE "Unknown line state %02x\n", buf[OFFSET_7]); | 491 | atm_info(usbatm, "Unknown line state %02x\n", buf[OFFSET_7]); |
433 | } | 492 | } |
434 | break; | 493 | break; |
435 | } | 494 | } |
436 | } | 495 | } |
437 | 496 | ||
438 | static void speedtch_timer_poll(unsigned long data) | 497 | static void speedtch_status_poll(unsigned long data) |
439 | { | 498 | { |
440 | struct speedtch_instance_data *instance = (void *)data; | 499 | struct speedtch_instance_data *instance = (void *)data; |
441 | 500 | ||
442 | schedule_work(&instance->poll_work); | 501 | schedule_work(&instance->status_checker); |
443 | mod_timer(&instance->poll_timer, jiffies + (5 * HZ)); | 502 | |
503 | /* The following check is racy, but the race is harmless */ | ||
504 | if (instance->poll_delay < MAX_POLL_DELAY) | ||
505 | mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(instance->poll_delay)); | ||
506 | else | ||
507 | atm_warn(instance->usbatm, "Too many failures - disabling line status polling\n"); | ||
444 | } | 508 | } |
445 | 509 | ||
446 | #ifdef USE_FW_LOADER | 510 | static void speedtch_resubmit_int(unsigned long data) |
447 | static void speedtch_upload_firmware(struct speedtch_instance_data *instance, | ||
448 | const struct firmware *fw1, | ||
449 | const struct firmware *fw2) | ||
450 | { | 511 | { |
451 | unsigned char *buffer; | 512 | struct speedtch_instance_data *instance = (void *)data; |
452 | struct usb_device *usb_dev = instance->u.usb_dev; | 513 | struct urb *int_urb = instance->int_urb; |
453 | struct usb_interface *intf; | 514 | int ret; |
454 | int actual_length, ret; | ||
455 | int offset; | ||
456 | |||
457 | dbg("speedtch_upload_firmware"); | ||
458 | |||
459 | if (!(intf = usb_ifnum_to_if(usb_dev, 2))) { | ||
460 | dbg("speedtch_upload_firmware: interface not found!"); | ||
461 | goto fail; | ||
462 | } | ||
463 | |||
464 | if (!(buffer = (unsigned char *)__get_free_page(GFP_KERNEL))) { | ||
465 | dbg("speedtch_upload_firmware: no memory for buffer!"); | ||
466 | goto fail; | ||
467 | } | ||
468 | |||
469 | /* A user-space firmware loader may already have claimed interface #2 */ | ||
470 | if ((ret = | ||
471 | usb_driver_claim_interface(&speedtch_usb_driver, intf, NULL)) < 0) { | ||
472 | dbg("speedtch_upload_firmware: interface in use (%d)!", ret); | ||
473 | goto fail_free; | ||
474 | } | ||
475 | |||
476 | /* URB 7 */ | ||
477 | if (dl_512_first) { /* some modems need a read before writing the firmware */ | ||
478 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | ||
479 | buffer, 0x200, &actual_length, 2000); | ||
480 | |||
481 | if (ret < 0 && ret != -ETIMEDOUT) | ||
482 | dbg("speedtch_upload_firmware: read BLOCK0 from modem failed (%d)!", ret); | ||
483 | else | ||
484 | dbg("speedtch_upload_firmware: BLOCK0 downloaded (%d bytes)", ret); | ||
485 | } | ||
486 | |||
487 | /* URB 8 : both leds are static green */ | ||
488 | for (offset = 0; offset < fw1->size; offset += PAGE_SIZE) { | ||
489 | int thislen = min_t(int, PAGE_SIZE, fw1->size - offset); | ||
490 | memcpy(buffer, fw1->data + offset, thislen); | ||
491 | 515 | ||
492 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | 516 | atm_dbg(instance->usbatm, "%s entered\n", __func__); |
493 | buffer, thislen, &actual_length, DATA_TIMEOUT); | ||
494 | 517 | ||
495 | if (ret < 0) { | 518 | if (int_urb) { |
496 | dbg("speedtch_upload_firmware: write BLOCK1 to modem failed (%d)!", ret); | 519 | ret = usb_submit_urb(int_urb, GFP_ATOMIC); |
497 | goto fail_release; | 520 | if (!ret) |
521 | schedule_work(&instance->status_checker); | ||
522 | else { | ||
523 | atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); | ||
524 | mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY)); | ||
498 | } | 525 | } |
499 | dbg("speedtch_upload_firmware: BLOCK1 uploaded (%zu bytes)", fw1->size); | ||
500 | } | 526 | } |
527 | } | ||
501 | 528 | ||
502 | /* USB led blinking green, ADSL led off */ | 529 | static void speedtch_handle_int(struct urb *int_urb, struct pt_regs *regs) |
530 | { | ||
531 | struct speedtch_instance_data *instance = int_urb->context; | ||
532 | struct usbatm_data *usbatm = instance->usbatm; | ||
533 | unsigned int count = int_urb->actual_length; | ||
534 | int ret = int_urb->status; | ||
503 | 535 | ||
504 | /* URB 11 */ | 536 | /* The magic interrupt for "up state" */ |
505 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | 537 | const static unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 }; |
506 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | 538 | /* The magic interrupt for "down state" */ |
539 | const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
540 | |||
541 | atm_dbg(usbatm, "%s entered\n", __func__); | ||
507 | 542 | ||
508 | if (ret < 0) { | 543 | if (ret < 0) { |
509 | dbg("speedtch_upload_firmware: read BLOCK2 from modem failed (%d)!", ret); | 544 | atm_dbg(usbatm, "%s: nonzero urb status %d!\n", __func__, ret); |
510 | goto fail_release; | 545 | goto fail; |
511 | } | 546 | } |
512 | dbg("speedtch_upload_firmware: BLOCK2 downloaded (%d bytes)", actual_length); | ||
513 | 547 | ||
514 | /* URBs 12 to 139 - USB led blinking green, ADSL led off */ | 548 | if ((count == 6) && !memcmp(up_int, instance->int_data, 6)) { |
515 | for (offset = 0; offset < fw2->size; offset += PAGE_SIZE) { | 549 | del_timer(&instance->status_checker.timer); |
516 | int thislen = min_t(int, PAGE_SIZE, fw2->size - offset); | 550 | atm_info(usbatm, "DSL line goes up\n"); |
517 | memcpy(buffer, fw2->data + offset, thislen); | 551 | } else if ((count == 6) && !memcmp(down_int, instance->int_data, 6)) { |
552 | atm_info(usbatm, "DSL line goes down\n"); | ||
553 | } else { | ||
554 | int i; | ||
518 | 555 | ||
519 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | 556 | atm_dbg(usbatm, "%s: unknown interrupt packet of length %d:", __func__, count); |
520 | buffer, thislen, &actual_length, DATA_TIMEOUT); | 557 | for (i = 0; i < count; i++) |
558 | printk(" %02x", instance->int_data[i]); | ||
559 | printk("\n"); | ||
560 | goto fail; | ||
561 | } | ||
521 | 562 | ||
563 | if ((int_urb = instance->int_urb)) { | ||
564 | ret = usb_submit_urb(int_urb, GFP_ATOMIC); | ||
565 | schedule_work(&instance->status_checker); | ||
522 | if (ret < 0) { | 566 | if (ret < 0) { |
523 | dbg("speedtch_upload_firmware: write BLOCK3 to modem failed (%d)!", ret); | 567 | atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); |
524 | goto fail_release; | 568 | goto fail; |
525 | } | 569 | } |
526 | } | 570 | } |
527 | dbg("speedtch_upload_firmware: BLOCK3 uploaded (%zu bytes)", fw2->size); | ||
528 | |||
529 | /* USB led static green, ADSL led static red */ | ||
530 | |||
531 | /* URB 142 */ | ||
532 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | ||
533 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | ||
534 | |||
535 | if (ret < 0) { | ||
536 | dbg("speedtch_upload_firmware: read BLOCK4 from modem failed (%d)!", ret); | ||
537 | goto fail_release; | ||
538 | } | ||
539 | |||
540 | /* success */ | ||
541 | dbg("speedtch_upload_firmware: BLOCK4 downloaded (%d bytes)", actual_length); | ||
542 | |||
543 | /* Delay to allow firmware to start up. We can do this here | ||
544 | because we're in our own kernel thread anyway. */ | ||
545 | msleep(1000); | ||
546 | |||
547 | /* Enable software buffering, if requested */ | ||
548 | if (sw_buffering) | ||
549 | speedtch_set_swbuff(instance, 1); | ||
550 | |||
551 | /* Magic spell; don't ask us what this does */ | ||
552 | speedtch_test_sequence(instance); | ||
553 | |||
554 | /* Start modem synchronisation */ | ||
555 | if (speedtch_start_synchro(instance)) | ||
556 | dbg("speedtch_start_synchro: failed"); | ||
557 | |||
558 | speedtch_got_firmware(instance, 1); | ||
559 | 571 | ||
560 | free_page((unsigned long)buffer); | ||
561 | return; | 572 | return; |
562 | 573 | ||
563 | fail_release: | 574 | fail: |
564 | /* Only release interface #2 if uploading failed; we don't release it | 575 | if ((int_urb = instance->int_urb)) |
565 | we succeeded. This prevents the userspace tools from trying to load | 576 | mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY)); |
566 | the firmware themselves */ | ||
567 | usb_driver_release_interface(&speedtch_usb_driver, intf); | ||
568 | fail_free: | ||
569 | free_page((unsigned long)buffer); | ||
570 | fail: | ||
571 | speedtch_got_firmware(instance, 0); | ||
572 | } | 577 | } |
573 | 578 | ||
574 | static int speedtch_find_firmware(struct speedtch_instance_data | 579 | static int speedtch_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_dev) |
575 | *instance, int phase, | ||
576 | const struct firmware **fw_p) | ||
577 | { | 580 | { |
578 | char buf[24]; | 581 | struct usb_device *usb_dev = usbatm->usb_dev; |
579 | const u16 bcdDevice = le16_to_cpu(instance->u.usb_dev->descriptor.bcdDevice); | 582 | struct speedtch_instance_data *instance = usbatm->driver_data; |
580 | const u8 major_revision = bcdDevice >> 8; | 583 | int i, ret; |
581 | const u8 minor_revision = bcdDevice & 0xff; | 584 | unsigned char mac_str[13]; |
582 | |||
583 | sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision); | ||
584 | dbg("speedtch_find_firmware: looking for %s", buf); | ||
585 | |||
586 | if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) { | ||
587 | sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision); | ||
588 | dbg("speedtch_find_firmware: looking for %s", buf); | ||
589 | 585 | ||
590 | if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) { | 586 | atm_dbg(usbatm, "%s entered\n", __func__); |
591 | sprintf(buf, "speedtch-%d.bin", phase); | ||
592 | dbg("speedtch_find_firmware: looking for %s", buf); | ||
593 | 587 | ||
594 | if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) { | 588 | if ((ret = usb_set_interface(usb_dev, 1, altsetting)) < 0) { |
595 | dev_warn(&instance->u.usb_dev->dev, "no stage %d firmware found!", phase); | 589 | atm_dbg(usbatm, "%s: usb_set_interface returned %d!\n", __func__, ret); |
596 | return -ENOENT; | 590 | return ret; |
597 | } | ||
598 | } | ||
599 | } | 591 | } |
600 | 592 | ||
601 | dev_info(&instance->u.usb_dev->dev, "found stage %d firmware %s\n", phase, buf); | 593 | /* Set MAC address, it is stored in the serial number */ |
602 | 594 | memset(atm_dev->esi, 0, sizeof(atm_dev->esi)); | |
603 | return 0; | 595 | if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) { |
604 | } | 596 | for (i = 0; i < 6; i++) |
605 | 597 | atm_dev->esi[i] = (hex2int(mac_str[i * 2]) * 16) + (hex2int(mac_str[i * 2 + 1])); | |
606 | static int speedtch_load_firmware(void *arg) | 598 | } |
607 | { | ||
608 | const struct firmware *fw1, *fw2; | ||
609 | struct speedtch_instance_data *instance = arg; | ||
610 | |||
611 | BUG_ON(!instance); | ||
612 | 599 | ||
613 | daemonize("firmware/speedtch"); | 600 | /* Start modem synchronisation */ |
601 | ret = speedtch_start_synchro(instance); | ||
614 | 602 | ||
615 | if (!speedtch_find_firmware(instance, 1, &fw1)) { | 603 | /* Set up interrupt endpoint */ |
616 | if (!speedtch_find_firmware(instance, 2, &fw2)) { | 604 | if (instance->int_urb) { |
617 | speedtch_upload_firmware(instance, fw1, fw2); | 605 | ret = usb_submit_urb(instance->int_urb, GFP_KERNEL); |
618 | release_firmware(fw2); | 606 | if (ret < 0) { |
607 | /* Doesn't matter; we'll poll anyway */ | ||
608 | atm_dbg(usbatm, "%s: submission of interrupt URB failed (%d)!\n", __func__, ret); | ||
609 | usb_free_urb(instance->int_urb); | ||
610 | instance->int_urb = NULL; | ||
619 | } | 611 | } |
620 | release_firmware(fw1); | ||
621 | } | 612 | } |
622 | 613 | ||
623 | /* In case we failed, set state back to NO_FIRMWARE so that | 614 | /* Start status polling */ |
624 | another later attempt may work. Otherwise, we never actually | 615 | mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(1000)); |
625 | manage to recover if, for example, the firmware is on /usr and | ||
626 | we look for it too early. */ | ||
627 | speedtch_got_firmware(instance, 0); | ||
628 | 616 | ||
629 | module_put(THIS_MODULE); | ||
630 | udsl_put_instance(&instance->u); | ||
631 | return 0; | 617 | return 0; |
632 | } | 618 | } |
633 | #endif /* USE_FW_LOADER */ | ||
634 | 619 | ||
635 | static void speedtch_firmware_start(struct speedtch_instance_data *instance) | 620 | static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_dev) |
636 | { | 621 | { |
637 | #ifdef USE_FW_LOADER | 622 | struct speedtch_instance_data *instance = usbatm->driver_data; |
638 | int ret; | 623 | struct urb *int_urb = instance->int_urb; |
639 | #endif | 624 | |
640 | 625 | atm_dbg(usbatm, "%s entered\n", __func__); | |
641 | dbg("speedtch_firmware_start"); | 626 | |
642 | 627 | del_timer_sync(&instance->status_checker.timer); | |
643 | down(&instance->u.serialize); /* vs self, speedtch_got_firmware */ | 628 | |
644 | 629 | /* | |
645 | if (instance->u.status >= UDSL_LOADING_FIRMWARE) { | 630 | * Since resubmit_timer and int_urb can schedule themselves and |
646 | up(&instance->u.serialize); | 631 | * each other, shutting them down correctly takes some care |
647 | return; | 632 | */ |
648 | } | 633 | instance->int_urb = NULL; /* signal shutdown */ |
634 | mb(); | ||
635 | usb_kill_urb(int_urb); | ||
636 | del_timer_sync(&instance->resubmit_timer); | ||
637 | /* | ||
638 | * At this point, speedtch_handle_int and speedtch_resubmit_int | ||
639 | * can run or be running, but instance->int_urb == NULL means that | ||
640 | * they will not reschedule | ||
641 | */ | ||
642 | usb_kill_urb(int_urb); | ||
643 | del_timer_sync(&instance->resubmit_timer); | ||
644 | usb_free_urb(int_urb); | ||
649 | 645 | ||
650 | instance->u.status = UDSL_LOADING_FIRMWARE; | 646 | flush_scheduled_work(); |
651 | up(&instance->u.serialize); | 647 | } |
652 | 648 | ||
653 | #ifdef USE_FW_LOADER | ||
654 | udsl_get_instance(&instance->u); | ||
655 | try_module_get(THIS_MODULE); | ||
656 | 649 | ||
657 | ret = kernel_thread(speedtch_load_firmware, instance, | 650 | /********** |
658 | CLONE_FS | CLONE_FILES); | 651 | ** USB ** |
652 | **********/ | ||
659 | 653 | ||
660 | if (ret >= 0) | 654 | static struct usb_device_id speedtch_usb_ids[] = { |
661 | return; /* OK */ | 655 | {USB_DEVICE(0x06b9, 0x4061)}, |
656 | {} | ||
657 | }; | ||
662 | 658 | ||
663 | dbg("speedtch_firmware_start: kernel_thread failed (%d)!", ret); | 659 | MODULE_DEVICE_TABLE(usb, speedtch_usb_ids); |
664 | 660 | ||
665 | module_put(THIS_MODULE); | 661 | static int speedtch_usb_probe(struct usb_interface *, const struct usb_device_id *); |
666 | udsl_put_instance(&instance->u); | ||
667 | /* Just pretend it never happened... hope modem_run happens */ | ||
668 | #endif /* USE_FW_LOADER */ | ||
669 | 662 | ||
670 | speedtch_got_firmware(instance, 0); | 663 | static struct usb_driver speedtch_usb_driver = { |
671 | } | 664 | .owner = THIS_MODULE, |
672 | 665 | .name = speedtch_driver_name, | |
673 | static int speedtch_firmware_wait(struct udsl_instance_data *instance) | 666 | .probe = speedtch_usb_probe, |
674 | { | 667 | .disconnect = usbatm_usb_disconnect, |
675 | speedtch_firmware_start((void *)instance); | 668 | .id_table = speedtch_usb_ids |
669 | }; | ||
676 | 670 | ||
677 | if (wait_event_interruptible(instance->firmware_waiters, instance->status != UDSL_LOADING_FIRMWARE) < 0) | 671 | static void speedtch_release_interfaces(struct usb_device *usb_dev, int num_interfaces) { |
678 | return -ERESTARTSYS; | 672 | struct usb_interface *cur_intf; |
673 | int i; | ||
679 | 674 | ||
680 | return (instance->status == UDSL_LOADED_FIRMWARE) ? 0 : -EAGAIN; | 675 | for(i = 0; i < num_interfaces; i++) |
676 | if ((cur_intf = usb_ifnum_to_if(usb_dev, i))) { | ||
677 | usb_set_intfdata(cur_intf, NULL); | ||
678 | usb_driver_release_interface(&speedtch_usb_driver, cur_intf); | ||
679 | } | ||
681 | } | 680 | } |
682 | 681 | ||
683 | /********** | 682 | static int speedtch_bind(struct usbatm_data *usbatm, |
684 | ** USB ** | 683 | struct usb_interface *intf, |
685 | **********/ | 684 | const struct usb_device_id *id, |
686 | 685 | int *need_heavy_init) | |
687 | static int speedtch_usb_ioctl(struct usb_interface *intf, unsigned int code, | ||
688 | void *user_data) | ||
689 | { | 686 | { |
690 | struct speedtch_instance_data *instance = usb_get_intfdata(intf); | 687 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
688 | struct usb_interface *cur_intf; | ||
689 | struct speedtch_instance_data *instance; | ||
690 | int ifnum = intf->altsetting->desc.bInterfaceNumber; | ||
691 | int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces; | ||
692 | int i, ret; | ||
691 | 693 | ||
692 | dbg("speedtch_usb_ioctl entered"); | 694 | usb_dbg(usbatm, "%s entered\n", __func__); |
693 | 695 | ||
694 | if (!instance) { | 696 | if (usb_dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { |
695 | dbg("speedtch_usb_ioctl: NULL instance!"); | 697 | usb_dbg(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass); |
696 | return -ENODEV; | 698 | return -ENODEV; |
697 | } | 699 | } |
698 | 700 | ||
699 | switch (code) { | 701 | /* claim all interfaces */ |
700 | case UDSL_IOCTL_LINE_UP: | ||
701 | instance->u.atm_dev->signal = ATM_PHY_SIG_FOUND; | ||
702 | speedtch_got_firmware(instance, 1); | ||
703 | return (instance->u.status == UDSL_LOADED_FIRMWARE) ? 0 : -EIO; | ||
704 | case UDSL_IOCTL_LINE_DOWN: | ||
705 | instance->u.atm_dev->signal = ATM_PHY_SIG_LOST; | ||
706 | return 0; | ||
707 | default: | ||
708 | return -ENOTTY; | ||
709 | } | ||
710 | } | ||
711 | 702 | ||
712 | static int speedtch_usb_probe(struct usb_interface *intf, | 703 | for (i=0; i < num_interfaces; i++) { |
713 | const struct usb_device_id *id) | 704 | cur_intf = usb_ifnum_to_if(usb_dev, i); |
714 | { | ||
715 | struct usb_device *dev = interface_to_usbdev(intf); | ||
716 | int ifnum = intf->altsetting->desc.bInterfaceNumber; | ||
717 | struct speedtch_instance_data *instance; | ||
718 | unsigned char mac_str[13]; | ||
719 | int ret, i; | ||
720 | char buf7[SIZE_7]; | ||
721 | 705 | ||
722 | dbg("speedtch_usb_probe: trying device with vendor=0x%x, product=0x%x, ifnum %d", | 706 | if ((i != ifnum) && cur_intf) { |
723 | le16_to_cpu(dev->descriptor.idVendor), | 707 | ret = usb_driver_claim_interface(&speedtch_usb_driver, cur_intf, usbatm); |
724 | le16_to_cpu(dev->descriptor.idProduct), ifnum); | ||
725 | 708 | ||
726 | if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || | 709 | if (ret < 0) { |
727 | (ifnum != 1)) | 710 | usb_dbg(usbatm, "%s: failed to claim interface %d (%d)\n", __func__, i, ret); |
728 | return -ENODEV; | 711 | speedtch_release_interfaces(usb_dev, i); |
729 | 712 | return ret; | |
730 | dbg("speedtch_usb_probe: device accepted"); | 713 | } |
714 | } | ||
715 | } | ||
731 | 716 | ||
732 | /* instance init */ | ||
733 | instance = kmalloc(sizeof(*instance), GFP_KERNEL); | 717 | instance = kmalloc(sizeof(*instance), GFP_KERNEL); |
718 | |||
734 | if (!instance) { | 719 | if (!instance) { |
735 | dbg("speedtch_usb_probe: no memory for instance data!"); | 720 | usb_dbg(usbatm, "%s: no memory for instance data!\n", __func__); |
736 | return -ENOMEM; | 721 | ret = -ENOMEM; |
722 | goto fail_release; | ||
737 | } | 723 | } |
738 | 724 | ||
739 | memset(instance, 0, sizeof(struct speedtch_instance_data)); | 725 | memset(instance, 0, sizeof(struct speedtch_instance_data)); |
740 | 726 | ||
741 | if ((ret = usb_set_interface(dev, 0, 0)) < 0) | 727 | instance->usbatm = usbatm; |
742 | goto fail; | ||
743 | 728 | ||
744 | if ((ret = usb_set_interface(dev, 2, 0)) < 0) | 729 | INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); |
745 | goto fail; | ||
746 | 730 | ||
747 | instance->u.data_endpoint = SPEEDTCH_ENDPOINT_DATA; | 731 | instance->status_checker.timer.function = speedtch_status_poll; |
748 | instance->u.firmware_wait = speedtch_firmware_wait; | 732 | instance->status_checker.timer.data = (unsigned long)instance; |
749 | instance->u.driver_name = speedtch_driver_name; | 733 | instance->poll_delay = MIN_POLL_DELAY; |
750 | 734 | ||
751 | ret = udsl_instance_setup(dev, &instance->u); | 735 | init_timer(&instance->resubmit_timer); |
752 | if (ret) | 736 | instance->resubmit_timer.function = speedtch_resubmit_int; |
753 | goto fail; | 737 | instance->resubmit_timer.data = (unsigned long)instance; |
754 | 738 | ||
755 | init_timer(&instance->poll_timer); | 739 | instance->int_urb = usb_alloc_urb(0, GFP_KERNEL); |
756 | instance->poll_timer.function = speedtch_timer_poll; | ||
757 | instance->poll_timer.data = (unsigned long)instance; | ||
758 | 740 | ||
759 | INIT_WORK(&instance->poll_work, (void *)speedtch_poll_status, instance); | 741 | if (instance->int_urb) |
742 | usb_fill_int_urb(instance->int_urb, usb_dev, | ||
743 | usb_rcvintpipe(usb_dev, ENDPOINT_INT), | ||
744 | instance->int_data, sizeof(instance->int_data), | ||
745 | speedtch_handle_int, instance, 50); | ||
746 | else | ||
747 | usb_dbg(usbatm, "%s: no memory for interrupt urb!\n", __func__); | ||
760 | 748 | ||
761 | /* set MAC address, it is stored in the serial number */ | 749 | /* check whether the modem already seems to be alive */ |
762 | memset(instance->u.atm_dev->esi, 0, sizeof(instance->u.atm_dev->esi)); | 750 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
763 | if (usb_string(dev, dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) { | 751 | 0x12, 0xc0, 0x07, 0x00, |
764 | for (i = 0; i < 6; i++) | 752 | instance->scratch_buffer + OFFSET_7, SIZE_7, 500); |
765 | instance->u.atm_dev->esi[i] = | ||
766 | (hex2int(mac_str[i * 2]) * 16) + (hex2int(mac_str[i * 2 + 1])); | ||
767 | } | ||
768 | 753 | ||
769 | /* First check whether the modem already seems to be alive */ | 754 | *need_heavy_init = (ret != SIZE_7); |
770 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
771 | 0x12, 0xc0, 0x07, 0x00, buf7, SIZE_7, 500); | ||
772 | 755 | ||
773 | if (ret == SIZE_7) { | 756 | usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, need_heavy_init ? "not" : "already"); |
774 | dbg("firmware appears to be already loaded"); | 757 | |
775 | speedtch_got_firmware(instance, 1); | 758 | if (*need_heavy_init) |
776 | speedtch_poll_status(instance); | 759 | if ((ret = usb_reset_device(usb_dev)) < 0) |
777 | } else { | 760 | goto fail_free; |
778 | speedtch_firmware_start(instance); | ||
779 | } | ||
780 | 761 | ||
781 | usb_set_intfdata(intf, instance); | 762 | usbatm->driver_data = instance; |
782 | 763 | ||
783 | return 0; | 764 | return 0; |
784 | 765 | ||
785 | fail: | 766 | fail_free: |
767 | usb_free_urb(instance->int_urb); | ||
786 | kfree(instance); | 768 | kfree(instance); |
787 | 769 | fail_release: | |
788 | return -ENOMEM; | 770 | speedtch_release_interfaces(usb_dev, num_interfaces); |
771 | return ret; | ||
789 | } | 772 | } |
790 | 773 | ||
791 | static void speedtch_usb_disconnect(struct usb_interface *intf) | 774 | static void speedtch_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) |
792 | { | 775 | { |
793 | struct speedtch_instance_data *instance = usb_get_intfdata(intf); | 776 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
794 | 777 | struct speedtch_instance_data *instance = usbatm->driver_data; | |
795 | dbg("speedtch_usb_disconnect entered"); | ||
796 | |||
797 | if (!instance) { | ||
798 | dbg("speedtch_usb_disconnect: NULL instance!"); | ||
799 | return; | ||
800 | } | ||
801 | 778 | ||
802 | /*QQ need to handle disconnects on interface #2 while uploading firmware */ | 779 | usb_dbg(usbatm, "%s entered\n", __func__); |
803 | /*QQ and what about interface #1? */ | ||
804 | |||
805 | if (instance->int_urb) { | ||
806 | struct urb *int_urb = instance->int_urb; | ||
807 | instance->int_urb = NULL; | ||
808 | wmb(); | ||
809 | usb_unlink_urb(int_urb); | ||
810 | usb_free_urb(int_urb); | ||
811 | } | ||
812 | 780 | ||
813 | instance->int_data[0] = 1; | 781 | speedtch_release_interfaces(usb_dev, usb_dev->actconfig->desc.bNumInterfaces); |
814 | del_timer_sync(&instance->poll_timer); | 782 | usb_free_urb(instance->int_urb); |
815 | wmb(); | 783 | kfree(instance); |
816 | flush_scheduled_work(); | ||
817 | |||
818 | udsl_instance_disconnect(&instance->u); | ||
819 | |||
820 | /* clean up */ | ||
821 | usb_set_intfdata(intf, NULL); | ||
822 | udsl_put_instance(&instance->u); | ||
823 | } | 784 | } |
824 | 785 | ||
786 | |||
825 | /*********** | 787 | /*********** |
826 | ** init ** | 788 | ** init ** |
827 | ***********/ | 789 | ***********/ |
828 | 790 | ||
791 | static struct usbatm_driver speedtch_usbatm_driver = { | ||
792 | .owner = THIS_MODULE, | ||
793 | .driver_name = speedtch_driver_name, | ||
794 | .bind = speedtch_bind, | ||
795 | .heavy_init = speedtch_heavy_init, | ||
796 | .unbind = speedtch_unbind, | ||
797 | .atm_start = speedtch_atm_start, | ||
798 | .atm_stop = speedtch_atm_stop, | ||
799 | .in = ENDPOINT_DATA, | ||
800 | .out = ENDPOINT_DATA | ||
801 | }; | ||
802 | |||
803 | static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
804 | { | ||
805 | return usbatm_usb_probe(intf, id, &speedtch_usbatm_driver); | ||
806 | } | ||
807 | |||
829 | static int __init speedtch_usb_init(void) | 808 | static int __init speedtch_usb_init(void) |
830 | { | 809 | { |
831 | dbg("speedtch_usb_init: driver version " DRIVER_VERSION); | 810 | dbg("%s: driver version %s", __func__, DRIVER_VERSION); |
832 | 811 | ||
833 | return usb_register(&speedtch_usb_driver); | 812 | return usb_register(&speedtch_usb_driver); |
834 | } | 813 | } |
835 | 814 | ||
836 | static void __exit speedtch_usb_cleanup(void) | 815 | static void __exit speedtch_usb_cleanup(void) |
837 | { | 816 | { |
838 | dbg("speedtch_usb_cleanup entered"); | 817 | dbg("%s", __func__); |
839 | 818 | ||
840 | usb_deregister(&speedtch_usb_driver); | 819 | usb_deregister(&speedtch_usb_driver); |
841 | } | 820 | } |
diff --git a/drivers/usb/atm/usb_atm.c b/drivers/usb/atm/usb_atm.c deleted file mode 100644 index a4cd4476d49a..000000000000 --- a/drivers/usb/atm/usb_atm.c +++ /dev/null | |||
@@ -1,1188 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * usb_atm.c - Generic USB xDSL driver core | ||
3 | * | ||
4 | * Copyright (C) 2001, Alcatel | ||
5 | * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas | ||
6 | * Copyright (C) 2004, David Woodhouse | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | /* | ||
25 | * Written by Johan Verrept, maintained by Duncan Sands (duncan.sands@free.fr) | ||
26 | * | ||
27 | * 1.7+: - See the check-in logs | ||
28 | * | ||
29 | * 1.6: - No longer opens a connection if the firmware is not loaded | ||
30 | * - Added support for the speedtouch 330 | ||
31 | * - Removed the limit on the number of devices | ||
32 | * - Module now autoloads on device plugin | ||
33 | * - Merged relevant parts of sarlib | ||
34 | * - Replaced the kernel thread with a tasklet | ||
35 | * - New packet transmission code | ||
36 | * - Changed proc file contents | ||
37 | * - Fixed all known SMP races | ||
38 | * - Many fixes and cleanups | ||
39 | * - Various fixes by Oliver Neukum (oliver@neukum.name) | ||
40 | * | ||
41 | * 1.5A: - Version for inclusion in 2.5 series kernel | ||
42 | * - Modifications by Richard Purdie (rpurdie@rpsys.net) | ||
43 | * - made compatible with kernel 2.5.6 onwards by changing | ||
44 | * udsl_usb_send_data_context->urb to a pointer and adding code | ||
45 | * to alloc and free it | ||
46 | * - remove_wait_queue() added to udsl_atm_processqueue_thread() | ||
47 | * | ||
48 | * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL. | ||
49 | * (reported by stephen.robinson@zen.co.uk) | ||
50 | * | ||
51 | * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave() | ||
52 | * - unlink all active send urbs of a vcc that is being closed. | ||
53 | * | ||
54 | * 1.3.1: - added the version number | ||
55 | * | ||
56 | * 1.3: - Added multiple send urb support | ||
57 | * - fixed memory leak and vcc->tx_inuse starvation bug | ||
58 | * when not enough memory left in vcc. | ||
59 | * | ||
60 | * 1.2: - Fixed race condition in udsl_usb_send_data() | ||
61 | * 1.1: - Turned off packet debugging | ||
62 | * | ||
63 | */ | ||
64 | |||
65 | #include <linux/module.h> | ||
66 | #include <linux/moduleparam.h> | ||
67 | #include <linux/kernel.h> | ||
68 | #include <linux/sched.h> | ||
69 | #include <linux/timer.h> | ||
70 | #include <linux/errno.h> | ||
71 | #include <linux/proc_fs.h> | ||
72 | #include <linux/slab.h> | ||
73 | #include <linux/wait.h> | ||
74 | #include <linux/list.h> | ||
75 | #include <asm/uaccess.h> | ||
76 | #include <linux/smp_lock.h> | ||
77 | #include <linux/interrupt.h> | ||
78 | #include <linux/atm.h> | ||
79 | #include <linux/atmdev.h> | ||
80 | #include <linux/crc32.h> | ||
81 | #include <linux/init.h> | ||
82 | #include <linux/firmware.h> | ||
83 | |||
84 | #include "usb_atm.h" | ||
85 | |||
86 | #ifdef VERBOSE_DEBUG | ||
87 | static int udsl_print_packet(const unsigned char *data, int len); | ||
88 | #define PACKETDEBUG(arg...) udsl_print_packet (arg) | ||
89 | #define vdbg(arg...) dbg (arg) | ||
90 | #else | ||
91 | #define PACKETDEBUG(arg...) | ||
92 | #define vdbg(arg...) | ||
93 | #endif | ||
94 | |||
95 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" | ||
96 | #define DRIVER_VERSION "1.8" | ||
97 | #define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION | ||
98 | |||
99 | static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; | ||
100 | static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; | ||
101 | static unsigned int num_rcv_bufs = UDSL_DEFAULT_RCV_BUFS; | ||
102 | static unsigned int num_snd_bufs = UDSL_DEFAULT_SND_BUFS; | ||
103 | static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE; | ||
104 | static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE; | ||
105 | |||
106 | module_param(num_rcv_urbs, uint, 0444); | ||
107 | MODULE_PARM_DESC(num_rcv_urbs, | ||
108 | "Number of urbs used for reception (range: 0-" | ||
109 | __MODULE_STRING(UDSL_MAX_RCV_URBS) ", default: " | ||
110 | __MODULE_STRING(UDSL_DEFAULT_RCV_URBS) ")"); | ||
111 | |||
112 | module_param(num_snd_urbs, uint, 0444); | ||
113 | MODULE_PARM_DESC(num_snd_urbs, | ||
114 | "Number of urbs used for transmission (range: 0-" | ||
115 | __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: " | ||
116 | __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")"); | ||
117 | |||
118 | module_param(num_rcv_bufs, uint, 0444); | ||
119 | MODULE_PARM_DESC(num_rcv_bufs, | ||
120 | "Number of buffers used for reception (range: 0-" | ||
121 | __MODULE_STRING(UDSL_MAX_RCV_BUFS) ", default: " | ||
122 | __MODULE_STRING(UDSL_DEFAULT_RCV_BUFS) ")"); | ||
123 | |||
124 | module_param(num_snd_bufs, uint, 0444); | ||
125 | MODULE_PARM_DESC(num_snd_bufs, | ||
126 | "Number of buffers used for transmission (range: 0-" | ||
127 | __MODULE_STRING(UDSL_MAX_SND_BUFS) ", default: " | ||
128 | __MODULE_STRING(UDSL_DEFAULT_SND_BUFS) ")"); | ||
129 | |||
130 | module_param(rcv_buf_size, uint, 0444); | ||
131 | MODULE_PARM_DESC(rcv_buf_size, | ||
132 | "Size of the buffers used for reception (range: 0-" | ||
133 | __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: " | ||
134 | __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")"); | ||
135 | |||
136 | module_param(snd_buf_size, uint, 0444); | ||
137 | MODULE_PARM_DESC(snd_buf_size, | ||
138 | "Size of the buffers used for transmission (range: 0-" | ||
139 | __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: " | ||
140 | __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")"); | ||
141 | |||
142 | /* ATM */ | ||
143 | |||
144 | static void udsl_atm_dev_close(struct atm_dev *dev); | ||
145 | static int udsl_atm_open(struct atm_vcc *vcc); | ||
146 | static void udsl_atm_close(struct atm_vcc *vcc); | ||
147 | static int udsl_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg); | ||
148 | static int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb); | ||
149 | static int udsl_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page); | ||
150 | |||
151 | static struct atmdev_ops udsl_atm_devops = { | ||
152 | .dev_close = udsl_atm_dev_close, | ||
153 | .open = udsl_atm_open, | ||
154 | .close = udsl_atm_close, | ||
155 | .ioctl = udsl_atm_ioctl, | ||
156 | .send = udsl_atm_send, | ||
157 | .proc_read = udsl_atm_proc_read, | ||
158 | .owner = THIS_MODULE, | ||
159 | }; | ||
160 | |||
161 | /*********** | ||
162 | ** misc ** | ||
163 | ***********/ | ||
164 | |||
165 | static inline void udsl_pop(struct atm_vcc *vcc, struct sk_buff *skb) | ||
166 | { | ||
167 | if (vcc->pop) | ||
168 | vcc->pop(vcc, skb); | ||
169 | else | ||
170 | dev_kfree_skb(skb); | ||
171 | } | ||
172 | |||
173 | /************* | ||
174 | ** decode ** | ||
175 | *************/ | ||
176 | |||
177 | static inline struct udsl_vcc_data *udsl_find_vcc(struct udsl_instance_data *instance, | ||
178 | short vpi, int vci) | ||
179 | { | ||
180 | struct udsl_vcc_data *vcc; | ||
181 | |||
182 | list_for_each_entry(vcc, &instance->vcc_list, list) | ||
183 | if ((vcc->vci == vci) && (vcc->vpi == vpi)) | ||
184 | return vcc; | ||
185 | return NULL; | ||
186 | } | ||
187 | |||
188 | static void udsl_extract_cells(struct udsl_instance_data *instance, | ||
189 | unsigned char *source, unsigned int howmany) | ||
190 | { | ||
191 | struct udsl_vcc_data *cached_vcc = NULL; | ||
192 | struct atm_vcc *vcc; | ||
193 | struct sk_buff *sarb; | ||
194 | struct udsl_vcc_data *vcc_data; | ||
195 | int cached_vci = 0; | ||
196 | unsigned int i; | ||
197 | int pti; | ||
198 | int vci; | ||
199 | short cached_vpi = 0; | ||
200 | short vpi; | ||
201 | |||
202 | for (i = 0; i < howmany; | ||
203 | i++, source += ATM_CELL_SIZE + instance->rcv_padding) { | ||
204 | vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4); | ||
205 | vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4); | ||
206 | pti = (source[3] & 0x2) != 0; | ||
207 | |||
208 | vdbg("udsl_extract_cells: vpi %hd, vci %d, pti %d", vpi, vci, pti); | ||
209 | |||
210 | if (cached_vcc && (vci == cached_vci) && (vpi == cached_vpi)) | ||
211 | vcc_data = cached_vcc; | ||
212 | else if ((vcc_data = udsl_find_vcc(instance, vpi, vci))) { | ||
213 | cached_vcc = vcc_data; | ||
214 | cached_vpi = vpi; | ||
215 | cached_vci = vci; | ||
216 | } else { | ||
217 | dbg("udsl_extract_cells: unknown vpi/vci (%hd/%d)!", vpi, vci); | ||
218 | continue; | ||
219 | } | ||
220 | |||
221 | vcc = vcc_data->vcc; | ||
222 | sarb = vcc_data->sarb; | ||
223 | |||
224 | if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) { | ||
225 | dbg("udsl_extract_cells: buffer overrun (sarb->len %u, vcc: 0x%p)!", sarb->len, vcc); | ||
226 | /* discard cells already received */ | ||
227 | skb_trim(sarb, 0); | ||
228 | } | ||
229 | |||
230 | memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); | ||
231 | __skb_put(sarb, ATM_CELL_PAYLOAD); | ||
232 | |||
233 | if (pti) { | ||
234 | struct sk_buff *skb; | ||
235 | unsigned int length; | ||
236 | unsigned int pdu_length; | ||
237 | |||
238 | length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5]; | ||
239 | |||
240 | /* guard against overflow */ | ||
241 | if (length > ATM_MAX_AAL5_PDU) { | ||
242 | dbg("udsl_extract_cells: bogus length %u (vcc: 0x%p)!", length, vcc); | ||
243 | atomic_inc(&vcc->stats->rx_err); | ||
244 | goto out; | ||
245 | } | ||
246 | |||
247 | pdu_length = UDSL_NUM_CELLS(length) * ATM_CELL_PAYLOAD; | ||
248 | |||
249 | if (sarb->len < pdu_length) { | ||
250 | dbg("udsl_extract_cells: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!", pdu_length, sarb->len, vcc); | ||
251 | atomic_inc(&vcc->stats->rx_err); | ||
252 | goto out; | ||
253 | } | ||
254 | |||
255 | if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) { | ||
256 | dbg("udsl_extract_cells: packet failed crc check (vcc: 0x%p)!", vcc); | ||
257 | atomic_inc(&vcc->stats->rx_err); | ||
258 | goto out; | ||
259 | } | ||
260 | |||
261 | vdbg("udsl_extract_cells: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", length, pdu_length, vcc); | ||
262 | |||
263 | if (!(skb = dev_alloc_skb(length))) { | ||
264 | dbg("udsl_extract_cells: no memory for skb (length: %u)!", length); | ||
265 | atomic_inc(&vcc->stats->rx_drop); | ||
266 | goto out; | ||
267 | } | ||
268 | |||
269 | vdbg("udsl_extract_cells: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", skb, skb->truesize); | ||
270 | |||
271 | if (!atm_charge(vcc, skb->truesize)) { | ||
272 | dbg("udsl_extract_cells: failed atm_charge (skb->truesize: %u)!", skb->truesize); | ||
273 | dev_kfree_skb(skb); | ||
274 | goto out; /* atm_charge increments rx_drop */ | ||
275 | } | ||
276 | |||
277 | memcpy(skb->data, sarb->tail - pdu_length, length); | ||
278 | __skb_put(skb, length); | ||
279 | |||
280 | vdbg("udsl_extract_cells: sending skb 0x%p, skb->len %u, skb->truesize %u", skb, skb->len, skb->truesize); | ||
281 | |||
282 | PACKETDEBUG(skb->data, skb->len); | ||
283 | |||
284 | vcc->push(vcc, skb); | ||
285 | |||
286 | atomic_inc(&vcc->stats->rx); | ||
287 | out: | ||
288 | skb_trim(sarb, 0); | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /************* | ||
294 | ** encode ** | ||
295 | *************/ | ||
296 | |||
297 | static inline void udsl_fill_cell_header(unsigned char *target, struct atm_vcc *vcc) | ||
298 | { | ||
299 | target[0] = vcc->vpi >> 4; | ||
300 | target[1] = (vcc->vpi << 4) | (vcc->vci >> 12); | ||
301 | target[2] = vcc->vci >> 4; | ||
302 | target[3] = vcc->vci << 4; | ||
303 | target[4] = 0xec; | ||
304 | } | ||
305 | |||
306 | static const unsigned char zeros[ATM_CELL_PAYLOAD]; | ||
307 | |||
308 | static void udsl_groom_skb(struct atm_vcc *vcc, struct sk_buff *skb) | ||
309 | { | ||
310 | struct udsl_control *ctrl = UDSL_SKB(skb); | ||
311 | unsigned int zero_padding; | ||
312 | u32 crc; | ||
313 | |||
314 | ctrl->atm_data.vcc = vcc; | ||
315 | |||
316 | ctrl->num_cells = UDSL_NUM_CELLS(skb->len); | ||
317 | ctrl->num_entire = skb->len / ATM_CELL_PAYLOAD; | ||
318 | |||
319 | zero_padding = ctrl->num_cells * ATM_CELL_PAYLOAD - skb->len - ATM_AAL5_TRAILER; | ||
320 | |||
321 | if (ctrl->num_entire + 1 < ctrl->num_cells) | ||
322 | ctrl->pdu_padding = zero_padding - (ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); | ||
323 | else | ||
324 | ctrl->pdu_padding = zero_padding; | ||
325 | |||
326 | ctrl->aal5_trailer[0] = 0; /* UU = 0 */ | ||
327 | ctrl->aal5_trailer[1] = 0; /* CPI = 0 */ | ||
328 | ctrl->aal5_trailer[2] = skb->len >> 8; | ||
329 | ctrl->aal5_trailer[3] = skb->len; | ||
330 | |||
331 | crc = crc32_be(~0, skb->data, skb->len); | ||
332 | crc = crc32_be(crc, zeros, zero_padding); | ||
333 | crc = crc32_be(crc, ctrl->aal5_trailer, 4); | ||
334 | crc = ~crc; | ||
335 | |||
336 | ctrl->aal5_trailer[4] = crc >> 24; | ||
337 | ctrl->aal5_trailer[5] = crc >> 16; | ||
338 | ctrl->aal5_trailer[6] = crc >> 8; | ||
339 | ctrl->aal5_trailer[7] = crc; | ||
340 | } | ||
341 | |||
342 | static unsigned int udsl_write_cells(struct udsl_instance_data *instance, | ||
343 | unsigned int howmany, struct sk_buff *skb, | ||
344 | unsigned char **target_p) | ||
345 | { | ||
346 | struct udsl_control *ctrl = UDSL_SKB(skb); | ||
347 | unsigned char *target = *target_p; | ||
348 | unsigned int nc, ne, i; | ||
349 | |||
350 | vdbg("udsl_write_cells: howmany=%u, skb->len=%d, num_cells=%u, num_entire=%u, pdu_padding=%u", howmany, skb->len, ctrl->num_cells, ctrl->num_entire, ctrl->pdu_padding); | ||
351 | |||
352 | nc = ctrl->num_cells; | ||
353 | ne = min(howmany, ctrl->num_entire); | ||
354 | |||
355 | for (i = 0; i < ne; i++) { | ||
356 | udsl_fill_cell_header(target, ctrl->atm_data.vcc); | ||
357 | target += ATM_CELL_HEADER; | ||
358 | memcpy(target, skb->data, ATM_CELL_PAYLOAD); | ||
359 | target += ATM_CELL_PAYLOAD; | ||
360 | if (instance->snd_padding) { | ||
361 | memset(target, 0, instance->snd_padding); | ||
362 | target += instance->snd_padding; | ||
363 | } | ||
364 | __skb_pull(skb, ATM_CELL_PAYLOAD); | ||
365 | } | ||
366 | |||
367 | ctrl->num_entire -= ne; | ||
368 | |||
369 | if (!(ctrl->num_cells -= ne) || !(howmany -= ne)) | ||
370 | goto out; | ||
371 | |||
372 | udsl_fill_cell_header(target, ctrl->atm_data.vcc); | ||
373 | target += ATM_CELL_HEADER; | ||
374 | memcpy(target, skb->data, skb->len); | ||
375 | target += skb->len; | ||
376 | __skb_pull(skb, skb->len); | ||
377 | memset(target, 0, ctrl->pdu_padding); | ||
378 | target += ctrl->pdu_padding; | ||
379 | |||
380 | if (--ctrl->num_cells) { | ||
381 | if (!--howmany) { | ||
382 | ctrl->pdu_padding = ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; | ||
383 | goto out; | ||
384 | } | ||
385 | |||
386 | if (instance->snd_padding) { | ||
387 | memset(target, 0, instance->snd_padding); | ||
388 | target += instance->snd_padding; | ||
389 | } | ||
390 | udsl_fill_cell_header(target, ctrl->atm_data.vcc); | ||
391 | target += ATM_CELL_HEADER; | ||
392 | memset(target, 0, ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); | ||
393 | target += ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; | ||
394 | |||
395 | --ctrl->num_cells; | ||
396 | UDSL_ASSERT(!ctrl->num_cells); | ||
397 | } | ||
398 | |||
399 | memcpy(target, ctrl->aal5_trailer, ATM_AAL5_TRAILER); | ||
400 | target += ATM_AAL5_TRAILER; | ||
401 | /* set pti bit in last cell */ | ||
402 | *(target + 3 - ATM_CELL_SIZE) |= 0x2; | ||
403 | if (instance->snd_padding) { | ||
404 | memset(target, 0, instance->snd_padding); | ||
405 | target += instance->snd_padding; | ||
406 | } | ||
407 | out: | ||
408 | *target_p = target; | ||
409 | return nc - ctrl->num_cells; | ||
410 | } | ||
411 | |||
412 | /************** | ||
413 | ** receive ** | ||
414 | **************/ | ||
415 | |||
416 | static void udsl_complete_receive(struct urb *urb, struct pt_regs *regs) | ||
417 | { | ||
418 | struct udsl_receive_buffer *buf; | ||
419 | struct udsl_instance_data *instance; | ||
420 | struct udsl_receiver *rcv; | ||
421 | unsigned long flags; | ||
422 | |||
423 | if (!urb || !(rcv = urb->context)) { | ||
424 | dbg("udsl_complete_receive: bad urb!"); | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | instance = rcv->instance; | ||
429 | buf = rcv->buffer; | ||
430 | |||
431 | buf->filled_cells = urb->actual_length / (ATM_CELL_SIZE + instance->rcv_padding); | ||
432 | |||
433 | vdbg("udsl_complete_receive: urb 0x%p, status %d, actual_length %d, filled_cells %u, rcv 0x%p, buf 0x%p", urb, urb->status, urb->actual_length, buf->filled_cells, rcv, buf); | ||
434 | |||
435 | UDSL_ASSERT(buf->filled_cells <= rcv_buf_size); | ||
436 | |||
437 | /* may not be in_interrupt() */ | ||
438 | spin_lock_irqsave(&instance->receive_lock, flags); | ||
439 | list_add(&rcv->list, &instance->spare_receivers); | ||
440 | list_add_tail(&buf->list, &instance->filled_receive_buffers); | ||
441 | if (likely(!urb->status)) | ||
442 | tasklet_schedule(&instance->receive_tasklet); | ||
443 | spin_unlock_irqrestore(&instance->receive_lock, flags); | ||
444 | } | ||
445 | |||
446 | static void udsl_process_receive(unsigned long data) | ||
447 | { | ||
448 | struct udsl_receive_buffer *buf; | ||
449 | struct udsl_instance_data *instance = (struct udsl_instance_data *)data; | ||
450 | struct udsl_receiver *rcv; | ||
451 | int err; | ||
452 | |||
453 | made_progress: | ||
454 | while (!list_empty(&instance->spare_receive_buffers)) { | ||
455 | spin_lock_irq(&instance->receive_lock); | ||
456 | if (list_empty(&instance->spare_receivers)) { | ||
457 | spin_unlock_irq(&instance->receive_lock); | ||
458 | break; | ||
459 | } | ||
460 | rcv = list_entry(instance->spare_receivers.next, | ||
461 | struct udsl_receiver, list); | ||
462 | list_del(&rcv->list); | ||
463 | spin_unlock_irq(&instance->receive_lock); | ||
464 | |||
465 | buf = list_entry(instance->spare_receive_buffers.next, | ||
466 | struct udsl_receive_buffer, list); | ||
467 | list_del(&buf->list); | ||
468 | |||
469 | rcv->buffer = buf; | ||
470 | |||
471 | usb_fill_bulk_urb(rcv->urb, instance->usb_dev, | ||
472 | usb_rcvbulkpipe(instance->usb_dev, instance->data_endpoint), | ||
473 | buf->base, | ||
474 | rcv_buf_size * (ATM_CELL_SIZE + instance->rcv_padding), | ||
475 | udsl_complete_receive, rcv); | ||
476 | |||
477 | vdbg("udsl_process_receive: sending urb 0x%p, rcv 0x%p, buf 0x%p", | ||
478 | rcv->urb, rcv, buf); | ||
479 | |||
480 | if ((err = usb_submit_urb(rcv->urb, GFP_ATOMIC)) < 0) { | ||
481 | dbg("udsl_process_receive: urb submission failed (%d)!", err); | ||
482 | list_add(&buf->list, &instance->spare_receive_buffers); | ||
483 | spin_lock_irq(&instance->receive_lock); | ||
484 | list_add(&rcv->list, &instance->spare_receivers); | ||
485 | spin_unlock_irq(&instance->receive_lock); | ||
486 | break; | ||
487 | } | ||
488 | } | ||
489 | |||
490 | spin_lock_irq(&instance->receive_lock); | ||
491 | if (list_empty(&instance->filled_receive_buffers)) { | ||
492 | spin_unlock_irq(&instance->receive_lock); | ||
493 | return; /* done - no more buffers */ | ||
494 | } | ||
495 | buf = list_entry(instance->filled_receive_buffers.next, | ||
496 | struct udsl_receive_buffer, list); | ||
497 | list_del(&buf->list); | ||
498 | spin_unlock_irq(&instance->receive_lock); | ||
499 | |||
500 | vdbg("udsl_process_receive: processing buf 0x%p", buf); | ||
501 | udsl_extract_cells(instance, buf->base, buf->filled_cells); | ||
502 | list_add(&buf->list, &instance->spare_receive_buffers); | ||
503 | goto made_progress; | ||
504 | } | ||
505 | |||
506 | /*********** | ||
507 | ** send ** | ||
508 | ***********/ | ||
509 | |||
510 | static void udsl_complete_send(struct urb *urb, struct pt_regs *regs) | ||
511 | { | ||
512 | struct udsl_instance_data *instance; | ||
513 | struct udsl_sender *snd; | ||
514 | unsigned long flags; | ||
515 | |||
516 | if (!urb || !(snd = urb->context) || !(instance = snd->instance)) { | ||
517 | dbg("udsl_complete_send: bad urb!"); | ||
518 | return; | ||
519 | } | ||
520 | |||
521 | vdbg("udsl_complete_send: urb 0x%p, status %d, snd 0x%p, buf 0x%p", urb, | ||
522 | urb->status, snd, snd->buffer); | ||
523 | |||
524 | /* may not be in_interrupt() */ | ||
525 | spin_lock_irqsave(&instance->send_lock, flags); | ||
526 | list_add(&snd->list, &instance->spare_senders); | ||
527 | list_add(&snd->buffer->list, &instance->spare_send_buffers); | ||
528 | tasklet_schedule(&instance->send_tasklet); | ||
529 | spin_unlock_irqrestore(&instance->send_lock, flags); | ||
530 | } | ||
531 | |||
532 | static void udsl_process_send(unsigned long data) | ||
533 | { | ||
534 | struct udsl_send_buffer *buf; | ||
535 | struct udsl_instance_data *instance = (struct udsl_instance_data *)data; | ||
536 | struct sk_buff *skb; | ||
537 | struct udsl_sender *snd; | ||
538 | int err; | ||
539 | unsigned int num_written; | ||
540 | |||
541 | made_progress: | ||
542 | spin_lock_irq(&instance->send_lock); | ||
543 | while (!list_empty(&instance->spare_senders)) { | ||
544 | if (!list_empty(&instance->filled_send_buffers)) { | ||
545 | buf = list_entry(instance->filled_send_buffers.next, | ||
546 | struct udsl_send_buffer, list); | ||
547 | list_del(&buf->list); | ||
548 | } else if ((buf = instance->current_buffer)) { | ||
549 | instance->current_buffer = NULL; | ||
550 | } else /* all buffers empty */ | ||
551 | break; | ||
552 | |||
553 | snd = list_entry(instance->spare_senders.next, | ||
554 | struct udsl_sender, list); | ||
555 | list_del(&snd->list); | ||
556 | spin_unlock_irq(&instance->send_lock); | ||
557 | |||
558 | snd->buffer = buf; | ||
559 | usb_fill_bulk_urb(snd->urb, instance->usb_dev, | ||
560 | usb_sndbulkpipe(instance->usb_dev, instance->data_endpoint), | ||
561 | buf->base, | ||
562 | (snd_buf_size - buf->free_cells) * (ATM_CELL_SIZE + instance->snd_padding), | ||
563 | udsl_complete_send, snd); | ||
564 | |||
565 | vdbg("udsl_process_send: submitting urb 0x%p (%d cells), snd 0x%p, buf 0x%p", | ||
566 | snd->urb, snd_buf_size - buf->free_cells, snd, buf); | ||
567 | |||
568 | if ((err = usb_submit_urb(snd->urb, GFP_ATOMIC)) < 0) { | ||
569 | dbg("udsl_process_send: urb submission failed (%d)!", err); | ||
570 | spin_lock_irq(&instance->send_lock); | ||
571 | list_add(&snd->list, &instance->spare_senders); | ||
572 | spin_unlock_irq(&instance->send_lock); | ||
573 | list_add(&buf->list, &instance->filled_send_buffers); | ||
574 | return; /* bail out */ | ||
575 | } | ||
576 | |||
577 | spin_lock_irq(&instance->send_lock); | ||
578 | } /* while */ | ||
579 | spin_unlock_irq(&instance->send_lock); | ||
580 | |||
581 | if (!instance->current_skb) | ||
582 | instance->current_skb = skb_dequeue(&instance->sndqueue); | ||
583 | if (!instance->current_skb) | ||
584 | return; /* done - no more skbs */ | ||
585 | |||
586 | skb = instance->current_skb; | ||
587 | |||
588 | if (!(buf = instance->current_buffer)) { | ||
589 | spin_lock_irq(&instance->send_lock); | ||
590 | if (list_empty(&instance->spare_send_buffers)) { | ||
591 | instance->current_buffer = NULL; | ||
592 | spin_unlock_irq(&instance->send_lock); | ||
593 | return; /* done - no more buffers */ | ||
594 | } | ||
595 | buf = list_entry(instance->spare_send_buffers.next, | ||
596 | struct udsl_send_buffer, list); | ||
597 | list_del(&buf->list); | ||
598 | spin_unlock_irq(&instance->send_lock); | ||
599 | |||
600 | buf->free_start = buf->base; | ||
601 | buf->free_cells = snd_buf_size; | ||
602 | |||
603 | instance->current_buffer = buf; | ||
604 | } | ||
605 | |||
606 | num_written = udsl_write_cells(instance, buf->free_cells, skb, &buf->free_start); | ||
607 | |||
608 | vdbg("udsl_process_send: wrote %u cells from skb 0x%p to buffer 0x%p", | ||
609 | num_written, skb, buf); | ||
610 | |||
611 | if (!(buf->free_cells -= num_written)) { | ||
612 | list_add_tail(&buf->list, &instance->filled_send_buffers); | ||
613 | instance->current_buffer = NULL; | ||
614 | } | ||
615 | |||
616 | vdbg("udsl_process_send: buffer contains %d cells, %d left", | ||
617 | snd_buf_size - buf->free_cells, buf->free_cells); | ||
618 | |||
619 | if (!UDSL_SKB(skb)->num_cells) { | ||
620 | struct atm_vcc *vcc = UDSL_SKB(skb)->atm_data.vcc; | ||
621 | |||
622 | udsl_pop(vcc, skb); | ||
623 | instance->current_skb = NULL; | ||
624 | |||
625 | atomic_inc(&vcc->stats->tx); | ||
626 | } | ||
627 | |||
628 | goto made_progress; | ||
629 | } | ||
630 | |||
631 | static void udsl_cancel_send(struct udsl_instance_data *instance, | ||
632 | struct atm_vcc *vcc) | ||
633 | { | ||
634 | struct sk_buff *skb, *n; | ||
635 | |||
636 | dbg("udsl_cancel_send entered"); | ||
637 | spin_lock_irq(&instance->sndqueue.lock); | ||
638 | for (skb = instance->sndqueue.next, n = skb->next; | ||
639 | skb != (struct sk_buff *)&instance->sndqueue; | ||
640 | skb = n, n = skb->next) | ||
641 | if (UDSL_SKB(skb)->atm_data.vcc == vcc) { | ||
642 | dbg("udsl_cancel_send: popping skb 0x%p", skb); | ||
643 | __skb_unlink(skb, &instance->sndqueue); | ||
644 | udsl_pop(vcc, skb); | ||
645 | } | ||
646 | spin_unlock_irq(&instance->sndqueue.lock); | ||
647 | |||
648 | tasklet_disable(&instance->send_tasklet); | ||
649 | if ((skb = instance->current_skb) && (UDSL_SKB(skb)->atm_data.vcc == vcc)) { | ||
650 | dbg("udsl_cancel_send: popping current skb (0x%p)", skb); | ||
651 | instance->current_skb = NULL; | ||
652 | udsl_pop(vcc, skb); | ||
653 | } | ||
654 | tasklet_enable(&instance->send_tasklet); | ||
655 | dbg("udsl_cancel_send done"); | ||
656 | } | ||
657 | |||
658 | static int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) | ||
659 | { | ||
660 | struct udsl_instance_data *instance = vcc->dev->dev_data; | ||
661 | int err; | ||
662 | |||
663 | vdbg("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len); | ||
664 | |||
665 | if (!instance) { | ||
666 | dbg("udsl_atm_send: NULL data!"); | ||
667 | err = -ENODEV; | ||
668 | goto fail; | ||
669 | } | ||
670 | |||
671 | if (vcc->qos.aal != ATM_AAL5) { | ||
672 | dbg("udsl_atm_send: unsupported ATM type %d!", vcc->qos.aal); | ||
673 | err = -EINVAL; | ||
674 | goto fail; | ||
675 | } | ||
676 | |||
677 | if (skb->len > ATM_MAX_AAL5_PDU) { | ||
678 | dbg("udsl_atm_send: packet too long (%d vs %d)!", skb->len, | ||
679 | ATM_MAX_AAL5_PDU); | ||
680 | err = -EINVAL; | ||
681 | goto fail; | ||
682 | } | ||
683 | |||
684 | PACKETDEBUG(skb->data, skb->len); | ||
685 | |||
686 | udsl_groom_skb(vcc, skb); | ||
687 | skb_queue_tail(&instance->sndqueue, skb); | ||
688 | tasklet_schedule(&instance->send_tasklet); | ||
689 | |||
690 | return 0; | ||
691 | |||
692 | fail: | ||
693 | udsl_pop(vcc, skb); | ||
694 | return err; | ||
695 | } | ||
696 | |||
697 | /******************** | ||
698 | ** bean counting ** | ||
699 | ********************/ | ||
700 | |||
701 | static void udsl_destroy_instance(struct kref *kref) | ||
702 | { | ||
703 | struct udsl_instance_data *instance = | ||
704 | container_of(kref, struct udsl_instance_data, refcount); | ||
705 | |||
706 | tasklet_kill(&instance->receive_tasklet); | ||
707 | tasklet_kill(&instance->send_tasklet); | ||
708 | usb_put_dev(instance->usb_dev); | ||
709 | kfree(instance); | ||
710 | } | ||
711 | |||
712 | void udsl_get_instance(struct udsl_instance_data *instance) | ||
713 | { | ||
714 | kref_get(&instance->refcount); | ||
715 | } | ||
716 | |||
717 | void udsl_put_instance(struct udsl_instance_data *instance) | ||
718 | { | ||
719 | kref_put(&instance->refcount, udsl_destroy_instance); | ||
720 | } | ||
721 | |||
722 | /********** | ||
723 | ** ATM ** | ||
724 | **********/ | ||
725 | |||
726 | static void udsl_atm_dev_close(struct atm_dev *dev) | ||
727 | { | ||
728 | struct udsl_instance_data *instance = dev->dev_data; | ||
729 | |||
730 | dev->dev_data = NULL; | ||
731 | udsl_put_instance(instance); | ||
732 | } | ||
733 | |||
734 | static int udsl_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page) | ||
735 | { | ||
736 | struct udsl_instance_data *instance = atm_dev->dev_data; | ||
737 | int left = *pos; | ||
738 | |||
739 | if (!instance) { | ||
740 | dbg("udsl_atm_proc_read: NULL instance!"); | ||
741 | return -ENODEV; | ||
742 | } | ||
743 | |||
744 | if (!left--) | ||
745 | return sprintf(page, "%s\n", instance->description); | ||
746 | |||
747 | if (!left--) | ||
748 | return sprintf(page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
749 | atm_dev->esi[0], atm_dev->esi[1], | ||
750 | atm_dev->esi[2], atm_dev->esi[3], | ||
751 | atm_dev->esi[4], atm_dev->esi[5]); | ||
752 | |||
753 | if (!left--) | ||
754 | return sprintf(page, | ||
755 | "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n", | ||
756 | atomic_read(&atm_dev->stats.aal5.tx), | ||
757 | atomic_read(&atm_dev->stats.aal5.tx_err), | ||
758 | atomic_read(&atm_dev->stats.aal5.rx), | ||
759 | atomic_read(&atm_dev->stats.aal5.rx_err), | ||
760 | atomic_read(&atm_dev->stats.aal5.rx_drop)); | ||
761 | |||
762 | if (!left--) { | ||
763 | switch (atm_dev->signal) { | ||
764 | case ATM_PHY_SIG_FOUND: | ||
765 | sprintf(page, "Line up"); | ||
766 | break; | ||
767 | case ATM_PHY_SIG_LOST: | ||
768 | sprintf(page, "Line down"); | ||
769 | break; | ||
770 | default: | ||
771 | sprintf(page, "Line state unknown"); | ||
772 | break; | ||
773 | } | ||
774 | |||
775 | if (instance->usb_dev->state == USB_STATE_NOTATTACHED) | ||
776 | strcat(page, ", disconnected\n"); | ||
777 | else { | ||
778 | if (instance->status == UDSL_LOADED_FIRMWARE) | ||
779 | strcat(page, ", firmware loaded\n"); | ||
780 | else if (instance->status == UDSL_LOADING_FIRMWARE) | ||
781 | strcat(page, ", firmware loading\n"); | ||
782 | else | ||
783 | strcat(page, ", no firmware\n"); | ||
784 | } | ||
785 | |||
786 | return strlen(page); | ||
787 | } | ||
788 | |||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static int udsl_atm_open(struct atm_vcc *vcc) | ||
793 | { | ||
794 | struct udsl_instance_data *instance = vcc->dev->dev_data; | ||
795 | struct udsl_vcc_data *new; | ||
796 | unsigned int max_pdu; | ||
797 | int vci = vcc->vci; | ||
798 | short vpi = vcc->vpi; | ||
799 | int err; | ||
800 | |||
801 | dbg("udsl_atm_open: vpi %hd, vci %d", vpi, vci); | ||
802 | |||
803 | if (!instance) { | ||
804 | dbg("udsl_atm_open: NULL data!"); | ||
805 | return -ENODEV; | ||
806 | } | ||
807 | |||
808 | /* only support AAL5 */ | ||
809 | if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0) | ||
810 | || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) { | ||
811 | dbg("udsl_atm_open: unsupported ATM type %d!", vcc->qos.aal); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
815 | if (instance->firmware_wait && | ||
816 | (err = instance->firmware_wait(instance)) < 0) { | ||
817 | dbg("udsl_atm_open: firmware not loaded (%d)!", err); | ||
818 | return err; | ||
819 | } | ||
820 | |||
821 | down(&instance->serialize); /* vs self, udsl_atm_close */ | ||
822 | |||
823 | if (udsl_find_vcc(instance, vpi, vci)) { | ||
824 | dbg("udsl_atm_open: %hd/%d already in use!", vpi, vci); | ||
825 | up(&instance->serialize); | ||
826 | return -EADDRINUSE; | ||
827 | } | ||
828 | |||
829 | if (!(new = kmalloc(sizeof(struct udsl_vcc_data), GFP_KERNEL))) { | ||
830 | dbg("udsl_atm_open: no memory for vcc_data!"); | ||
831 | up(&instance->serialize); | ||
832 | return -ENOMEM; | ||
833 | } | ||
834 | |||
835 | memset(new, 0, sizeof(struct udsl_vcc_data)); | ||
836 | new->vcc = vcc; | ||
837 | new->vpi = vpi; | ||
838 | new->vci = vci; | ||
839 | |||
840 | /* udsl_extract_cells requires at least one cell */ | ||
841 | max_pdu = max(1, UDSL_NUM_CELLS(vcc->qos.rxtp.max_sdu)) * ATM_CELL_PAYLOAD; | ||
842 | if (!(new->sarb = alloc_skb(max_pdu, GFP_KERNEL))) { | ||
843 | dbg("udsl_atm_open: no memory for SAR buffer!"); | ||
844 | kfree(new); | ||
845 | up(&instance->serialize); | ||
846 | return -ENOMEM; | ||
847 | } | ||
848 | |||
849 | vcc->dev_data = new; | ||
850 | |||
851 | tasklet_disable(&instance->receive_tasklet); | ||
852 | list_add(&new->list, &instance->vcc_list); | ||
853 | tasklet_enable(&instance->receive_tasklet); | ||
854 | |||
855 | set_bit(ATM_VF_ADDR, &vcc->flags); | ||
856 | set_bit(ATM_VF_PARTIAL, &vcc->flags); | ||
857 | set_bit(ATM_VF_READY, &vcc->flags); | ||
858 | |||
859 | up(&instance->serialize); | ||
860 | |||
861 | tasklet_schedule(&instance->receive_tasklet); | ||
862 | |||
863 | dbg("udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)", new, max_pdu); | ||
864 | |||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | static void udsl_atm_close(struct atm_vcc *vcc) | ||
869 | { | ||
870 | struct udsl_instance_data *instance = vcc->dev->dev_data; | ||
871 | struct udsl_vcc_data *vcc_data = vcc->dev_data; | ||
872 | |||
873 | dbg("udsl_atm_close called"); | ||
874 | |||
875 | if (!instance || !vcc_data) { | ||
876 | dbg("udsl_atm_close: NULL data!"); | ||
877 | return; | ||
878 | } | ||
879 | |||
880 | dbg("udsl_atm_close: deallocating vcc 0x%p with vpi %d vci %d", | ||
881 | vcc_data, vcc_data->vpi, vcc_data->vci); | ||
882 | |||
883 | udsl_cancel_send(instance, vcc); | ||
884 | |||
885 | down(&instance->serialize); /* vs self, udsl_atm_open */ | ||
886 | |||
887 | tasklet_disable(&instance->receive_tasklet); | ||
888 | list_del(&vcc_data->list); | ||
889 | tasklet_enable(&instance->receive_tasklet); | ||
890 | |||
891 | kfree_skb(vcc_data->sarb); | ||
892 | vcc_data->sarb = NULL; | ||
893 | |||
894 | kfree(vcc_data); | ||
895 | vcc->dev_data = NULL; | ||
896 | |||
897 | vcc->vpi = ATM_VPI_UNSPEC; | ||
898 | vcc->vci = ATM_VCI_UNSPEC; | ||
899 | clear_bit(ATM_VF_READY, &vcc->flags); | ||
900 | clear_bit(ATM_VF_PARTIAL, &vcc->flags); | ||
901 | clear_bit(ATM_VF_ADDR, &vcc->flags); | ||
902 | |||
903 | up(&instance->serialize); | ||
904 | |||
905 | dbg("udsl_atm_close successful"); | ||
906 | } | ||
907 | |||
908 | static int udsl_atm_ioctl(struct atm_dev *dev, unsigned int cmd, | ||
909 | void __user * arg) | ||
910 | { | ||
911 | switch (cmd) { | ||
912 | case ATM_QUERYLOOP: | ||
913 | return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0; | ||
914 | default: | ||
915 | return -ENOIOCTLCMD; | ||
916 | } | ||
917 | } | ||
918 | |||
919 | /********** | ||
920 | ** USB ** | ||
921 | **********/ | ||
922 | |||
923 | int udsl_instance_setup(struct usb_device *dev, | ||
924 | struct udsl_instance_data *instance) | ||
925 | { | ||
926 | char *buf; | ||
927 | int i, length; | ||
928 | |||
929 | kref_init(&instance->refcount); /* one for USB */ | ||
930 | udsl_get_instance(instance); /* one for ATM */ | ||
931 | |||
932 | init_MUTEX(&instance->serialize); | ||
933 | |||
934 | instance->usb_dev = dev; | ||
935 | |||
936 | INIT_LIST_HEAD(&instance->vcc_list); | ||
937 | |||
938 | instance->status = UDSL_NO_FIRMWARE; | ||
939 | init_waitqueue_head(&instance->firmware_waiters); | ||
940 | |||
941 | spin_lock_init(&instance->receive_lock); | ||
942 | INIT_LIST_HEAD(&instance->spare_receivers); | ||
943 | INIT_LIST_HEAD(&instance->filled_receive_buffers); | ||
944 | |||
945 | tasklet_init(&instance->receive_tasklet, udsl_process_receive, (unsigned long)instance); | ||
946 | INIT_LIST_HEAD(&instance->spare_receive_buffers); | ||
947 | |||
948 | skb_queue_head_init(&instance->sndqueue); | ||
949 | |||
950 | spin_lock_init(&instance->send_lock); | ||
951 | INIT_LIST_HEAD(&instance->spare_senders); | ||
952 | INIT_LIST_HEAD(&instance->spare_send_buffers); | ||
953 | |||
954 | tasklet_init(&instance->send_tasklet, udsl_process_send, | ||
955 | (unsigned long)instance); | ||
956 | INIT_LIST_HEAD(&instance->filled_send_buffers); | ||
957 | |||
958 | /* receive init */ | ||
959 | for (i = 0; i < num_rcv_urbs; i++) { | ||
960 | struct udsl_receiver *rcv = &(instance->receivers[i]); | ||
961 | |||
962 | if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { | ||
963 | dbg("udsl_usb_probe: no memory for receive urb %d!", i); | ||
964 | goto fail; | ||
965 | } | ||
966 | |||
967 | rcv->instance = instance; | ||
968 | |||
969 | list_add(&rcv->list, &instance->spare_receivers); | ||
970 | } | ||
971 | |||
972 | for (i = 0; i < num_rcv_bufs; i++) { | ||
973 | struct udsl_receive_buffer *buf = | ||
974 | &(instance->receive_buffers[i]); | ||
975 | |||
976 | buf->base = kmalloc(rcv_buf_size * (ATM_CELL_SIZE + instance->rcv_padding), | ||
977 | GFP_KERNEL); | ||
978 | if (!buf->base) { | ||
979 | dbg("udsl_usb_probe: no memory for receive buffer %d!", i); | ||
980 | goto fail; | ||
981 | } | ||
982 | |||
983 | list_add(&buf->list, &instance->spare_receive_buffers); | ||
984 | } | ||
985 | |||
986 | /* send init */ | ||
987 | for (i = 0; i < num_snd_urbs; i++) { | ||
988 | struct udsl_sender *snd = &(instance->senders[i]); | ||
989 | |||
990 | if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) { | ||
991 | dbg("udsl_usb_probe: no memory for send urb %d!", i); | ||
992 | goto fail; | ||
993 | } | ||
994 | |||
995 | snd->instance = instance; | ||
996 | |||
997 | list_add(&snd->list, &instance->spare_senders); | ||
998 | } | ||
999 | |||
1000 | for (i = 0; i < num_snd_bufs; i++) { | ||
1001 | struct udsl_send_buffer *buf = &(instance->send_buffers[i]); | ||
1002 | |||
1003 | buf->base = kmalloc(snd_buf_size * (ATM_CELL_SIZE + instance->snd_padding), | ||
1004 | GFP_KERNEL); | ||
1005 | if (!buf->base) { | ||
1006 | dbg("udsl_usb_probe: no memory for send buffer %d!", i); | ||
1007 | goto fail; | ||
1008 | } | ||
1009 | |||
1010 | list_add(&buf->list, &instance->spare_send_buffers); | ||
1011 | } | ||
1012 | |||
1013 | /* ATM init */ | ||
1014 | instance->atm_dev = atm_dev_register(instance->driver_name, | ||
1015 | &udsl_atm_devops, -1, NULL); | ||
1016 | if (!instance->atm_dev) { | ||
1017 | dbg("udsl_usb_probe: failed to register ATM device!"); | ||
1018 | goto fail; | ||
1019 | } | ||
1020 | |||
1021 | instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX; | ||
1022 | instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX; | ||
1023 | instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | ||
1024 | |||
1025 | /* temp init ATM device, set to 128kbit */ | ||
1026 | instance->atm_dev->link_rate = 128 * 1000 / 424; | ||
1027 | |||
1028 | /* device description */ | ||
1029 | buf = instance->description; | ||
1030 | length = sizeof(instance->description); | ||
1031 | |||
1032 | if ((i = usb_string(dev, dev->descriptor.iProduct, buf, length)) < 0) | ||
1033 | goto finish; | ||
1034 | |||
1035 | buf += i; | ||
1036 | length -= i; | ||
1037 | |||
1038 | i = scnprintf(buf, length, " ("); | ||
1039 | buf += i; | ||
1040 | length -= i; | ||
1041 | |||
1042 | if (length <= 0 || (i = usb_make_path(dev, buf, length)) < 0) | ||
1043 | goto finish; | ||
1044 | |||
1045 | buf += i; | ||
1046 | length -= i; | ||
1047 | |||
1048 | snprintf(buf, length, ")"); | ||
1049 | |||
1050 | finish: | ||
1051 | /* ready for ATM callbacks */ | ||
1052 | wmb(); | ||
1053 | instance->atm_dev->dev_data = instance; | ||
1054 | |||
1055 | usb_get_dev(dev); | ||
1056 | |||
1057 | return 0; | ||
1058 | |||
1059 | fail: | ||
1060 | for (i = 0; i < num_snd_bufs; i++) | ||
1061 | kfree(instance->send_buffers[i].base); | ||
1062 | |||
1063 | for (i = 0; i < num_snd_urbs; i++) | ||
1064 | usb_free_urb(instance->senders[i].urb); | ||
1065 | |||
1066 | for (i = 0; i < num_rcv_bufs; i++) | ||
1067 | kfree(instance->receive_buffers[i].base); | ||
1068 | |||
1069 | for (i = 0; i < num_rcv_urbs; i++) | ||
1070 | usb_free_urb(instance->receivers[i].urb); | ||
1071 | |||
1072 | return -ENOMEM; | ||
1073 | } | ||
1074 | |||
1075 | void udsl_instance_disconnect(struct udsl_instance_data *instance) | ||
1076 | { | ||
1077 | int i; | ||
1078 | |||
1079 | dbg("udsl_instance_disconnect entered"); | ||
1080 | |||
1081 | if (!instance) { | ||
1082 | dbg("udsl_instance_disconnect: NULL instance!"); | ||
1083 | return; | ||
1084 | } | ||
1085 | |||
1086 | /* receive finalize */ | ||
1087 | tasklet_disable(&instance->receive_tasklet); | ||
1088 | |||
1089 | for (i = 0; i < num_rcv_urbs; i++) | ||
1090 | usb_kill_urb(instance->receivers[i].urb); | ||
1091 | |||
1092 | /* no need to take the spinlock */ | ||
1093 | INIT_LIST_HEAD(&instance->filled_receive_buffers); | ||
1094 | INIT_LIST_HEAD(&instance->spare_receive_buffers); | ||
1095 | |||
1096 | tasklet_enable(&instance->receive_tasklet); | ||
1097 | |||
1098 | for (i = 0; i < num_rcv_urbs; i++) | ||
1099 | usb_free_urb(instance->receivers[i].urb); | ||
1100 | |||
1101 | for (i = 0; i < num_rcv_bufs; i++) | ||
1102 | kfree(instance->receive_buffers[i].base); | ||
1103 | |||
1104 | /* send finalize */ | ||
1105 | tasklet_disable(&instance->send_tasklet); | ||
1106 | |||
1107 | for (i = 0; i < num_snd_urbs; i++) | ||
1108 | usb_kill_urb(instance->senders[i].urb); | ||
1109 | |||
1110 | /* no need to take the spinlock */ | ||
1111 | INIT_LIST_HEAD(&instance->spare_senders); | ||
1112 | INIT_LIST_HEAD(&instance->spare_send_buffers); | ||
1113 | instance->current_buffer = NULL; | ||
1114 | |||
1115 | tasklet_enable(&instance->send_tasklet); | ||
1116 | |||
1117 | for (i = 0; i < num_snd_urbs; i++) | ||
1118 | usb_free_urb(instance->senders[i].urb); | ||
1119 | |||
1120 | for (i = 0; i < num_snd_bufs; i++) | ||
1121 | kfree(instance->send_buffers[i].base); | ||
1122 | |||
1123 | /* ATM finalize */ | ||
1124 | shutdown_atm_dev(instance->atm_dev); | ||
1125 | } | ||
1126 | |||
1127 | EXPORT_SYMBOL_GPL(udsl_get_instance); | ||
1128 | EXPORT_SYMBOL_GPL(udsl_put_instance); | ||
1129 | EXPORT_SYMBOL_GPL(udsl_instance_setup); | ||
1130 | EXPORT_SYMBOL_GPL(udsl_instance_disconnect); | ||
1131 | |||
1132 | /*********** | ||
1133 | ** init ** | ||
1134 | ***********/ | ||
1135 | |||
1136 | static int __init udsl_usb_init(void) | ||
1137 | { | ||
1138 | dbg("udsl_usb_init: driver version " DRIVER_VERSION); | ||
1139 | |||
1140 | if (sizeof(struct udsl_control) > sizeof(((struct sk_buff *) 0)->cb)) { | ||
1141 | printk(KERN_ERR __FILE__ ": unusable with this kernel!\n"); | ||
1142 | return -EIO; | ||
1143 | } | ||
1144 | |||
1145 | if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) | ||
1146 | || (num_snd_urbs > UDSL_MAX_SND_URBS) | ||
1147 | || (num_rcv_bufs > UDSL_MAX_RCV_BUFS) | ||
1148 | || (num_snd_bufs > UDSL_MAX_SND_BUFS) | ||
1149 | || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE) | ||
1150 | || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE)) | ||
1151 | return -EINVAL; | ||
1152 | |||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1156 | static void __exit udsl_usb_exit(void) | ||
1157 | { | ||
1158 | } | ||
1159 | |||
1160 | module_init(udsl_usb_init); | ||
1161 | module_exit(udsl_usb_exit); | ||
1162 | |||
1163 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1164 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1165 | MODULE_LICENSE("GPL"); | ||
1166 | MODULE_VERSION(DRIVER_VERSION); | ||
1167 | |||
1168 | /************ | ||
1169 | ** debug ** | ||
1170 | ************/ | ||
1171 | |||
1172 | #ifdef VERBOSE_DEBUG | ||
1173 | static int udsl_print_packet(const unsigned char *data, int len) | ||
1174 | { | ||
1175 | unsigned char buffer[256]; | ||
1176 | int i = 0, j = 0; | ||
1177 | |||
1178 | for (i = 0; i < len;) { | ||
1179 | buffer[0] = '\0'; | ||
1180 | sprintf(buffer, "%.3d :", i); | ||
1181 | for (j = 0; (j < 16) && (i < len); j++, i++) { | ||
1182 | sprintf(buffer, "%s %2.2x", buffer, data[i]); | ||
1183 | } | ||
1184 | dbg("%s", buffer); | ||
1185 | } | ||
1186 | return i; | ||
1187 | } | ||
1188 | #endif | ||
diff --git a/drivers/usb/atm/usb_atm.h b/drivers/usb/atm/usb_atm.h deleted file mode 100644 index cf8c53283530..000000000000 --- a/drivers/usb/atm/usb_atm.h +++ /dev/null | |||
@@ -1,176 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * usb_atm.h - Generic USB xDSL driver core | ||
3 | * | ||
4 | * Copyright (C) 2001, Alcatel | ||
5 | * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas | ||
6 | * Copyright (C) 2004, David Woodhouse | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/kref.h> | ||
27 | #include <linux/atm.h> | ||
28 | #include <linux/atmdev.h> | ||
29 | #include <asm/semaphore.h> | ||
30 | |||
31 | /* | ||
32 | #define DEBUG | ||
33 | #define VERBOSE_DEBUG | ||
34 | */ | ||
35 | |||
36 | #if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) | ||
37 | # define DEBUG | ||
38 | #endif | ||
39 | |||
40 | #include <linux/usb.h> | ||
41 | |||
42 | #ifdef DEBUG | ||
43 | #define UDSL_ASSERT(x) BUG_ON(!(x)) | ||
44 | #else | ||
45 | #define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '" #x "' at line %d", __LINE__); } while(0) | ||
46 | #endif | ||
47 | |||
48 | #define UDSL_MAX_RCV_URBS 4 | ||
49 | #define UDSL_MAX_SND_URBS 4 | ||
50 | #define UDSL_MAX_RCV_BUFS 8 | ||
51 | #define UDSL_MAX_SND_BUFS 8 | ||
52 | #define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */ | ||
53 | #define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */ | ||
54 | #define UDSL_DEFAULT_RCV_URBS 2 | ||
55 | #define UDSL_DEFAULT_SND_URBS 2 | ||
56 | #define UDSL_DEFAULT_RCV_BUFS 4 | ||
57 | #define UDSL_DEFAULT_SND_BUFS 4 | ||
58 | #define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */ | ||
59 | #define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */ | ||
60 | |||
61 | #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) | ||
62 | #define UDSL_NUM_CELLS(x) (((x) + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD) | ||
63 | |||
64 | /* receive */ | ||
65 | |||
66 | struct udsl_receive_buffer { | ||
67 | struct list_head list; | ||
68 | unsigned char *base; | ||
69 | unsigned int filled_cells; | ||
70 | }; | ||
71 | |||
72 | struct udsl_receiver { | ||
73 | struct list_head list; | ||
74 | struct udsl_receive_buffer *buffer; | ||
75 | struct urb *urb; | ||
76 | struct udsl_instance_data *instance; | ||
77 | }; | ||
78 | |||
79 | struct udsl_vcc_data { | ||
80 | /* vpi/vci lookup */ | ||
81 | struct list_head list; | ||
82 | short vpi; | ||
83 | int vci; | ||
84 | struct atm_vcc *vcc; | ||
85 | |||
86 | /* raw cell reassembly */ | ||
87 | struct sk_buff *sarb; | ||
88 | }; | ||
89 | |||
90 | /* send */ | ||
91 | |||
92 | struct udsl_send_buffer { | ||
93 | struct list_head list; | ||
94 | unsigned char *base; | ||
95 | unsigned char *free_start; | ||
96 | unsigned int free_cells; | ||
97 | }; | ||
98 | |||
99 | struct udsl_sender { | ||
100 | struct list_head list; | ||
101 | struct udsl_send_buffer *buffer; | ||
102 | struct urb *urb; | ||
103 | struct udsl_instance_data *instance; | ||
104 | }; | ||
105 | |||
106 | struct udsl_control { | ||
107 | struct atm_skb_data atm_data; | ||
108 | unsigned int num_cells; | ||
109 | unsigned int num_entire; | ||
110 | unsigned int pdu_padding; | ||
111 | unsigned char aal5_trailer[ATM_AAL5_TRAILER]; | ||
112 | }; | ||
113 | |||
114 | #define UDSL_SKB(x) ((struct udsl_control *)(x)->cb) | ||
115 | |||
116 | /* main driver data */ | ||
117 | |||
118 | enum udsl_status { | ||
119 | UDSL_NO_FIRMWARE, | ||
120 | UDSL_LOADING_FIRMWARE, | ||
121 | UDSL_LOADED_FIRMWARE | ||
122 | }; | ||
123 | |||
124 | struct udsl_instance_data { | ||
125 | struct kref refcount; | ||
126 | struct semaphore serialize; | ||
127 | |||
128 | /* USB device part */ | ||
129 | struct usb_device *usb_dev; | ||
130 | char description[64]; | ||
131 | int data_endpoint; | ||
132 | int snd_padding; | ||
133 | int rcv_padding; | ||
134 | const char *driver_name; | ||
135 | |||
136 | /* ATM device part */ | ||
137 | struct atm_dev *atm_dev; | ||
138 | struct list_head vcc_list; | ||
139 | |||
140 | /* firmware */ | ||
141 | int (*firmware_wait) (struct udsl_instance_data *); | ||
142 | enum udsl_status status; | ||
143 | wait_queue_head_t firmware_waiters; | ||
144 | |||
145 | /* receive */ | ||
146 | struct udsl_receiver receivers[UDSL_MAX_RCV_URBS]; | ||
147 | struct udsl_receive_buffer receive_buffers[UDSL_MAX_RCV_BUFS]; | ||
148 | |||
149 | spinlock_t receive_lock; | ||
150 | struct list_head spare_receivers; | ||
151 | struct list_head filled_receive_buffers; | ||
152 | |||
153 | struct tasklet_struct receive_tasklet; | ||
154 | struct list_head spare_receive_buffers; | ||
155 | |||
156 | /* send */ | ||
157 | struct udsl_sender senders[UDSL_MAX_SND_URBS]; | ||
158 | struct udsl_send_buffer send_buffers[UDSL_MAX_SND_BUFS]; | ||
159 | |||
160 | struct sk_buff_head sndqueue; | ||
161 | |||
162 | spinlock_t send_lock; | ||
163 | struct list_head spare_senders; | ||
164 | struct list_head spare_send_buffers; | ||
165 | |||
166 | struct tasklet_struct send_tasklet; | ||
167 | struct sk_buff *current_skb; /* being emptied */ | ||
168 | struct udsl_send_buffer *current_buffer; /* being filled */ | ||
169 | struct list_head filled_send_buffers; | ||
170 | }; | ||
171 | |||
172 | extern int udsl_instance_setup(struct usb_device *dev, | ||
173 | struct udsl_instance_data *instance); | ||
174 | extern void udsl_instance_disconnect(struct udsl_instance_data *instance); | ||
175 | extern void udsl_get_instance(struct udsl_instance_data *instance); | ||
176 | extern void udsl_put_instance(struct udsl_instance_data *instance); | ||
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c new file mode 100644 index 000000000000..bb1db1959854 --- /dev/null +++ b/drivers/usb/atm/usbatm.c | |||
@@ -0,0 +1,1230 @@ | |||
1 | /****************************************************************************** | ||
2 | * usbatm.c - Generic USB xDSL driver core | ||
3 | * | ||
4 | * Copyright (C) 2001, Alcatel | ||
5 | * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas | ||
6 | * Copyright (C) 2004, David Woodhouse, Roman Kagan | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | /* | ||
25 | * Written by Johan Verrept, Duncan Sands (duncan.sands@free.fr) and David Woodhouse | ||
26 | * | ||
27 | * 1.7+: - See the check-in logs | ||
28 | * | ||
29 | * 1.6: - No longer opens a connection if the firmware is not loaded | ||
30 | * - Added support for the speedtouch 330 | ||
31 | * - Removed the limit on the number of devices | ||
32 | * - Module now autoloads on device plugin | ||
33 | * - Merged relevant parts of sarlib | ||
34 | * - Replaced the kernel thread with a tasklet | ||
35 | * - New packet transmission code | ||
36 | * - Changed proc file contents | ||
37 | * - Fixed all known SMP races | ||
38 | * - Many fixes and cleanups | ||
39 | * - Various fixes by Oliver Neukum (oliver@neukum.name) | ||
40 | * | ||
41 | * 1.5A: - Version for inclusion in 2.5 series kernel | ||
42 | * - Modifications by Richard Purdie (rpurdie@rpsys.net) | ||
43 | * - made compatible with kernel 2.5.6 onwards by changing | ||
44 | * usbatm_usb_send_data_context->urb to a pointer and adding code | ||
45 | * to alloc and free it | ||
46 | * - remove_wait_queue() added to usbatm_atm_processqueue_thread() | ||
47 | * | ||
48 | * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL. | ||
49 | * (reported by stephen.robinson@zen.co.uk) | ||
50 | * | ||
51 | * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave() | ||
52 | * - unlink all active send urbs of a vcc that is being closed. | ||
53 | * | ||
54 | * 1.3.1: - added the version number | ||
55 | * | ||
56 | * 1.3: - Added multiple send urb support | ||
57 | * - fixed memory leak and vcc->tx_inuse starvation bug | ||
58 | * when not enough memory left in vcc. | ||
59 | * | ||
60 | * 1.2: - Fixed race condition in usbatm_usb_send_data() | ||
61 | * 1.1: - Turned off packet debugging | ||
62 | * | ||
63 | */ | ||
64 | |||
65 | #include "usbatm.h" | ||
66 | |||
67 | #include <asm/uaccess.h> | ||
68 | #include <linux/crc32.h> | ||
69 | #include <linux/errno.h> | ||
70 | #include <linux/init.h> | ||
71 | #include <linux/interrupt.h> | ||
72 | #include <linux/kernel.h> | ||
73 | #include <linux/module.h> | ||
74 | #include <linux/moduleparam.h> | ||
75 | #include <linux/proc_fs.h> | ||
76 | #include <linux/sched.h> | ||
77 | #include <linux/signal.h> | ||
78 | #include <linux/slab.h> | ||
79 | #include <linux/smp_lock.h> | ||
80 | #include <linux/stat.h> | ||
81 | #include <linux/timer.h> | ||
82 | #include <linux/wait.h> | ||
83 | |||
84 | #ifdef VERBOSE_DEBUG | ||
85 | static int usbatm_print_packet(const unsigned char *data, int len); | ||
86 | #define PACKETDEBUG(arg...) usbatm_print_packet (arg) | ||
87 | #define vdbg(arg...) dbg (arg) | ||
88 | #else | ||
89 | #define PACKETDEBUG(arg...) | ||
90 | #define vdbg(arg...) | ||
91 | #endif | ||
92 | |||
93 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" | ||
94 | #define DRIVER_VERSION "1.9" | ||
95 | #define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION | ||
96 | |||
97 | static const char usbatm_driver_name[] = "usbatm"; | ||
98 | |||
99 | #define UDSL_MAX_RCV_URBS 16 | ||
100 | #define UDSL_MAX_SND_URBS 16 | ||
101 | #define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */ | ||
102 | #define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */ | ||
103 | #define UDSL_DEFAULT_RCV_URBS 4 | ||
104 | #define UDSL_DEFAULT_SND_URBS 4 | ||
105 | #define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */ | ||
106 | #define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */ | ||
107 | |||
108 | #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) | ||
109 | |||
110 | #define THROTTLE_MSECS 100 /* delay to recover processing after urb submission fails */ | ||
111 | |||
112 | static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; | ||
113 | static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; | ||
114 | static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE; | ||
115 | static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE; | ||
116 | |||
117 | module_param(num_rcv_urbs, uint, S_IRUGO); | ||
118 | MODULE_PARM_DESC(num_rcv_urbs, | ||
119 | "Number of urbs used for reception (range: 0-" | ||
120 | __MODULE_STRING(UDSL_MAX_RCV_URBS) ", default: " | ||
121 | __MODULE_STRING(UDSL_DEFAULT_RCV_URBS) ")"); | ||
122 | |||
123 | module_param(num_snd_urbs, uint, S_IRUGO); | ||
124 | MODULE_PARM_DESC(num_snd_urbs, | ||
125 | "Number of urbs used for transmission (range: 0-" | ||
126 | __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: " | ||
127 | __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")"); | ||
128 | |||
129 | module_param(rcv_buf_size, uint, S_IRUGO); | ||
130 | MODULE_PARM_DESC(rcv_buf_size, | ||
131 | "Size of the buffers used for reception in ATM cells (range: 1-" | ||
132 | __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: " | ||
133 | __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")"); | ||
134 | |||
135 | module_param(snd_buf_size, uint, S_IRUGO); | ||
136 | MODULE_PARM_DESC(snd_buf_size, | ||
137 | "Size of the buffers used for transmission in ATM cells (range: 1-" | ||
138 | __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: " | ||
139 | __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")"); | ||
140 | |||
141 | |||
142 | /* receive */ | ||
143 | |||
144 | struct usbatm_vcc_data { | ||
145 | /* vpi/vci lookup */ | ||
146 | struct list_head list; | ||
147 | short vpi; | ||
148 | int vci; | ||
149 | struct atm_vcc *vcc; | ||
150 | |||
151 | /* raw cell reassembly */ | ||
152 | struct sk_buff *sarb; | ||
153 | }; | ||
154 | |||
155 | |||
156 | /* send */ | ||
157 | |||
158 | struct usbatm_control { | ||
159 | struct atm_skb_data atm; | ||
160 | u32 len; | ||
161 | u32 crc; | ||
162 | }; | ||
163 | |||
164 | #define UDSL_SKB(x) ((struct usbatm_control *)(x)->cb) | ||
165 | |||
166 | |||
167 | /* ATM */ | ||
168 | |||
169 | static void usbatm_atm_dev_close(struct atm_dev *dev); | ||
170 | static int usbatm_atm_open(struct atm_vcc *vcc); | ||
171 | static void usbatm_atm_close(struct atm_vcc *vcc); | ||
172 | static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg); | ||
173 | static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb); | ||
174 | static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page); | ||
175 | |||
176 | static struct atmdev_ops usbatm_atm_devops = { | ||
177 | .dev_close = usbatm_atm_dev_close, | ||
178 | .open = usbatm_atm_open, | ||
179 | .close = usbatm_atm_close, | ||
180 | .ioctl = usbatm_atm_ioctl, | ||
181 | .send = usbatm_atm_send, | ||
182 | .proc_read = usbatm_atm_proc_read, | ||
183 | .owner = THIS_MODULE, | ||
184 | }; | ||
185 | |||
186 | |||
187 | /*********** | ||
188 | ** misc ** | ||
189 | ***********/ | ||
190 | |||
191 | static inline unsigned int usbatm_pdu_length(unsigned int length) | ||
192 | { | ||
193 | length += ATM_CELL_PAYLOAD - 1 + ATM_AAL5_TRAILER; | ||
194 | return length - length % ATM_CELL_PAYLOAD; | ||
195 | } | ||
196 | |||
197 | static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb) | ||
198 | { | ||
199 | if (vcc->pop) | ||
200 | vcc->pop(vcc, skb); | ||
201 | else | ||
202 | dev_kfree_skb(skb); | ||
203 | } | ||
204 | |||
205 | |||
206 | /*********** | ||
207 | ** urbs ** | ||
208 | ************/ | ||
209 | |||
210 | static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel) | ||
211 | { | ||
212 | struct urb *urb; | ||
213 | |||
214 | spin_lock_irq(&channel->lock); | ||
215 | if (list_empty(&channel->list)) { | ||
216 | spin_unlock_irq(&channel->lock); | ||
217 | return NULL; | ||
218 | } | ||
219 | |||
220 | urb = list_entry(channel->list.next, struct urb, urb_list); | ||
221 | list_del(&urb->urb_list); | ||
222 | spin_unlock_irq(&channel->lock); | ||
223 | |||
224 | return urb; | ||
225 | } | ||
226 | |||
227 | static inline int usbatm_submit_urb(struct urb *urb) | ||
228 | { | ||
229 | struct usbatm_channel *channel = urb->context; | ||
230 | int ret; | ||
231 | |||
232 | vdbg("%s: submitting urb 0x%p, size %u", | ||
233 | __func__, urb, urb->transfer_buffer_length); | ||
234 | |||
235 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
236 | if (ret) { | ||
237 | atm_dbg(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n", | ||
238 | __func__, urb, ret); | ||
239 | |||
240 | /* consider all errors transient and return the buffer back to the queue */ | ||
241 | urb->status = -EAGAIN; | ||
242 | spin_lock_irq(&channel->lock); | ||
243 | |||
244 | /* must add to the front when sending; doesn't matter when receiving */ | ||
245 | list_add(&urb->urb_list, &channel->list); | ||
246 | |||
247 | spin_unlock_irq(&channel->lock); | ||
248 | |||
249 | /* make sure the channel doesn't stall */ | ||
250 | mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS)); | ||
251 | } | ||
252 | |||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | static void usbatm_complete(struct urb *urb, struct pt_regs *regs) | ||
257 | { | ||
258 | struct usbatm_channel *channel = urb->context; | ||
259 | unsigned long flags; | ||
260 | |||
261 | vdbg("%s: urb 0x%p, status %d, actual_length %d", | ||
262 | __func__, urb, urb->status, urb->actual_length); | ||
263 | |||
264 | /* usually in_interrupt(), but not always */ | ||
265 | spin_lock_irqsave(&channel->lock, flags); | ||
266 | |||
267 | /* must add to the back when receiving; doesn't matter when sending */ | ||
268 | list_add_tail(&urb->urb_list, &channel->list); | ||
269 | |||
270 | spin_unlock_irqrestore(&channel->lock, flags); | ||
271 | |||
272 | if (unlikely(urb->status)) | ||
273 | /* throttle processing in case of an error */ | ||
274 | mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS)); | ||
275 | else | ||
276 | tasklet_schedule(&channel->tasklet); | ||
277 | } | ||
278 | |||
279 | |||
280 | /************* | ||
281 | ** decode ** | ||
282 | *************/ | ||
283 | |||
284 | static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance, | ||
285 | short vpi, int vci) | ||
286 | { | ||
287 | struct usbatm_vcc_data *vcc; | ||
288 | |||
289 | list_for_each_entry(vcc, &instance->vcc_list, list) | ||
290 | if ((vcc->vci == vci) && (vcc->vpi == vpi)) | ||
291 | return vcc; | ||
292 | return NULL; | ||
293 | } | ||
294 | |||
295 | static void usbatm_extract_cells(struct usbatm_data *instance, | ||
296 | unsigned char *source, unsigned int avail_data) | ||
297 | { | ||
298 | struct usbatm_vcc_data *cached_vcc = NULL; | ||
299 | struct atm_vcc *vcc; | ||
300 | struct sk_buff *sarb; | ||
301 | unsigned int stride = instance->rx_channel.stride; | ||
302 | int vci, cached_vci = 0; | ||
303 | short vpi, cached_vpi = 0; | ||
304 | u8 pti; | ||
305 | |||
306 | for (; avail_data >= stride; avail_data -= stride, source += stride) { | ||
307 | vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4); | ||
308 | vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4); | ||
309 | pti = ((source[3] & 0xe) >> 1); | ||
310 | |||
311 | vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti); | ||
312 | |||
313 | if ((vci != cached_vci) || (vpi != cached_vpi)) { | ||
314 | cached_vpi = vpi; | ||
315 | cached_vci = vci; | ||
316 | |||
317 | cached_vcc = usbatm_find_vcc(instance, vpi, vci); | ||
318 | |||
319 | if (!cached_vcc) | ||
320 | atm_dbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci); | ||
321 | } | ||
322 | |||
323 | if (!cached_vcc) | ||
324 | continue; | ||
325 | |||
326 | vcc = cached_vcc->vcc; | ||
327 | |||
328 | /* OAM F5 end-to-end */ | ||
329 | if (pti == ATM_PTI_E2EF5) { | ||
330 | atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n", __func__, vpi, vci); | ||
331 | atomic_inc(&vcc->stats->rx_err); | ||
332 | continue; | ||
333 | } | ||
334 | |||
335 | sarb = cached_vcc->sarb; | ||
336 | |||
337 | if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) { | ||
338 | atm_dbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n", | ||
339 | __func__, sarb->len, vcc); | ||
340 | /* discard cells already received */ | ||
341 | skb_trim(sarb, 0); | ||
342 | UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end); | ||
343 | } | ||
344 | |||
345 | memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); | ||
346 | __skb_put(sarb, ATM_CELL_PAYLOAD); | ||
347 | |||
348 | if (pti & 1) { | ||
349 | struct sk_buff *skb; | ||
350 | unsigned int length; | ||
351 | unsigned int pdu_length; | ||
352 | |||
353 | length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5]; | ||
354 | |||
355 | /* guard against overflow */ | ||
356 | if (length > ATM_MAX_AAL5_PDU) { | ||
357 | atm_dbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n", | ||
358 | __func__, length, vcc); | ||
359 | atomic_inc(&vcc->stats->rx_err); | ||
360 | goto out; | ||
361 | } | ||
362 | |||
363 | pdu_length = usbatm_pdu_length(length); | ||
364 | |||
365 | if (sarb->len < pdu_length) { | ||
366 | atm_dbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n", | ||
367 | __func__, pdu_length, sarb->len, vcc); | ||
368 | atomic_inc(&vcc->stats->rx_err); | ||
369 | goto out; | ||
370 | } | ||
371 | |||
372 | if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) { | ||
373 | atm_dbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n", | ||
374 | __func__, vcc); | ||
375 | atomic_inc(&vcc->stats->rx_err); | ||
376 | goto out; | ||
377 | } | ||
378 | |||
379 | vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc); | ||
380 | |||
381 | if (!(skb = dev_alloc_skb(length))) { | ||
382 | atm_dbg(instance, "%s: no memory for skb (length: %u)!\n", __func__, length); | ||
383 | atomic_inc(&vcc->stats->rx_drop); | ||
384 | goto out; | ||
385 | } | ||
386 | |||
387 | vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize); | ||
388 | |||
389 | if (!atm_charge(vcc, skb->truesize)) { | ||
390 | atm_dbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n", __func__, skb->truesize); | ||
391 | dev_kfree_skb(skb); | ||
392 | goto out; /* atm_charge increments rx_drop */ | ||
393 | } | ||
394 | |||
395 | memcpy(skb->data, sarb->tail - pdu_length, length); | ||
396 | __skb_put(skb, length); | ||
397 | |||
398 | vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u", | ||
399 | __func__, skb, skb->len, skb->truesize); | ||
400 | |||
401 | PACKETDEBUG(skb->data, skb->len); | ||
402 | |||
403 | vcc->push(vcc, skb); | ||
404 | |||
405 | atomic_inc(&vcc->stats->rx); | ||
406 | out: | ||
407 | skb_trim(sarb, 0); | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | |||
412 | |||
413 | /************* | ||
414 | ** encode ** | ||
415 | *************/ | ||
416 | |||
417 | static unsigned int usbatm_write_cells(struct usbatm_data *instance, | ||
418 | struct sk_buff *skb, | ||
419 | u8 *target, unsigned int avail_space) | ||
420 | { | ||
421 | struct usbatm_control *ctrl = UDSL_SKB(skb); | ||
422 | struct atm_vcc *vcc = ctrl->atm.vcc; | ||
423 | unsigned int num_written; | ||
424 | unsigned int stride = instance->tx_channel.stride; | ||
425 | |||
426 | vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space); | ||
427 | UDSL_ASSERT(!(avail_space % stride)); | ||
428 | |||
429 | for (num_written = 0; num_written < avail_space && ctrl->len; | ||
430 | num_written += stride, target += stride) { | ||
431 | unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD); | ||
432 | unsigned int left = ATM_CELL_PAYLOAD - data_len; | ||
433 | u8 *ptr = target; | ||
434 | |||
435 | ptr[0] = vcc->vpi >> 4; | ||
436 | ptr[1] = (vcc->vpi << 4) | (vcc->vci >> 12); | ||
437 | ptr[2] = vcc->vci >> 4; | ||
438 | ptr[3] = vcc->vci << 4; | ||
439 | ptr[4] = 0xec; | ||
440 | ptr += ATM_CELL_HEADER; | ||
441 | |||
442 | memcpy(ptr, skb->data, data_len); | ||
443 | ptr += data_len; | ||
444 | __skb_pull(skb, data_len); | ||
445 | |||
446 | if(!left) | ||
447 | continue; | ||
448 | |||
449 | memset(ptr, 0, left); | ||
450 | |||
451 | if (left >= ATM_AAL5_TRAILER) { /* trailer will go in this cell */ | ||
452 | u8 *trailer = target + ATM_CELL_SIZE - ATM_AAL5_TRAILER; | ||
453 | /* trailer[0] = 0; UU = 0 */ | ||
454 | /* trailer[1] = 0; CPI = 0 */ | ||
455 | trailer[2] = ctrl->len >> 8; | ||
456 | trailer[3] = ctrl->len; | ||
457 | |||
458 | ctrl->crc = ~ crc32_be(ctrl->crc, ptr, left - 4); | ||
459 | |||
460 | trailer[4] = ctrl->crc >> 24; | ||
461 | trailer[5] = ctrl->crc >> 16; | ||
462 | trailer[6] = ctrl->crc >> 8; | ||
463 | trailer[7] = ctrl->crc; | ||
464 | |||
465 | target[3] |= 0x2; /* adjust PTI */ | ||
466 | |||
467 | ctrl->len = 0; /* tag this skb finished */ | ||
468 | } | ||
469 | else | ||
470 | ctrl->crc = crc32_be(ctrl->crc, ptr, left); | ||
471 | } | ||
472 | |||
473 | return num_written; | ||
474 | } | ||
475 | |||
476 | |||
477 | /************** | ||
478 | ** receive ** | ||
479 | **************/ | ||
480 | |||
481 | static void usbatm_rx_process(unsigned long data) | ||
482 | { | ||
483 | struct usbatm_data *instance = (struct usbatm_data *)data; | ||
484 | struct urb *urb; | ||
485 | |||
486 | while ((urb = usbatm_pop_urb(&instance->rx_channel))) { | ||
487 | vdbg("%s: processing urb 0x%p", __func__, urb); | ||
488 | |||
489 | if (usb_pipeisoc(urb->pipe)) { | ||
490 | int i; | ||
491 | for (i = 0; i < urb->number_of_packets; i++) | ||
492 | if (!urb->iso_frame_desc[i].status) | ||
493 | usbatm_extract_cells(instance, | ||
494 | (u8 *)urb->transfer_buffer + urb->iso_frame_desc[i].offset, | ||
495 | urb->iso_frame_desc[i].actual_length); | ||
496 | } | ||
497 | else | ||
498 | if (!urb->status) | ||
499 | usbatm_extract_cells(instance, urb->transfer_buffer, urb->actual_length); | ||
500 | |||
501 | if (usbatm_submit_urb(urb)) | ||
502 | return; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | |||
507 | /*********** | ||
508 | ** send ** | ||
509 | ***********/ | ||
510 | |||
511 | static void usbatm_tx_process(unsigned long data) | ||
512 | { | ||
513 | struct usbatm_data *instance = (struct usbatm_data *)data; | ||
514 | struct sk_buff *skb = instance->current_skb; | ||
515 | struct urb *urb = NULL; | ||
516 | const unsigned int buf_size = instance->tx_channel.buf_size; | ||
517 | unsigned int num_written = 0; | ||
518 | u8 *buffer = NULL; | ||
519 | |||
520 | if (!skb) | ||
521 | skb = skb_dequeue(&instance->sndqueue); | ||
522 | |||
523 | while (skb) { | ||
524 | if (!urb) { | ||
525 | urb = usbatm_pop_urb(&instance->tx_channel); | ||
526 | if (!urb) | ||
527 | break; /* no more senders */ | ||
528 | buffer = urb->transfer_buffer; | ||
529 | num_written = (urb->status == -EAGAIN) ? | ||
530 | urb->transfer_buffer_length : 0; | ||
531 | } | ||
532 | |||
533 | num_written += usbatm_write_cells(instance, skb, | ||
534 | buffer + num_written, | ||
535 | buf_size - num_written); | ||
536 | |||
537 | vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p", | ||
538 | __func__, num_written, skb, urb); | ||
539 | |||
540 | if (!UDSL_SKB(skb)->len) { | ||
541 | struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc; | ||
542 | |||
543 | usbatm_pop(vcc, skb); | ||
544 | atomic_inc(&vcc->stats->tx); | ||
545 | |||
546 | skb = skb_dequeue(&instance->sndqueue); | ||
547 | } | ||
548 | |||
549 | if (num_written == buf_size || (!skb && num_written)) { | ||
550 | urb->transfer_buffer_length = num_written; | ||
551 | |||
552 | if (usbatm_submit_urb(urb)) | ||
553 | break; | ||
554 | urb = NULL; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | instance->current_skb = skb; | ||
559 | } | ||
560 | |||
561 | static void usbatm_cancel_send(struct usbatm_data *instance, | ||
562 | struct atm_vcc *vcc) | ||
563 | { | ||
564 | struct sk_buff *skb, *n; | ||
565 | |||
566 | atm_dbg(instance, "%s entered\n", __func__); | ||
567 | spin_lock_irq(&instance->sndqueue.lock); | ||
568 | for (skb = instance->sndqueue.next, n = skb->next; | ||
569 | skb != (struct sk_buff *)&instance->sndqueue; | ||
570 | skb = n, n = skb->next) | ||
571 | if (UDSL_SKB(skb)->atm.vcc == vcc) { | ||
572 | atm_dbg(instance, "%s: popping skb 0x%p\n", __func__, skb); | ||
573 | __skb_unlink(skb, &instance->sndqueue); | ||
574 | usbatm_pop(vcc, skb); | ||
575 | } | ||
576 | spin_unlock_irq(&instance->sndqueue.lock); | ||
577 | |||
578 | tasklet_disable(&instance->tx_channel.tasklet); | ||
579 | if ((skb = instance->current_skb) && (UDSL_SKB(skb)->atm.vcc == vcc)) { | ||
580 | atm_dbg(instance, "%s: popping current skb (0x%p)\n", __func__, skb); | ||
581 | instance->current_skb = NULL; | ||
582 | usbatm_pop(vcc, skb); | ||
583 | } | ||
584 | tasklet_enable(&instance->tx_channel.tasklet); | ||
585 | atm_dbg(instance, "%s done\n", __func__); | ||
586 | } | ||
587 | |||
588 | static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) | ||
589 | { | ||
590 | struct usbatm_data *instance = vcc->dev->dev_data; | ||
591 | struct usbatm_control *ctrl = UDSL_SKB(skb); | ||
592 | int err; | ||
593 | |||
594 | vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len); | ||
595 | |||
596 | if (!instance) { | ||
597 | dbg("%s: NULL data!", __func__); | ||
598 | err = -ENODEV; | ||
599 | goto fail; | ||
600 | } | ||
601 | |||
602 | if (vcc->qos.aal != ATM_AAL5) { | ||
603 | atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); | ||
604 | err = -EINVAL; | ||
605 | goto fail; | ||
606 | } | ||
607 | |||
608 | if (skb->len > ATM_MAX_AAL5_PDU) { | ||
609 | atm_dbg(instance, "%s: packet too long (%d vs %d)!\n", | ||
610 | __func__, skb->len, ATM_MAX_AAL5_PDU); | ||
611 | err = -EINVAL; | ||
612 | goto fail; | ||
613 | } | ||
614 | |||
615 | PACKETDEBUG(skb->data, skb->len); | ||
616 | |||
617 | /* initialize the control block */ | ||
618 | ctrl->atm.vcc = vcc; | ||
619 | ctrl->len = skb->len; | ||
620 | ctrl->crc = crc32_be(~0, skb->data, skb->len); | ||
621 | |||
622 | skb_queue_tail(&instance->sndqueue, skb); | ||
623 | tasklet_schedule(&instance->tx_channel.tasklet); | ||
624 | |||
625 | return 0; | ||
626 | |||
627 | fail: | ||
628 | usbatm_pop(vcc, skb); | ||
629 | return err; | ||
630 | } | ||
631 | |||
632 | |||
633 | /******************** | ||
634 | ** bean counting ** | ||
635 | ********************/ | ||
636 | |||
637 | static void usbatm_destroy_instance(struct kref *kref) | ||
638 | { | ||
639 | struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount); | ||
640 | |||
641 | dbg("%s", __func__); | ||
642 | |||
643 | tasklet_kill(&instance->rx_channel.tasklet); | ||
644 | tasklet_kill(&instance->tx_channel.tasklet); | ||
645 | usb_put_dev(instance->usb_dev); | ||
646 | kfree(instance); | ||
647 | } | ||
648 | |||
649 | void usbatm_get_instance(struct usbatm_data *instance) | ||
650 | { | ||
651 | dbg("%s", __func__); | ||
652 | |||
653 | kref_get(&instance->refcount); | ||
654 | } | ||
655 | |||
656 | void usbatm_put_instance(struct usbatm_data *instance) | ||
657 | { | ||
658 | dbg("%s", __func__); | ||
659 | |||
660 | kref_put(&instance->refcount, usbatm_destroy_instance); | ||
661 | } | ||
662 | |||
663 | |||
664 | /********** | ||
665 | ** ATM ** | ||
666 | **********/ | ||
667 | |||
668 | static void usbatm_atm_dev_close(struct atm_dev *dev) | ||
669 | { | ||
670 | struct usbatm_data *instance = dev->dev_data; | ||
671 | |||
672 | dbg("%s", __func__); | ||
673 | |||
674 | if (!instance) | ||
675 | return; | ||
676 | |||
677 | dev->dev_data = NULL; | ||
678 | usbatm_put_instance(instance); /* taken in usbatm_atm_init */ | ||
679 | } | ||
680 | |||
681 | static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page) | ||
682 | { | ||
683 | struct usbatm_data *instance = atm_dev->dev_data; | ||
684 | int left = *pos; | ||
685 | |||
686 | if (!instance) { | ||
687 | dbg("%s: NULL instance!", __func__); | ||
688 | return -ENODEV; | ||
689 | } | ||
690 | |||
691 | if (!left--) | ||
692 | return sprintf(page, "%s\n", instance->description); | ||
693 | |||
694 | if (!left--) | ||
695 | return sprintf(page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
696 | atm_dev->esi[0], atm_dev->esi[1], | ||
697 | atm_dev->esi[2], atm_dev->esi[3], | ||
698 | atm_dev->esi[4], atm_dev->esi[5]); | ||
699 | |||
700 | if (!left--) | ||
701 | return sprintf(page, | ||
702 | "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n", | ||
703 | atomic_read(&atm_dev->stats.aal5.tx), | ||
704 | atomic_read(&atm_dev->stats.aal5.tx_err), | ||
705 | atomic_read(&atm_dev->stats.aal5.rx), | ||
706 | atomic_read(&atm_dev->stats.aal5.rx_err), | ||
707 | atomic_read(&atm_dev->stats.aal5.rx_drop)); | ||
708 | |||
709 | if (!left--) | ||
710 | switch (atm_dev->signal) { | ||
711 | case ATM_PHY_SIG_FOUND: | ||
712 | return sprintf(page, "Line up\n"); | ||
713 | case ATM_PHY_SIG_LOST: | ||
714 | return sprintf(page, "Line down\n"); | ||
715 | default: | ||
716 | return sprintf(page, "Line state unknown\n"); | ||
717 | } | ||
718 | |||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | static int usbatm_atm_open(struct atm_vcc *vcc) | ||
723 | { | ||
724 | struct usbatm_data *instance = vcc->dev->dev_data; | ||
725 | struct usbatm_vcc_data *new = NULL; | ||
726 | int ret; | ||
727 | int vci = vcc->vci; | ||
728 | short vpi = vcc->vpi; | ||
729 | |||
730 | if (!instance) { | ||
731 | dbg("%s: NULL data!", __func__); | ||
732 | return -ENODEV; | ||
733 | } | ||
734 | |||
735 | atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci); | ||
736 | |||
737 | /* only support AAL5 */ | ||
738 | if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0) | ||
739 | || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) { | ||
740 | atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); | ||
741 | return -EINVAL; | ||
742 | } | ||
743 | |||
744 | down(&instance->serialize); /* vs self, usbatm_atm_close */ | ||
745 | |||
746 | if (usbatm_find_vcc(instance, vpi, vci)) { | ||
747 | atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci); | ||
748 | ret = -EADDRINUSE; | ||
749 | goto fail; | ||
750 | } | ||
751 | |||
752 | if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) { | ||
753 | atm_dbg(instance, "%s: no memory for vcc_data!\n", __func__); | ||
754 | ret = -ENOMEM; | ||
755 | goto fail; | ||
756 | } | ||
757 | |||
758 | memset(new, 0, sizeof(struct usbatm_vcc_data)); | ||
759 | new->vcc = vcc; | ||
760 | new->vpi = vpi; | ||
761 | new->vci = vci; | ||
762 | |||
763 | new->sarb = alloc_skb(usbatm_pdu_length(vcc->qos.rxtp.max_sdu), GFP_KERNEL); | ||
764 | if (!new->sarb) { | ||
765 | atm_dbg(instance, "%s: no memory for SAR buffer!\n", __func__); | ||
766 | ret = -ENOMEM; | ||
767 | goto fail; | ||
768 | } | ||
769 | |||
770 | vcc->dev_data = new; | ||
771 | |||
772 | tasklet_disable(&instance->rx_channel.tasklet); | ||
773 | list_add(&new->list, &instance->vcc_list); | ||
774 | tasklet_enable(&instance->rx_channel.tasklet); | ||
775 | |||
776 | set_bit(ATM_VF_ADDR, &vcc->flags); | ||
777 | set_bit(ATM_VF_PARTIAL, &vcc->flags); | ||
778 | set_bit(ATM_VF_READY, &vcc->flags); | ||
779 | |||
780 | up(&instance->serialize); | ||
781 | |||
782 | atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new); | ||
783 | |||
784 | return 0; | ||
785 | |||
786 | fail: | ||
787 | kfree(new); | ||
788 | up(&instance->serialize); | ||
789 | return ret; | ||
790 | } | ||
791 | |||
792 | static void usbatm_atm_close(struct atm_vcc *vcc) | ||
793 | { | ||
794 | struct usbatm_data *instance = vcc->dev->dev_data; | ||
795 | struct usbatm_vcc_data *vcc_data = vcc->dev_data; | ||
796 | |||
797 | if (!instance || !vcc_data) { | ||
798 | dbg("%s: NULL data!", __func__); | ||
799 | return; | ||
800 | } | ||
801 | |||
802 | atm_dbg(instance, "%s entered\n", __func__); | ||
803 | |||
804 | atm_dbg(instance, "%s: deallocating vcc 0x%p with vpi %d vci %d\n", | ||
805 | __func__, vcc_data, vcc_data->vpi, vcc_data->vci); | ||
806 | |||
807 | usbatm_cancel_send(instance, vcc); | ||
808 | |||
809 | down(&instance->serialize); /* vs self, usbatm_atm_open */ | ||
810 | |||
811 | tasklet_disable(&instance->rx_channel.tasklet); | ||
812 | list_del(&vcc_data->list); | ||
813 | tasklet_enable(&instance->rx_channel.tasklet); | ||
814 | |||
815 | kfree_skb(vcc_data->sarb); | ||
816 | vcc_data->sarb = NULL; | ||
817 | |||
818 | kfree(vcc_data); | ||
819 | vcc->dev_data = NULL; | ||
820 | |||
821 | vcc->vpi = ATM_VPI_UNSPEC; | ||
822 | vcc->vci = ATM_VCI_UNSPEC; | ||
823 | clear_bit(ATM_VF_READY, &vcc->flags); | ||
824 | clear_bit(ATM_VF_PARTIAL, &vcc->flags); | ||
825 | clear_bit(ATM_VF_ADDR, &vcc->flags); | ||
826 | |||
827 | up(&instance->serialize); | ||
828 | |||
829 | atm_dbg(instance, "%s successful\n", __func__); | ||
830 | } | ||
831 | |||
832 | static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, | ||
833 | void __user * arg) | ||
834 | { | ||
835 | switch (cmd) { | ||
836 | case ATM_QUERYLOOP: | ||
837 | return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0; | ||
838 | default: | ||
839 | return -ENOIOCTLCMD; | ||
840 | } | ||
841 | } | ||
842 | |||
843 | static int usbatm_atm_init(struct usbatm_data *instance) | ||
844 | { | ||
845 | struct atm_dev *atm_dev; | ||
846 | int ret, i; | ||
847 | |||
848 | /* ATM init */ | ||
849 | atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL); | ||
850 | if (!atm_dev) { | ||
851 | usb_dbg(instance, "%s: failed to register ATM device!\n", __func__); | ||
852 | return -1; | ||
853 | } | ||
854 | |||
855 | instance->atm_dev = atm_dev; | ||
856 | |||
857 | atm_dev->ci_range.vpi_bits = ATM_CI_MAX; | ||
858 | atm_dev->ci_range.vci_bits = ATM_CI_MAX; | ||
859 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | ||
860 | |||
861 | /* temp init ATM device, set to 128kbit */ | ||
862 | atm_dev->link_rate = 128 * 1000 / 424; | ||
863 | |||
864 | if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) { | ||
865 | atm_dbg(instance, "%s: atm_start failed: %d!\n", __func__, ret); | ||
866 | goto fail; | ||
867 | } | ||
868 | |||
869 | /* ready for ATM callbacks */ | ||
870 | usbatm_get_instance(instance); /* dropped in usbatm_atm_dev_close */ | ||
871 | mb(); | ||
872 | atm_dev->dev_data = instance; | ||
873 | |||
874 | /* submit all rx URBs */ | ||
875 | for (i = 0; i < num_rcv_urbs; i++) | ||
876 | usbatm_submit_urb(instance->urbs[i]); | ||
877 | |||
878 | return 0; | ||
879 | |||
880 | fail: | ||
881 | instance->atm_dev = NULL; | ||
882 | shutdown_atm_dev(atm_dev); /* usbatm_atm_dev_close will eventually be called */ | ||
883 | return ret; | ||
884 | } | ||
885 | |||
886 | |||
887 | /********** | ||
888 | ** USB ** | ||
889 | **********/ | ||
890 | |||
891 | static int usbatm_do_heavy_init(void *arg) | ||
892 | { | ||
893 | struct usbatm_data *instance = arg; | ||
894 | int ret; | ||
895 | |||
896 | daemonize(instance->driver->driver_name); | ||
897 | allow_signal(SIGTERM); | ||
898 | |||
899 | complete(&instance->thread_started); | ||
900 | |||
901 | ret = instance->driver->heavy_init(instance, instance->usb_intf); | ||
902 | |||
903 | if (!ret) | ||
904 | ret = usbatm_atm_init(instance); | ||
905 | |||
906 | down(&instance->serialize); | ||
907 | instance->thread_pid = -1; | ||
908 | up(&instance->serialize); | ||
909 | |||
910 | complete_and_exit(&instance->thread_exited, ret); | ||
911 | } | ||
912 | |||
913 | static int usbatm_heavy_init(struct usbatm_data *instance) | ||
914 | { | ||
915 | int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL); | ||
916 | |||
917 | if (ret < 0) { | ||
918 | usb_dbg(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret); | ||
919 | return ret; | ||
920 | } | ||
921 | |||
922 | down(&instance->serialize); | ||
923 | instance->thread_pid = ret; | ||
924 | up(&instance->serialize); | ||
925 | |||
926 | wait_for_completion(&instance->thread_started); | ||
927 | |||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | static void usbatm_tasklet_schedule(unsigned long data) | ||
932 | { | ||
933 | tasklet_schedule((struct tasklet_struct *) data); | ||
934 | } | ||
935 | |||
936 | static inline void usbatm_init_channel(struct usbatm_channel *channel) | ||
937 | { | ||
938 | spin_lock_init(&channel->lock); | ||
939 | INIT_LIST_HEAD(&channel->list); | ||
940 | channel->delay.function = usbatm_tasklet_schedule; | ||
941 | channel->delay.data = (unsigned long) &channel->tasklet; | ||
942 | init_timer(&channel->delay); | ||
943 | } | ||
944 | |||
945 | int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | ||
946 | struct usbatm_driver *driver) | ||
947 | { | ||
948 | struct device *dev = &intf->dev; | ||
949 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
950 | struct usbatm_data *instance; | ||
951 | char *buf; | ||
952 | int error = -ENOMEM; | ||
953 | int i, length; | ||
954 | int need_heavy; | ||
955 | |||
956 | dev_dbg(dev, "%s: trying driver %s with vendor=0x%x, product=0x%x, ifnum %d\n", | ||
957 | __func__, driver->driver_name, | ||
958 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
959 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
960 | intf->altsetting->desc.bInterfaceNumber); | ||
961 | |||
962 | /* instance init */ | ||
963 | instance = kcalloc(1, sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL); | ||
964 | if (!instance) { | ||
965 | dev_dbg(dev, "%s: no memory for instance data!\n", __func__); | ||
966 | return -ENOMEM; | ||
967 | } | ||
968 | |||
969 | /* public fields */ | ||
970 | |||
971 | instance->driver = driver; | ||
972 | snprintf(instance->driver_name, sizeof(instance->driver_name), driver->driver_name); | ||
973 | |||
974 | instance->usb_dev = usb_dev; | ||
975 | instance->usb_intf = intf; | ||
976 | |||
977 | buf = instance->description; | ||
978 | length = sizeof(instance->description); | ||
979 | |||
980 | if ((i = usb_string(usb_dev, usb_dev->descriptor.iProduct, buf, length)) < 0) | ||
981 | goto bind; | ||
982 | |||
983 | buf += i; | ||
984 | length -= i; | ||
985 | |||
986 | i = scnprintf(buf, length, " ("); | ||
987 | buf += i; | ||
988 | length -= i; | ||
989 | |||
990 | if (length <= 0 || (i = usb_make_path(usb_dev, buf, length)) < 0) | ||
991 | goto bind; | ||
992 | |||
993 | buf += i; | ||
994 | length -= i; | ||
995 | |||
996 | snprintf(buf, length, ")"); | ||
997 | |||
998 | bind: | ||
999 | need_heavy = 1; | ||
1000 | if (driver->bind && (error = driver->bind(instance, intf, id, &need_heavy)) < 0) { | ||
1001 | dev_dbg(dev, "%s: bind failed: %d!\n", __func__, error); | ||
1002 | goto fail_free; | ||
1003 | } | ||
1004 | |||
1005 | /* private fields */ | ||
1006 | |||
1007 | kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */ | ||
1008 | init_MUTEX(&instance->serialize); | ||
1009 | |||
1010 | instance->thread_pid = -1; | ||
1011 | init_completion(&instance->thread_started); | ||
1012 | init_completion(&instance->thread_exited); | ||
1013 | |||
1014 | INIT_LIST_HEAD(&instance->vcc_list); | ||
1015 | |||
1016 | usbatm_init_channel(&instance->rx_channel); | ||
1017 | usbatm_init_channel(&instance->tx_channel); | ||
1018 | tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance); | ||
1019 | tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance); | ||
1020 | instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->in); | ||
1021 | instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out); | ||
1022 | instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding; | ||
1023 | instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding; | ||
1024 | instance->rx_channel.buf_size = rcv_buf_size * instance->rx_channel.stride; | ||
1025 | instance->tx_channel.buf_size = snd_buf_size * instance->tx_channel.stride; | ||
1026 | instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance; | ||
1027 | |||
1028 | skb_queue_head_init(&instance->sndqueue); | ||
1029 | |||
1030 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { | ||
1031 | struct urb *urb; | ||
1032 | u8 *buffer; | ||
1033 | unsigned int iso_packets = 0, iso_size = 0; | ||
1034 | struct usbatm_channel *channel = i < num_rcv_urbs ? | ||
1035 | &instance->rx_channel : &instance->tx_channel; | ||
1036 | |||
1037 | if (usb_pipeisoc(channel->endpoint)) { | ||
1038 | /* don't expect iso out endpoints */ | ||
1039 | iso_size = usb_maxpacket(instance->usb_dev, channel->endpoint, 0); | ||
1040 | iso_size -= iso_size % channel->stride; /* alignment */ | ||
1041 | BUG_ON(!iso_size); | ||
1042 | iso_packets = (channel->buf_size - 1) / iso_size + 1; | ||
1043 | } | ||
1044 | |||
1045 | urb = usb_alloc_urb(iso_packets, GFP_KERNEL); | ||
1046 | if (!urb) { | ||
1047 | dev_dbg(dev, "%s: no memory for urb %d!\n", __func__, i); | ||
1048 | goto fail_unbind; | ||
1049 | } | ||
1050 | |||
1051 | instance->urbs[i] = urb; | ||
1052 | |||
1053 | buffer = kmalloc(channel->buf_size, GFP_KERNEL); | ||
1054 | if (!buffer) { | ||
1055 | dev_dbg(dev, "%s: no memory for buffer %d!\n", __func__, i); | ||
1056 | goto fail_unbind; | ||
1057 | } | ||
1058 | memset(buffer, 0, channel->buf_size); | ||
1059 | |||
1060 | usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint, | ||
1061 | buffer, channel->buf_size, usbatm_complete, channel); | ||
1062 | if (iso_packets) { | ||
1063 | int j; | ||
1064 | urb->interval = 1; | ||
1065 | urb->transfer_flags = URB_ISO_ASAP; | ||
1066 | urb->number_of_packets = iso_packets; | ||
1067 | for (j = 0; j < iso_packets; j++) { | ||
1068 | urb->iso_frame_desc[j].offset = iso_size * j; | ||
1069 | urb->iso_frame_desc[j].length = min_t(int, iso_size, | ||
1070 | channel->buf_size - urb->iso_frame_desc[j].offset); | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | /* put all tx URBs on the list of spares */ | ||
1075 | if (i >= num_rcv_urbs) | ||
1076 | list_add_tail(&urb->urb_list, &channel->list); | ||
1077 | |||
1078 | vdbg("%s: alloced buffer 0x%p buf size %u urb 0x%p", | ||
1079 | __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb); | ||
1080 | } | ||
1081 | |||
1082 | if (need_heavy && driver->heavy_init) { | ||
1083 | error = usbatm_heavy_init(instance); | ||
1084 | } else { | ||
1085 | complete(&instance->thread_exited); /* pretend that heavy_init was run */ | ||
1086 | error = usbatm_atm_init(instance); | ||
1087 | } | ||
1088 | |||
1089 | if (error < 0) | ||
1090 | goto fail_unbind; | ||
1091 | |||
1092 | usb_get_dev(usb_dev); | ||
1093 | usb_set_intfdata(intf, instance); | ||
1094 | |||
1095 | return 0; | ||
1096 | |||
1097 | fail_unbind: | ||
1098 | if (instance->driver->unbind) | ||
1099 | instance->driver->unbind(instance, intf); | ||
1100 | fail_free: | ||
1101 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { | ||
1102 | if (instance->urbs[i]) | ||
1103 | kfree(instance->urbs[i]->transfer_buffer); | ||
1104 | usb_free_urb(instance->urbs[i]); | ||
1105 | } | ||
1106 | |||
1107 | kfree (instance); | ||
1108 | |||
1109 | return error; | ||
1110 | } | ||
1111 | EXPORT_SYMBOL_GPL(usbatm_usb_probe); | ||
1112 | |||
1113 | void usbatm_usb_disconnect(struct usb_interface *intf) | ||
1114 | { | ||
1115 | struct device *dev = &intf->dev; | ||
1116 | struct usbatm_data *instance = usb_get_intfdata(intf); | ||
1117 | int i; | ||
1118 | |||
1119 | dev_dbg(dev, "%s entered\n", __func__); | ||
1120 | |||
1121 | if (!instance) { | ||
1122 | dev_dbg(dev, "%s: NULL instance!\n", __func__); | ||
1123 | return; | ||
1124 | } | ||
1125 | |||
1126 | usb_set_intfdata(intf, NULL); | ||
1127 | |||
1128 | down(&instance->serialize); | ||
1129 | if (instance->thread_pid >= 0) | ||
1130 | kill_proc(instance->thread_pid, SIGTERM, 1); | ||
1131 | up(&instance->serialize); | ||
1132 | |||
1133 | wait_for_completion(&instance->thread_exited); | ||
1134 | |||
1135 | tasklet_disable(&instance->rx_channel.tasklet); | ||
1136 | tasklet_disable(&instance->tx_channel.tasklet); | ||
1137 | |||
1138 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) | ||
1139 | usb_kill_urb(instance->urbs[i]); | ||
1140 | |||
1141 | del_timer_sync(&instance->rx_channel.delay); | ||
1142 | del_timer_sync(&instance->tx_channel.delay); | ||
1143 | |||
1144 | if (instance->atm_dev && instance->driver->atm_stop) | ||
1145 | instance->driver->atm_stop(instance, instance->atm_dev); | ||
1146 | |||
1147 | if (instance->driver->unbind) | ||
1148 | instance->driver->unbind(instance, intf); | ||
1149 | |||
1150 | instance->driver_data = NULL; | ||
1151 | |||
1152 | /* turn usbatm_[rt]x_process into noop */ | ||
1153 | /* no need to take the spinlock */ | ||
1154 | INIT_LIST_HEAD(&instance->rx_channel.list); | ||
1155 | INIT_LIST_HEAD(&instance->tx_channel.list); | ||
1156 | |||
1157 | tasklet_enable(&instance->rx_channel.tasklet); | ||
1158 | tasklet_enable(&instance->tx_channel.tasklet); | ||
1159 | |||
1160 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { | ||
1161 | kfree(instance->urbs[i]->transfer_buffer); | ||
1162 | usb_free_urb(instance->urbs[i]); | ||
1163 | } | ||
1164 | |||
1165 | /* ATM finalize */ | ||
1166 | if (instance->atm_dev) | ||
1167 | shutdown_atm_dev(instance->atm_dev); | ||
1168 | |||
1169 | usbatm_put_instance(instance); /* taken in usbatm_usb_probe */ | ||
1170 | } | ||
1171 | EXPORT_SYMBOL_GPL(usbatm_usb_disconnect); | ||
1172 | |||
1173 | |||
1174 | /*********** | ||
1175 | ** init ** | ||
1176 | ***********/ | ||
1177 | |||
1178 | static int __init usbatm_usb_init(void) | ||
1179 | { | ||
1180 | dbg("%s: driver version %s", __func__, DRIVER_VERSION); | ||
1181 | |||
1182 | if (sizeof(struct usbatm_control) > sizeof(((struct sk_buff *) 0)->cb)) { | ||
1183 | printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name); | ||
1184 | return -EIO; | ||
1185 | } | ||
1186 | |||
1187 | if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) | ||
1188 | || (num_snd_urbs > UDSL_MAX_SND_URBS) | ||
1189 | || (rcv_buf_size < 1) | ||
1190 | || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE) | ||
1191 | || (snd_buf_size < 1) | ||
1192 | || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE)) | ||
1193 | return -EINVAL; | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
1197 | module_init(usbatm_usb_init); | ||
1198 | |||
1199 | static void __exit usbatm_usb_exit(void) | ||
1200 | { | ||
1201 | dbg("%s", __func__); | ||
1202 | } | ||
1203 | module_exit(usbatm_usb_exit); | ||
1204 | |||
1205 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1206 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1207 | MODULE_LICENSE("GPL"); | ||
1208 | MODULE_VERSION(DRIVER_VERSION); | ||
1209 | |||
1210 | /************ | ||
1211 | ** debug ** | ||
1212 | ************/ | ||
1213 | |||
1214 | #ifdef VERBOSE_DEBUG | ||
1215 | static int usbatm_print_packet(const unsigned char *data, int len) | ||
1216 | { | ||
1217 | unsigned char buffer[256]; | ||
1218 | int i = 0, j = 0; | ||
1219 | |||
1220 | for (i = 0; i < len;) { | ||
1221 | buffer[0] = '\0'; | ||
1222 | sprintf(buffer, "%.3d :", i); | ||
1223 | for (j = 0; (j < 16) && (i < len); j++, i++) { | ||
1224 | sprintf(buffer, "%s %2.2x", buffer, data[i]); | ||
1225 | } | ||
1226 | dbg("%s", buffer); | ||
1227 | } | ||
1228 | return i; | ||
1229 | } | ||
1230 | #endif | ||
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h new file mode 100644 index 000000000000..936646457935 --- /dev/null +++ b/drivers/usb/atm/usbatm.h | |||
@@ -0,0 +1,184 @@ | |||
1 | /****************************************************************************** | ||
2 | * usbatm.h - Generic USB xDSL driver core | ||
3 | * | ||
4 | * Copyright (C) 2001, Alcatel | ||
5 | * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas | ||
6 | * Copyright (C) 2004, David Woodhouse | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | #ifndef _USBATM_H_ | ||
25 | #define _USBATM_H_ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | |||
29 | /* | ||
30 | #define DEBUG | ||
31 | #define VERBOSE_DEBUG | ||
32 | */ | ||
33 | |||
34 | #if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) | ||
35 | # define DEBUG | ||
36 | #endif | ||
37 | |||
38 | #include <asm/semaphore.h> | ||
39 | #include <linux/atm.h> | ||
40 | #include <linux/atmdev.h> | ||
41 | #include <linux/completion.h> | ||
42 | #include <linux/device.h> | ||
43 | #include <linux/kref.h> | ||
44 | #include <linux/list.h> | ||
45 | #include <linux/stringify.h> | ||
46 | #include <linux/usb.h> | ||
47 | |||
48 | #ifdef DEBUG | ||
49 | #define UDSL_ASSERT(x) BUG_ON(!(x)) | ||
50 | #else | ||
51 | #define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '%s' at line %d", __stringify(x), __LINE__); } while(0) | ||
52 | #endif | ||
53 | |||
54 | #define usb_err(instance, format, arg...) \ | ||
55 | dev_err(&(instance)->usb_intf->dev , format , ## arg) | ||
56 | #define usb_info(instance, format, arg...) \ | ||
57 | dev_info(&(instance)->usb_intf->dev , format , ## arg) | ||
58 | #define usb_warn(instance, format, arg...) \ | ||
59 | dev_warn(&(instance)->usb_intf->dev , format , ## arg) | ||
60 | #define usb_dbg(instance, format, arg...) \ | ||
61 | dev_dbg(&(instance)->usb_intf->dev , format , ## arg) | ||
62 | |||
63 | /* FIXME: move to dev_* once ATM is driver model aware */ | ||
64 | #define atm_printk(level, instance, format, arg...) \ | ||
65 | printk(level "ATM dev %d: " format , \ | ||
66 | (instance)->atm_dev->number , ## arg) | ||
67 | |||
68 | #define atm_err(instance, format, arg...) \ | ||
69 | atm_printk(KERN_ERR, instance , format , ## arg) | ||
70 | #define atm_info(instance, format, arg...) \ | ||
71 | atm_printk(KERN_INFO, instance , format , ## arg) | ||
72 | #define atm_warn(instance, format, arg...) \ | ||
73 | atm_printk(KERN_WARNING, instance , format , ## arg) | ||
74 | #ifdef DEBUG | ||
75 | #define atm_dbg(instance, format, arg...) \ | ||
76 | atm_printk(KERN_DEBUG, instance , format , ## arg) | ||
77 | #else | ||
78 | #define atm_dbg(instance, format, arg...) \ | ||
79 | do {} while (0) | ||
80 | #endif | ||
81 | |||
82 | |||
83 | /* mini driver */ | ||
84 | |||
85 | struct usbatm_data; | ||
86 | |||
87 | /* | ||
88 | * Assuming all methods exist and succeed, they are called in this order: | ||
89 | * | ||
90 | * bind, heavy_init, atm_start, ..., atm_stop, unbind | ||
91 | */ | ||
92 | |||
93 | struct usbatm_driver { | ||
94 | struct module *owner; | ||
95 | |||
96 | const char *driver_name; | ||
97 | |||
98 | /* | ||
99 | * init device ... can sleep, or cause probe() failure. Drivers with a heavy_init | ||
100 | * method can avoid having it called by setting need_heavy_init to zero. | ||
101 | */ | ||
102 | int (*bind) (struct usbatm_data *, struct usb_interface *, | ||
103 | const struct usb_device_id *id, int *need_heavy_init); | ||
104 | |||
105 | /* additional device initialization that is too slow to be done in probe() */ | ||
106 | int (*heavy_init) (struct usbatm_data *, struct usb_interface *); | ||
107 | |||
108 | /* cleanup device ... can sleep, but can't fail */ | ||
109 | void (*unbind) (struct usbatm_data *, struct usb_interface *); | ||
110 | |||
111 | /* init ATM device ... can sleep, or cause ATM initialization failure */ | ||
112 | int (*atm_start) (struct usbatm_data *, struct atm_dev *); | ||
113 | |||
114 | /* cleanup ATM device ... can sleep, but can't fail */ | ||
115 | void (*atm_stop) (struct usbatm_data *, struct atm_dev *); | ||
116 | |||
117 | int in; /* rx endpoint */ | ||
118 | int out; /* tx endpoint */ | ||
119 | |||
120 | unsigned rx_padding; | ||
121 | unsigned tx_padding; | ||
122 | }; | ||
123 | |||
124 | extern int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | ||
125 | struct usbatm_driver *driver); | ||
126 | extern void usbatm_usb_disconnect(struct usb_interface *intf); | ||
127 | |||
128 | |||
129 | struct usbatm_channel { | ||
130 | int endpoint; /* usb pipe */ | ||
131 | unsigned int stride; /* ATM cell size + padding */ | ||
132 | unsigned int buf_size; /* urb buffer size */ | ||
133 | spinlock_t lock; | ||
134 | struct list_head list; | ||
135 | struct tasklet_struct tasklet; | ||
136 | struct timer_list delay; | ||
137 | struct usbatm_data *usbatm; | ||
138 | }; | ||
139 | |||
140 | /* main driver data */ | ||
141 | |||
142 | struct usbatm_data { | ||
143 | /****************** | ||
144 | * public fields * | ||
145 | ******************/ | ||
146 | |||
147 | /* mini driver */ | ||
148 | struct usbatm_driver *driver; | ||
149 | void *driver_data; | ||
150 | char driver_name[16]; | ||
151 | |||
152 | /* USB device */ | ||
153 | struct usb_device *usb_dev; | ||
154 | struct usb_interface *usb_intf; | ||
155 | char description[64]; | ||
156 | |||
157 | /* ATM device */ | ||
158 | struct atm_dev *atm_dev; | ||
159 | |||
160 | /******************************** | ||
161 | * private fields - do not use * | ||
162 | ********************************/ | ||
163 | |||
164 | struct kref refcount; | ||
165 | struct semaphore serialize; | ||
166 | |||
167 | /* heavy init */ | ||
168 | int thread_pid; | ||
169 | struct completion thread_started; | ||
170 | struct completion thread_exited; | ||
171 | |||
172 | /* ATM device */ | ||
173 | struct list_head vcc_list; | ||
174 | |||
175 | struct usbatm_channel rx_channel; | ||
176 | struct usbatm_channel tx_channel; | ||
177 | |||
178 | struct sk_buff_head sndqueue; | ||
179 | struct sk_buff *current_skb; /* being emptied */ | ||
180 | |||
181 | struct urb *urbs[0]; | ||
182 | }; | ||
183 | |||
184 | #endif /* _USBATM_H_ */ | ||
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c new file mode 100644 index 000000000000..7fe7fb484d10 --- /dev/null +++ b/drivers/usb/atm/xusbatm.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /****************************************************************************** | ||
2 | * xusbatm.c - dumb usbatm-based driver for modems initialized in userspace | ||
3 | * | ||
4 | * Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
18 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | * | ||
20 | ******************************************************************************/ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/netdevice.h> /* FIXME: required by linux/etherdevice.h */ | ||
24 | #include <linux/etherdevice.h> /* for random_ether_addr() */ | ||
25 | |||
26 | #include "usbatm.h" | ||
27 | |||
28 | |||
29 | #define XUSBATM_DRIVERS_MAX 8 | ||
30 | |||
31 | #define XUSBATM_PARM(name, type, parmtype, desc) \ | ||
32 | static type name[XUSBATM_DRIVERS_MAX]; \ | ||
33 | static int num_##name; \ | ||
34 | module_param_array(name, parmtype, &num_##name, 0444); \ | ||
35 | MODULE_PARM_DESC(name, desc) | ||
36 | |||
37 | XUSBATM_PARM(vendor, unsigned short, ushort, "USB device vendor"); | ||
38 | XUSBATM_PARM(product, unsigned short, ushort, "USB device product"); | ||
39 | |||
40 | XUSBATM_PARM(rx_endpoint, unsigned char, byte, "rx endpoint number"); | ||
41 | XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number"); | ||
42 | XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)"); | ||
43 | XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)"); | ||
44 | |||
45 | static const char xusbatm_driver_name[] = "xusbatm"; | ||
46 | |||
47 | static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX]; | ||
48 | static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1]; | ||
49 | static struct usb_driver xusbatm_usb_driver; | ||
50 | |||
51 | static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep) | ||
52 | { | ||
53 | int i, j; | ||
54 | |||
55 | for (i = 0; i < intf->num_altsetting; i++) { | ||
56 | struct usb_host_interface *alt = intf->altsetting; | ||
57 | for (j = 0; j < alt->desc.bNumEndpoints; j++) | ||
58 | if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep) | ||
59 | return 1; | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static int xusbatm_bind(struct usbatm_data *usbatm_instance, | ||
65 | struct usb_interface *intf, const struct usb_device_id *id, | ||
66 | int *need_heavy_init) | ||
67 | { | ||
68 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
69 | int drv_ix = id - xusbatm_usb_ids; | ||
70 | int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]); | ||
71 | int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]); | ||
72 | u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix]; | ||
73 | int i, ret; | ||
74 | |||
75 | usb_dbg(usbatm_instance, "%s: binding driver %d: vendor %#x product %#x" | ||
76 | " rx: ep %#x padd %d tx: ep %#x padd %d\n", | ||
77 | __func__, drv_ix, vendor[drv_ix], product[drv_ix], | ||
78 | rx_endpoint[drv_ix], rx_padding[drv_ix], | ||
79 | tx_endpoint[drv_ix], tx_padding[drv_ix]); | ||
80 | |||
81 | if (!rx_ep_present && !tx_ep_present) { | ||
82 | usb_dbg(usbatm_instance, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n", | ||
83 | __func__, intf->altsetting->desc.bInterfaceNumber, | ||
84 | rx_endpoint[drv_ix], tx_endpoint[drv_ix]); | ||
85 | return -ENODEV; | ||
86 | } | ||
87 | |||
88 | if (rx_ep_present && tx_ep_present) | ||
89 | return 0; | ||
90 | |||
91 | for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { | ||
92 | struct usb_interface *cur_if = usb_dev->actconfig->interface[i]; | ||
93 | |||
94 | if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) { | ||
95 | ret = usb_driver_claim_interface(&xusbatm_usb_driver, | ||
96 | cur_if, usbatm_instance); | ||
97 | if (!ret) | ||
98 | usb_err(usbatm_instance, "%s: failed to claim interface #%d (%d)\n", | ||
99 | __func__, cur_if->altsetting->desc.bInterfaceNumber, ret); | ||
100 | return ret; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | usb_err(usbatm_instance, "%s: no interface has endpoint %#x\n", | ||
105 | __func__, searched_ep); | ||
106 | return -ENODEV; | ||
107 | } | ||
108 | |||
109 | static void xusbatm_unbind(struct usbatm_data *usbatm_instance, | ||
110 | struct usb_interface *intf) | ||
111 | { | ||
112 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
113 | int i; | ||
114 | usb_dbg(usbatm_instance, "%s entered\n", __func__); | ||
115 | |||
116 | for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { | ||
117 | struct usb_interface *cur_if = usb_dev->actconfig->interface[i]; | ||
118 | usb_set_intfdata(cur_if, NULL); | ||
119 | usb_driver_release_interface(&xusbatm_usb_driver, cur_if); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | static int xusbatm_atm_start(struct usbatm_data *usbatm_instance, | ||
124 | struct atm_dev *atm_dev) | ||
125 | { | ||
126 | atm_dbg(usbatm_instance, "%s entered\n", __func__); | ||
127 | |||
128 | /* use random MAC as we've no way to get it from the device */ | ||
129 | random_ether_addr(atm_dev->esi); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | |||
135 | static int xusbatm_usb_probe(struct usb_interface *intf, | ||
136 | const struct usb_device_id *id) | ||
137 | { | ||
138 | return usbatm_usb_probe(intf, id, | ||
139 | xusbatm_drivers + (id - xusbatm_usb_ids)); | ||
140 | } | ||
141 | |||
142 | static struct usb_driver xusbatm_usb_driver = { | ||
143 | .owner = THIS_MODULE, | ||
144 | .name = xusbatm_driver_name, | ||
145 | .probe = xusbatm_usb_probe, | ||
146 | .disconnect = usbatm_usb_disconnect, | ||
147 | .id_table = xusbatm_usb_ids | ||
148 | }; | ||
149 | |||
150 | static int __init xusbatm_init(void) | ||
151 | { | ||
152 | int i; | ||
153 | |||
154 | dbg("xusbatm_init"); | ||
155 | |||
156 | if (!num_vendor || | ||
157 | num_vendor != num_product || | ||
158 | num_vendor != num_rx_endpoint || | ||
159 | num_vendor != num_tx_endpoint) { | ||
160 | warn("malformed module parameters"); | ||
161 | return -EINVAL; | ||
162 | } | ||
163 | |||
164 | for (i = 0; i < num_vendor; i++) { | ||
165 | xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE; | ||
166 | xusbatm_usb_ids[i].idVendor = vendor[i]; | ||
167 | xusbatm_usb_ids[i].idProduct = product[i]; | ||
168 | |||
169 | |||
170 | xusbatm_drivers[i].owner = THIS_MODULE; | ||
171 | xusbatm_drivers[i].driver_name = xusbatm_driver_name; | ||
172 | xusbatm_drivers[i].bind = xusbatm_bind; | ||
173 | xusbatm_drivers[i].unbind = xusbatm_unbind; | ||
174 | xusbatm_drivers[i].atm_start = xusbatm_atm_start; | ||
175 | xusbatm_drivers[i].in = rx_endpoint[i]; | ||
176 | xusbatm_drivers[i].out = tx_endpoint[i]; | ||
177 | xusbatm_drivers[i].rx_padding = rx_padding[i]; | ||
178 | xusbatm_drivers[i].tx_padding = tx_padding[i]; | ||
179 | } | ||
180 | |||
181 | return usb_register(&xusbatm_usb_driver); | ||
182 | } | ||
183 | module_init(xusbatm_init); | ||
184 | |||
185 | static void __exit xusbatm_exit(void) | ||
186 | { | ||
187 | dbg("xusbatm_exit entered"); | ||
188 | |||
189 | usb_deregister(&xusbatm_usb_driver); | ||
190 | } | ||
191 | module_exit(xusbatm_exit); | ||
192 | |||
193 | MODULE_AUTHOR("Roman Kagan, Duncan Sands"); | ||
194 | MODULE_DESCRIPTION("Driver for USB ADSL modems initialized in userspace"); | ||
195 | MODULE_LICENSE("GPL"); | ||
196 | MODULE_VERSION("0.1"); | ||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6d1f9b6aecff..69e859e0f51d 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -106,6 +106,111 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int | |||
106 | acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) | 106 | acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) |
107 | 107 | ||
108 | /* | 108 | /* |
109 | * Write buffer management. | ||
110 | * All of these assume proper locks taken by the caller. | ||
111 | */ | ||
112 | |||
113 | static int acm_wb_alloc(struct acm *acm) | ||
114 | { | ||
115 | int i, wbn; | ||
116 | struct acm_wb *wb; | ||
117 | |||
118 | wbn = acm->write_current; | ||
119 | i = 0; | ||
120 | for (;;) { | ||
121 | wb = &acm->wb[wbn]; | ||
122 | if (!wb->use) { | ||
123 | wb->use = 1; | ||
124 | return wbn; | ||
125 | } | ||
126 | wbn = (wbn + 1) % ACM_NWB; | ||
127 | if (++i >= ACM_NWB) | ||
128 | return -1; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static void acm_wb_free(struct acm *acm, int wbn) | ||
133 | { | ||
134 | acm->wb[wbn].use = 0; | ||
135 | } | ||
136 | |||
137 | static int acm_wb_is_avail(struct acm *acm) | ||
138 | { | ||
139 | int i, n; | ||
140 | |||
141 | n = 0; | ||
142 | for (i = 0; i < ACM_NWB; i++) { | ||
143 | if (!acm->wb[i].use) | ||
144 | n++; | ||
145 | } | ||
146 | return n; | ||
147 | } | ||
148 | |||
149 | static inline int acm_wb_is_used(struct acm *acm, int wbn) | ||
150 | { | ||
151 | return acm->wb[wbn].use; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Finish write. | ||
156 | */ | ||
157 | static void acm_write_done(struct acm *acm) | ||
158 | { | ||
159 | unsigned long flags; | ||
160 | int wbn; | ||
161 | |||
162 | spin_lock_irqsave(&acm->write_lock, flags); | ||
163 | acm->write_ready = 1; | ||
164 | wbn = acm->write_current; | ||
165 | acm_wb_free(acm, wbn); | ||
166 | acm->write_current = (wbn + 1) % ACM_NWB; | ||
167 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Poke write. | ||
172 | */ | ||
173 | static int acm_write_start(struct acm *acm) | ||
174 | { | ||
175 | unsigned long flags; | ||
176 | int wbn; | ||
177 | struct acm_wb *wb; | ||
178 | int rc; | ||
179 | |||
180 | spin_lock_irqsave(&acm->write_lock, flags); | ||
181 | if (!acm->dev) { | ||
182 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
183 | return -ENODEV; | ||
184 | } | ||
185 | |||
186 | if (!acm->write_ready) { | ||
187 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
188 | return 0; /* A white lie */ | ||
189 | } | ||
190 | |||
191 | wbn = acm->write_current; | ||
192 | if (!acm_wb_is_used(acm, wbn)) { | ||
193 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
194 | return 0; | ||
195 | } | ||
196 | wb = &acm->wb[wbn]; | ||
197 | |||
198 | acm->write_ready = 0; | ||
199 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
200 | |||
201 | acm->writeurb->transfer_buffer = wb->buf; | ||
202 | acm->writeurb->transfer_dma = wb->dmah; | ||
203 | acm->writeurb->transfer_buffer_length = wb->len; | ||
204 | acm->writeurb->dev = acm->dev; | ||
205 | |||
206 | if ((rc = usb_submit_urb(acm->writeurb, GFP_ATOMIC)) < 0) { | ||
207 | dbg("usb_submit_urb(write bulk) failed: %d", rc); | ||
208 | acm_write_done(acm); | ||
209 | } | ||
210 | return rc; | ||
211 | } | ||
212 | |||
213 | /* | ||
109 | * Interrupt handlers for various ACM device responses | 214 | * Interrupt handlers for various ACM device responses |
110 | */ | 215 | */ |
111 | 216 | ||
@@ -237,17 +342,13 @@ static void acm_rx_tasklet(unsigned long _acm) | |||
237 | static void acm_write_bulk(struct urb *urb, struct pt_regs *regs) | 342 | static void acm_write_bulk(struct urb *urb, struct pt_regs *regs) |
238 | { | 343 | { |
239 | struct acm *acm = (struct acm *)urb->context; | 344 | struct acm *acm = (struct acm *)urb->context; |
240 | dbg("Entering acm_write_bulk with status %d\n", urb->status); | ||
241 | |||
242 | if (!ACM_READY(acm)) | ||
243 | goto out; | ||
244 | 345 | ||
245 | if (urb->status) | 346 | dbg("Entering acm_write_bulk with status %d\n", urb->status); |
246 | dbg("nonzero write bulk status received: %d", urb->status); | ||
247 | 347 | ||
248 | schedule_work(&acm->work); | 348 | acm_write_done(acm); |
249 | out: | 349 | acm_write_start(acm); |
250 | acm->ready_for_write = 1; | 350 | if (ACM_READY(acm)) |
351 | schedule_work(&acm->work); | ||
251 | } | 352 | } |
252 | 353 | ||
253 | static void acm_softint(void *private) | 354 | static void acm_softint(void *private) |
@@ -351,32 +452,33 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c | |||
351 | { | 452 | { |
352 | struct acm *acm = tty->driver_data; | 453 | struct acm *acm = tty->driver_data; |
353 | int stat; | 454 | int stat; |
455 | unsigned long flags; | ||
456 | int wbn; | ||
457 | struct acm_wb *wb; | ||
458 | |||
354 | dbg("Entering acm_tty_write to write %d bytes,\n", count); | 459 | dbg("Entering acm_tty_write to write %d bytes,\n", count); |
355 | 460 | ||
356 | if (!ACM_READY(acm)) | 461 | if (!ACM_READY(acm)) |
357 | return -EINVAL; | 462 | return -EINVAL; |
358 | if (!acm->ready_for_write) | ||
359 | return 0; | ||
360 | if (!count) | 463 | if (!count) |
361 | return 0; | 464 | return 0; |
362 | 465 | ||
363 | count = (count > acm->writesize) ? acm->writesize : count; | 466 | spin_lock_irqsave(&acm->write_lock, flags); |
467 | if ((wbn = acm_wb_alloc(acm)) < 0) { | ||
468 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
469 | acm_write_start(acm); | ||
470 | return 0; | ||
471 | } | ||
472 | wb = &acm->wb[wbn]; | ||
364 | 473 | ||
474 | count = (count > acm->writesize) ? acm->writesize : count; | ||
365 | dbg("Get %d bytes...", count); | 475 | dbg("Get %d bytes...", count); |
366 | memcpy(acm->write_buffer, buf, count); | 476 | memcpy(wb->buf, buf, count); |
367 | dbg(" Successfully copied.\n"); | 477 | wb->len = count; |
478 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
368 | 479 | ||
369 | acm->writeurb->transfer_buffer_length = count; | 480 | if ((stat = acm_write_start(acm)) < 0) |
370 | acm->writeurb->dev = acm->dev; | ||
371 | |||
372 | acm->ready_for_write = 0; | ||
373 | stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC); | ||
374 | if (stat < 0) { | ||
375 | dbg("usb_submit_urb(write bulk) failed"); | ||
376 | acm->ready_for_write = 1; | ||
377 | return stat; | 481 | return stat; |
378 | } | ||
379 | |||
380 | return count; | 482 | return count; |
381 | } | 483 | } |
382 | 484 | ||
@@ -385,7 +487,11 @@ static int acm_tty_write_room(struct tty_struct *tty) | |||
385 | struct acm *acm = tty->driver_data; | 487 | struct acm *acm = tty->driver_data; |
386 | if (!ACM_READY(acm)) | 488 | if (!ACM_READY(acm)) |
387 | return -EINVAL; | 489 | return -EINVAL; |
388 | return !acm->ready_for_write ? 0 : acm->writesize; | 490 | /* |
491 | * Do not let the line discipline to know that we have a reserve, | ||
492 | * or it might get too enthusiastic. | ||
493 | */ | ||
494 | return (acm->write_ready && acm_wb_is_avail(acm)) ? acm->writesize : 0; | ||
389 | } | 495 | } |
390 | 496 | ||
391 | static int acm_tty_chars_in_buffer(struct tty_struct *tty) | 497 | static int acm_tty_chars_in_buffer(struct tty_struct *tty) |
@@ -393,7 +499,10 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty) | |||
393 | struct acm *acm = tty->driver_data; | 499 | struct acm *acm = tty->driver_data; |
394 | if (!ACM_READY(acm)) | 500 | if (!ACM_READY(acm)) |
395 | return -EINVAL; | 501 | return -EINVAL; |
396 | return !acm->ready_for_write ? acm->writeurb->transfer_buffer_length : 0; | 502 | /* |
503 | * This is inaccurate (overcounts), but it works. | ||
504 | */ | ||
505 | return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize; | ||
397 | } | 506 | } |
398 | 507 | ||
399 | static void acm_tty_throttle(struct tty_struct *tty) | 508 | static void acm_tty_throttle(struct tty_struct *tty) |
@@ -526,6 +635,39 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_ | |||
526 | * USB probe and disconnect routines. | 635 | * USB probe and disconnect routines. |
527 | */ | 636 | */ |
528 | 637 | ||
638 | /* Little helper: write buffers free */ | ||
639 | static void acm_write_buffers_free(struct acm *acm) | ||
640 | { | ||
641 | int i; | ||
642 | struct acm_wb *wb; | ||
643 | |||
644 | for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { | ||
645 | usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | /* Little helper: write buffers allocate */ | ||
650 | static int acm_write_buffers_alloc(struct acm *acm) | ||
651 | { | ||
652 | int i; | ||
653 | struct acm_wb *wb; | ||
654 | |||
655 | for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { | ||
656 | wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL, | ||
657 | &wb->dmah); | ||
658 | if (!wb->buf) { | ||
659 | while (i != 0) { | ||
660 | --i; | ||
661 | --wb; | ||
662 | usb_buffer_free(acm->dev, acm->writesize, | ||
663 | wb->buf, wb->dmah); | ||
664 | } | ||
665 | return -ENOMEM; | ||
666 | } | ||
667 | } | ||
668 | return 0; | ||
669 | } | ||
670 | |||
529 | static int acm_probe (struct usb_interface *intf, | 671 | static int acm_probe (struct usb_interface *intf, |
530 | const struct usb_device_id *id) | 672 | const struct usb_device_id *id) |
531 | { | 673 | { |
@@ -700,7 +842,8 @@ skip_normal_probe: | |||
700 | acm->bh.data = (unsigned long) acm; | 842 | acm->bh.data = (unsigned long) acm; |
701 | INIT_WORK(&acm->work, acm_softint, acm); | 843 | INIT_WORK(&acm->work, acm_softint, acm); |
702 | spin_lock_init(&acm->throttle_lock); | 844 | spin_lock_init(&acm->throttle_lock); |
703 | acm->ready_for_write = 1; | 845 | spin_lock_init(&acm->write_lock); |
846 | acm->write_ready = 1; | ||
704 | 847 | ||
705 | buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); | 848 | buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); |
706 | if (!buf) { | 849 | if (!buf) { |
@@ -716,12 +859,10 @@ skip_normal_probe: | |||
716 | } | 859 | } |
717 | acm->read_buffer = buf; | 860 | acm->read_buffer = buf; |
718 | 861 | ||
719 | buf = usb_buffer_alloc(usb_dev, acm->writesize, GFP_KERNEL, &acm->write_dma); | 862 | if (acm_write_buffers_alloc(acm) < 0) { |
720 | if (!buf) { | ||
721 | dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n"); | 863 | dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n"); |
722 | goto alloc_fail4; | 864 | goto alloc_fail4; |
723 | } | 865 | } |
724 | acm->write_buffer = buf; | ||
725 | 866 | ||
726 | acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); | 867 | acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); |
727 | if (!acm->ctrlurb) { | 868 | if (!acm->ctrlurb) { |
@@ -750,9 +891,9 @@ skip_normal_probe: | |||
750 | acm->readurb->transfer_dma = acm->read_dma; | 891 | acm->readurb->transfer_dma = acm->read_dma; |
751 | 892 | ||
752 | usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), | 893 | usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), |
753 | acm->write_buffer, acm->writesize, acm_write_bulk, acm); | 894 | NULL, acm->writesize, acm_write_bulk, acm); |
754 | acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP; | 895 | acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP; |
755 | acm->writeurb->transfer_dma = acm->write_dma; | 896 | /* acm->writeurb->transfer_dma = 0; */ |
756 | 897 | ||
757 | dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); | 898 | dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); |
758 | 899 | ||
@@ -775,7 +916,7 @@ alloc_fail7: | |||
775 | alloc_fail6: | 916 | alloc_fail6: |
776 | usb_free_urb(acm->ctrlurb); | 917 | usb_free_urb(acm->ctrlurb); |
777 | alloc_fail5: | 918 | alloc_fail5: |
778 | usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma); | 919 | acm_write_buffers_free(acm); |
779 | alloc_fail4: | 920 | alloc_fail4: |
780 | usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma); | 921 | usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma); |
781 | alloc_fail3: | 922 | alloc_fail3: |
@@ -806,7 +947,7 @@ static void acm_disconnect(struct usb_interface *intf) | |||
806 | 947 | ||
807 | flush_scheduled_work(); /* wait for acm_softint */ | 948 | flush_scheduled_work(); /* wait for acm_softint */ |
808 | 949 | ||
809 | usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma); | 950 | acm_write_buffers_free(acm); |
810 | usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma); | 951 | usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma); |
811 | usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); | 952 | usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); |
812 | 953 | ||
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 9009114e311b..963a5dfd2096 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h | |||
@@ -51,14 +51,34 @@ | |||
51 | * Internal driver structures. | 51 | * Internal driver structures. |
52 | */ | 52 | */ |
53 | 53 | ||
54 | /* | ||
55 | * The only reason to have several buffers is to accomodate assumptions | ||
56 | * in line disciplines. They ask for empty space amount, receive our URB size, | ||
57 | * and proceed to issue several 1-character writes, assuming they will fit. | ||
58 | * The very first write takes a complete URB. Fortunately, this only happens | ||
59 | * when processing onlcr, so we only need 2 buffers. | ||
60 | */ | ||
61 | #define ACM_NWB 2 | ||
62 | struct acm_wb { | ||
63 | unsigned char *buf; | ||
64 | dma_addr_t dmah; | ||
65 | int len; | ||
66 | int use; | ||
67 | }; | ||
68 | |||
54 | struct acm { | 69 | struct acm { |
55 | struct usb_device *dev; /* the corresponding usb device */ | 70 | struct usb_device *dev; /* the corresponding usb device */ |
56 | struct usb_interface *control; /* control interface */ | 71 | struct usb_interface *control; /* control interface */ |
57 | struct usb_interface *data; /* data interface */ | 72 | struct usb_interface *data; /* data interface */ |
58 | struct tty_struct *tty; /* the corresponding tty */ | 73 | struct tty_struct *tty; /* the corresponding tty */ |
59 | struct urb *ctrlurb, *readurb, *writeurb; /* urbs */ | 74 | struct urb *ctrlurb, *readurb, *writeurb; /* urbs */ |
60 | u8 *ctrl_buffer, *read_buffer, *write_buffer; /* buffers of urbs */ | 75 | u8 *ctrl_buffer, *read_buffer; /* buffers of urbs */ |
61 | dma_addr_t ctrl_dma, read_dma, write_dma; /* dma handles of buffers */ | 76 | dma_addr_t ctrl_dma, read_dma; /* dma handles of buffers */ |
77 | struct acm_wb wb[ACM_NWB]; | ||
78 | int write_current; /* current write buffer */ | ||
79 | int write_used; /* number of non-empty write buffers */ | ||
80 | int write_ready; /* write urb is not running */ | ||
81 | spinlock_t write_lock; | ||
62 | struct usb_cdc_line_coding line; /* bits, stop, parity */ | 82 | struct usb_cdc_line_coding line; /* bits, stop, parity */ |
63 | struct work_struct work; /* work queue entry for line discipline waking up */ | 83 | struct work_struct work; /* work queue entry for line discipline waking up */ |
64 | struct tasklet_struct bh; /* rx processing */ | 84 | struct tasklet_struct bh; /* rx processing */ |
@@ -71,7 +91,6 @@ struct acm { | |||
71 | unsigned int minor; /* acm minor number */ | 91 | unsigned int minor; /* acm minor number */ |
72 | unsigned char throttle; /* throttled by tty layer */ | 92 | unsigned char throttle; /* throttled by tty layer */ |
73 | unsigned char clocal; /* termios CLOCAL */ | 93 | unsigned char clocal; /* termios CLOCAL */ |
74 | unsigned char ready_for_write; /* write urb can be used */ | ||
75 | unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */ | 94 | unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */ |
76 | unsigned int ctrl_caps; /* control capabilities from the class specific header */ | 95 | unsigned int ctrl_caps; /* control capabilities from the class specific header */ |
77 | }; | 96 | }; |
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index bba22e97ea0f..7ce43fb8118a 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -379,6 +379,8 @@ static int usblp_open(struct inode *inode, struct file *file) | |||
379 | usblp->writeurb->transfer_buffer_length = 0; | 379 | usblp->writeurb->transfer_buffer_length = 0; |
380 | usblp->wcomplete = 1; /* we begin writeable */ | 380 | usblp->wcomplete = 1; /* we begin writeable */ |
381 | usblp->rcomplete = 0; | 381 | usblp->rcomplete = 0; |
382 | usblp->writeurb->status = 0; | ||
383 | usblp->readurb->status = 0; | ||
382 | 384 | ||
383 | if (usblp->bidir) { | 385 | if (usblp->bidir) { |
384 | usblp->readcount = 0; | 386 | usblp->readcount = 0; |
@@ -751,6 +753,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, | |||
751 | schedule(); | 753 | schedule(); |
752 | } else { | 754 | } else { |
753 | set_current_state(TASK_RUNNING); | 755 | set_current_state(TASK_RUNNING); |
756 | down(&usblp->sem); | ||
754 | break; | 757 | break; |
755 | } | 758 | } |
756 | down (&usblp->sem); | 759 | down (&usblp->sem); |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6bfab4bcaa9e..787c27a63c51 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -784,16 +784,16 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg) | |||
784 | for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) { | 784 | for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) { |
785 | if (usb_interface_claimed(actconfig->interface[i])) { | 785 | if (usb_interface_claimed(actconfig->interface[i])) { |
786 | dev_warn (&ps->dev->dev, | 786 | dev_warn (&ps->dev->dev, |
787 | "usbfs: interface %d claimed " | 787 | "usbfs: interface %d claimed by %s " |
788 | "while '%s' sets config #%d\n", | 788 | "while '%s' sets config #%d\n", |
789 | actconfig->interface[i] | 789 | actconfig->interface[i] |
790 | ->cur_altsetting | 790 | ->cur_altsetting |
791 | ->desc.bInterfaceNumber, | 791 | ->desc.bInterfaceNumber, |
792 | actconfig->interface[i] | ||
793 | ->dev.driver->name, | ||
792 | current->comm, u); | 794 | current->comm, u); |
793 | #if 0 /* FIXME: enable in 2.6.10 or so */ | ||
794 | status = -EBUSY; | 795 | status = -EBUSY; |
795 | break; | 796 | break; |
796 | #endif | ||
797 | } | 797 | } |
798 | } | 798 | } |
799 | } | 799 | } |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0da23732e807..83e732a0d64a 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -519,119 +519,120 @@ error: | |||
519 | /*-------------------------------------------------------------------------*/ | 519 | /*-------------------------------------------------------------------------*/ |
520 | 520 | ||
521 | /* | 521 | /* |
522 | * Root Hub interrupt transfers are synthesized with a timer. | 522 | * Root Hub interrupt transfers are polled using a timer if the |
523 | * Completions are called in_interrupt() but not in_irq(). | 523 | * driver requests it; otherwise the driver is responsible for |
524 | * calling usb_hcd_poll_rh_status() when an event occurs. | ||
524 | * | 525 | * |
525 | * Note: some root hubs (including common UHCI based designs) can't | 526 | * Completions are called in_interrupt(), but they may or may not |
526 | * correctly issue port change IRQs. They're the ones that _need_ a | 527 | * be in_irq(). |
527 | * timer; most other root hubs don't. Some systems could save a | ||
528 | * lot of battery power by eliminating these root hub timer IRQs. | ||
529 | */ | 528 | */ |
529 | void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | ||
530 | { | ||
531 | struct urb *urb; | ||
532 | int length; | ||
533 | unsigned long flags; | ||
534 | char buffer[4]; /* Any root hubs with > 31 ports? */ | ||
530 | 535 | ||
531 | static void rh_report_status (unsigned long ptr); | 536 | if (!hcd->uses_new_polling && !hcd->status_urb) |
537 | return; | ||
532 | 538 | ||
533 | static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) | 539 | length = hcd->driver->hub_status_data(hcd, buffer); |
534 | { | 540 | if (length > 0) { |
535 | int len = 1 + (urb->dev->maxchild / 8); | ||
536 | 541 | ||
537 | /* rh_timer protected by hcd_data_lock */ | 542 | /* try to complete the status urb */ |
538 | if (hcd->rh_timer.data || urb->transfer_buffer_length < len) { | 543 | local_irq_save (flags); |
539 | dev_dbg (hcd->self.controller, | 544 | spin_lock(&hcd_root_hub_lock); |
540 | "not queuing rh status urb, stat %d\n", | 545 | urb = hcd->status_urb; |
541 | urb->status); | 546 | if (urb) { |
542 | return -EINVAL; | 547 | spin_lock(&urb->lock); |
548 | if (urb->status == -EINPROGRESS) { | ||
549 | hcd->poll_pending = 0; | ||
550 | hcd->status_urb = NULL; | ||
551 | urb->status = 0; | ||
552 | urb->hcpriv = NULL; | ||
553 | urb->actual_length = length; | ||
554 | memcpy(urb->transfer_buffer, buffer, length); | ||
555 | } else /* urb has been unlinked */ | ||
556 | length = 0; | ||
557 | spin_unlock(&urb->lock); | ||
558 | } else | ||
559 | length = 0; | ||
560 | spin_unlock(&hcd_root_hub_lock); | ||
561 | |||
562 | /* local irqs are always blocked in completions */ | ||
563 | if (length > 0) | ||
564 | usb_hcd_giveback_urb (hcd, urb, NULL); | ||
565 | else | ||
566 | hcd->poll_pending = 1; | ||
567 | local_irq_restore (flags); | ||
543 | } | 568 | } |
544 | 569 | ||
545 | init_timer (&hcd->rh_timer); | 570 | /* The USB 2.0 spec says 256 ms. This is close enough and won't |
546 | hcd->rh_timer.function = rh_report_status; | 571 | * exceed that limit if HZ is 100. */ |
547 | hcd->rh_timer.data = (unsigned long) urb; | 572 | if (hcd->uses_new_polling ? hcd->poll_rh : |
548 | /* USB 2.0 spec says 256msec; this is close enough */ | 573 | (length == 0 && hcd->status_urb != NULL)) |
549 | hcd->rh_timer.expires = jiffies + HZ/4; | 574 | mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250)); |
550 | add_timer (&hcd->rh_timer); | ||
551 | urb->hcpriv = hcd; /* nonzero to indicate it's queued */ | ||
552 | return 0; | ||
553 | } | 575 | } |
576 | EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status); | ||
554 | 577 | ||
555 | /* timer callback */ | 578 | /* timer callback */ |
579 | static void rh_timer_func (unsigned long _hcd) | ||
580 | { | ||
581 | usb_hcd_poll_rh_status((struct usb_hcd *) _hcd); | ||
582 | } | ||
556 | 583 | ||
557 | static void rh_report_status (unsigned long ptr) | 584 | /*-------------------------------------------------------------------------*/ |
585 | |||
586 | static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) | ||
558 | { | 587 | { |
559 | struct urb *urb; | 588 | int retval; |
560 | struct usb_hcd *hcd; | ||
561 | int length = 0; | ||
562 | unsigned long flags; | 589 | unsigned long flags; |
590 | int len = 1 + (urb->dev->maxchild / 8); | ||
563 | 591 | ||
564 | urb = (struct urb *) ptr; | 592 | spin_lock_irqsave (&hcd_root_hub_lock, flags); |
565 | local_irq_save (flags); | 593 | if (urb->status != -EINPROGRESS) /* already unlinked */ |
566 | spin_lock (&urb->lock); | 594 | retval = urb->status; |
595 | else if (hcd->status_urb || urb->transfer_buffer_length < len) { | ||
596 | dev_dbg (hcd->self.controller, "not queuing rh status urb\n"); | ||
597 | retval = -EINVAL; | ||
598 | } else { | ||
599 | hcd->status_urb = urb; | ||
600 | urb->hcpriv = hcd; /* indicate it's queued */ | ||
567 | 601 | ||
568 | /* do nothing if the urb's been unlinked */ | 602 | if (!hcd->uses_new_polling) |
569 | if (!urb->dev | 603 | mod_timer (&hcd->rh_timer, jiffies + |
570 | || urb->status != -EINPROGRESS | 604 | msecs_to_jiffies(250)); |
571 | || (hcd = urb->dev->bus->hcpriv) == NULL) { | ||
572 | spin_unlock (&urb->lock); | ||
573 | local_irq_restore (flags); | ||
574 | return; | ||
575 | } | ||
576 | 605 | ||
577 | /* complete the status urb, or retrigger the timer */ | 606 | /* If a status change has already occurred, report it ASAP */ |
578 | spin_lock (&hcd_data_lock); | 607 | else if (hcd->poll_pending) |
579 | if (urb->dev->state == USB_STATE_CONFIGURED) { | 608 | mod_timer (&hcd->rh_timer, jiffies); |
580 | length = hcd->driver->hub_status_data ( | 609 | retval = 0; |
581 | hcd, urb->transfer_buffer); | ||
582 | if (length > 0) { | ||
583 | hcd->rh_timer.data = 0; | ||
584 | urb->actual_length = length; | ||
585 | urb->status = 0; | ||
586 | urb->hcpriv = NULL; | ||
587 | } else | ||
588 | mod_timer (&hcd->rh_timer, jiffies + HZ/4); | ||
589 | } | 610 | } |
590 | spin_unlock (&hcd_data_lock); | 611 | spin_unlock_irqrestore (&hcd_root_hub_lock, flags); |
591 | spin_unlock (&urb->lock); | 612 | return retval; |
592 | |||
593 | /* local irqs are always blocked in completions */ | ||
594 | if (length > 0) | ||
595 | usb_hcd_giveback_urb (hcd, urb, NULL); | ||
596 | local_irq_restore (flags); | ||
597 | } | 613 | } |
598 | 614 | ||
599 | /*-------------------------------------------------------------------------*/ | ||
600 | |||
601 | static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) | 615 | static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) |
602 | { | 616 | { |
603 | if (usb_pipeint (urb->pipe)) { | 617 | if (usb_pipeint (urb->pipe)) |
604 | int retval; | 618 | return rh_queue_status (hcd, urb); |
605 | unsigned long flags; | ||
606 | |||
607 | spin_lock_irqsave (&hcd_data_lock, flags); | ||
608 | retval = rh_status_urb (hcd, urb); | ||
609 | spin_unlock_irqrestore (&hcd_data_lock, flags); | ||
610 | return retval; | ||
611 | } | ||
612 | if (usb_pipecontrol (urb->pipe)) | 619 | if (usb_pipecontrol (urb->pipe)) |
613 | return rh_call_control (hcd, urb); | 620 | return rh_call_control (hcd, urb); |
614 | else | 621 | return -EINVAL; |
615 | return -EINVAL; | ||
616 | } | 622 | } |
617 | 623 | ||
618 | /*-------------------------------------------------------------------------*/ | 624 | /*-------------------------------------------------------------------------*/ |
619 | 625 | ||
626 | /* Asynchronous unlinks of root-hub control URBs are legal, but they | ||
627 | * don't do anything. Status URB unlinks must be made in process context | ||
628 | * with interrupts enabled. | ||
629 | */ | ||
620 | static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | 630 | static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) |
621 | { | 631 | { |
622 | unsigned long flags; | 632 | if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */ |
633 | if (in_interrupt()) | ||
634 | return 0; /* nothing to do */ | ||
623 | 635 | ||
624 | /* note: always a synchronous unlink */ | ||
625 | if ((unsigned long) urb == hcd->rh_timer.data) { | ||
626 | del_timer_sync (&hcd->rh_timer); | ||
627 | hcd->rh_timer.data = 0; | ||
628 | |||
629 | local_irq_save (flags); | ||
630 | urb->hcpriv = NULL; | ||
631 | usb_hcd_giveback_urb (hcd, urb, NULL); | ||
632 | local_irq_restore (flags); | ||
633 | |||
634 | } else if (usb_pipeendpoint(urb->pipe) == 0) { | ||
635 | spin_lock_irq(&urb->lock); /* from usb_kill_urb */ | 636 | spin_lock_irq(&urb->lock); /* from usb_kill_urb */ |
636 | ++urb->reject; | 637 | ++urb->reject; |
637 | spin_unlock_irq(&urb->lock); | 638 | spin_unlock_irq(&urb->lock); |
@@ -642,8 +643,22 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |||
642 | spin_lock_irq(&urb->lock); | 643 | spin_lock_irq(&urb->lock); |
643 | --urb->reject; | 644 | --urb->reject; |
644 | spin_unlock_irq(&urb->lock); | 645 | spin_unlock_irq(&urb->lock); |
645 | } else | 646 | |
646 | return -EINVAL; | 647 | } else { /* Status URB */ |
648 | if (!hcd->uses_new_polling) | ||
649 | del_timer_sync (&hcd->rh_timer); | ||
650 | local_irq_disable (); | ||
651 | spin_lock (&hcd_root_hub_lock); | ||
652 | if (urb == hcd->status_urb) { | ||
653 | hcd->status_urb = NULL; | ||
654 | urb->hcpriv = NULL; | ||
655 | } else | ||
656 | urb = NULL; /* wasn't fully queued */ | ||
657 | spin_unlock (&hcd_root_hub_lock); | ||
658 | if (urb) | ||
659 | usb_hcd_giveback_urb (hcd, urb, NULL); | ||
660 | local_irq_enable (); | ||
661 | } | ||
647 | 662 | ||
648 | return 0; | 663 | return 0; |
649 | } | 664 | } |
@@ -817,30 +832,22 @@ static void usb_deregister_bus (struct usb_bus *bus) | |||
817 | } | 832 | } |
818 | 833 | ||
819 | /** | 834 | /** |
820 | * usb_hcd_register_root_hub - called by HCD to register its root hub | 835 | * register_root_hub - called by usb_add_hcd() to register a root hub |
821 | * @usb_dev: the usb root hub device to be registered. | 836 | * @usb_dev: the usb root hub device to be registered. |
822 | * @hcd: host controller for this root hub | 837 | * @hcd: host controller for this root hub |
823 | * | 838 | * |
824 | * The USB host controller calls this function to register the root hub | 839 | * This function registers the root hub with the USB subsystem. It sets up |
825 | * properly with the USB subsystem. It sets up the device properly in | 840 | * the device properly in the device tree and stores the root_hub pointer |
826 | * the device tree and stores the root_hub pointer in the bus structure, | 841 | * in the bus structure, then calls usb_new_device() to register the usb |
827 | * then calls usb_new_device() to register the usb device. It also | 842 | * device. It also assigns the root hub's USB address (always 1). |
828 | * assigns the root hub's USB address (always 1). | ||
829 | */ | 843 | */ |
830 | int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) | 844 | static int register_root_hub (struct usb_device *usb_dev, |
845 | struct usb_hcd *hcd) | ||
831 | { | 846 | { |
832 | struct device *parent_dev = hcd->self.controller; | 847 | struct device *parent_dev = hcd->self.controller; |
833 | const int devnum = 1; | 848 | const int devnum = 1; |
834 | int retval; | 849 | int retval; |
835 | 850 | ||
836 | /* hcd->driver->start() reported can_wakeup, probably with | ||
837 | * assistance from board's boot firmware. | ||
838 | * NOTE: normal devices won't enable wakeup by default. | ||
839 | */ | ||
840 | if (hcd->can_wakeup) | ||
841 | dev_dbg (parent_dev, "supports USB remote wakeup\n"); | ||
842 | hcd->remote_wakeup = hcd->can_wakeup; | ||
843 | |||
844 | usb_dev->devnum = devnum; | 851 | usb_dev->devnum = devnum; |
845 | usb_dev->bus->devnum_next = devnum + 1; | 852 | usb_dev->bus->devnum_next = devnum + 1; |
846 | memset (&usb_dev->bus->devmap.devicemap, 0, | 853 | memset (&usb_dev->bus->devmap.devicemap, 0, |
@@ -883,7 +890,16 @@ int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) | |||
883 | 890 | ||
884 | return retval; | 891 | return retval; |
885 | } | 892 | } |
886 | EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub); | 893 | |
894 | void usb_enable_root_hub_irq (struct usb_bus *bus) | ||
895 | { | ||
896 | struct usb_hcd *hcd; | ||
897 | |||
898 | hcd = container_of (bus, struct usb_hcd, self); | ||
899 | if (hcd->driver->hub_irq_enable && !hcd->poll_rh && | ||
900 | hcd->state != HC_STATE_HALT) | ||
901 | hcd->driver->hub_irq_enable (hcd); | ||
902 | } | ||
887 | 903 | ||
888 | 904 | ||
889 | /*-------------------------------------------------------------------------*/ | 905 | /*-------------------------------------------------------------------------*/ |
@@ -1348,7 +1364,8 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep) | |||
1348 | 1364 | ||
1349 | hcd = udev->bus->hcpriv; | 1365 | hcd = udev->bus->hcpriv; |
1350 | 1366 | ||
1351 | WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT); | 1367 | WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT && |
1368 | udev->state != USB_STATE_NOTATTACHED); | ||
1352 | 1369 | ||
1353 | local_irq_disable (); | 1370 | local_irq_disable (); |
1354 | 1371 | ||
@@ -1612,6 +1629,8 @@ void usb_hc_died (struct usb_hcd *hcd) | |||
1612 | 1629 | ||
1613 | spin_lock_irqsave (&hcd_root_hub_lock, flags); | 1630 | spin_lock_irqsave (&hcd_root_hub_lock, flags); |
1614 | if (hcd->rh_registered) { | 1631 | if (hcd->rh_registered) { |
1632 | hcd->poll_rh = 0; | ||
1633 | del_timer(&hcd->rh_timer); | ||
1615 | 1634 | ||
1616 | /* make khubd clean up old urbs and devices */ | 1635 | /* make khubd clean up old urbs and devices */ |
1617 | usb_set_device_state (hcd->self.root_hub, | 1636 | usb_set_device_state (hcd->self.root_hub, |
@@ -1665,6 +1684,8 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, | |||
1665 | hcd->self.bus_name = bus_name; | 1684 | hcd->self.bus_name = bus_name; |
1666 | 1685 | ||
1667 | init_timer(&hcd->rh_timer); | 1686 | init_timer(&hcd->rh_timer); |
1687 | hcd->rh_timer.function = rh_timer_func; | ||
1688 | hcd->rh_timer.data = (unsigned long) hcd; | ||
1668 | 1689 | ||
1669 | hcd->driver = driver; | 1690 | hcd->driver = driver; |
1670 | hcd->product_desc = (driver->product_desc) ? driver->product_desc : | 1691 | hcd->product_desc = (driver->product_desc) ? driver->product_desc : |
@@ -1694,7 +1715,8 @@ EXPORT_SYMBOL (usb_put_hcd); | |||
1694 | int usb_add_hcd(struct usb_hcd *hcd, | 1715 | int usb_add_hcd(struct usb_hcd *hcd, |
1695 | unsigned int irqnum, unsigned long irqflags) | 1716 | unsigned int irqnum, unsigned long irqflags) |
1696 | { | 1717 | { |
1697 | int retval; | 1718 | int retval; |
1719 | struct usb_device *rhdev; | ||
1698 | 1720 | ||
1699 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); | 1721 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); |
1700 | 1722 | ||
@@ -1710,7 +1732,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1710 | } | 1732 | } |
1711 | 1733 | ||
1712 | if ((retval = usb_register_bus(&hcd->self)) < 0) | 1734 | if ((retval = usb_register_bus(&hcd->self)) < 0) |
1713 | goto err1; | 1735 | goto err_register_bus; |
1714 | 1736 | ||
1715 | if (hcd->driver->irq) { | 1737 | if (hcd->driver->irq) { |
1716 | char buf[8], *bufp = buf; | 1738 | char buf[8], *bufp = buf; |
@@ -1727,7 +1749,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1727 | hcd->irq_descr, hcd)) != 0) { | 1749 | hcd->irq_descr, hcd)) != 0) { |
1728 | dev_err(hcd->self.controller, | 1750 | dev_err(hcd->self.controller, |
1729 | "request interrupt %s failed\n", bufp); | 1751 | "request interrupt %s failed\n", bufp); |
1730 | goto err2; | 1752 | goto err_request_irq; |
1731 | } | 1753 | } |
1732 | hcd->irq = irqnum; | 1754 | hcd->irq = irqnum; |
1733 | dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, | 1755 | dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, |
@@ -1743,19 +1765,55 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1743 | (unsigned long long)hcd->rsrc_start); | 1765 | (unsigned long long)hcd->rsrc_start); |
1744 | } | 1766 | } |
1745 | 1767 | ||
1768 | /* Allocate the root hub before calling hcd->driver->start(), | ||
1769 | * but don't register it until afterward so that the hardware | ||
1770 | * is running. | ||
1771 | */ | ||
1772 | if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { | ||
1773 | dev_err(hcd->self.controller, "unable to allocate root hub\n"); | ||
1774 | retval = -ENOMEM; | ||
1775 | goto err_allocate_root_hub; | ||
1776 | } | ||
1777 | rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : | ||
1778 | USB_SPEED_FULL; | ||
1779 | |||
1780 | /* Although in principle hcd->driver->start() might need to use rhdev, | ||
1781 | * none of the current drivers do. | ||
1782 | */ | ||
1746 | if ((retval = hcd->driver->start(hcd)) < 0) { | 1783 | if ((retval = hcd->driver->start(hcd)) < 0) { |
1747 | dev_err(hcd->self.controller, "startup error %d\n", retval); | 1784 | dev_err(hcd->self.controller, "startup error %d\n", retval); |
1748 | goto err3; | 1785 | goto err_hcd_driver_start; |
1749 | } | 1786 | } |
1750 | 1787 | ||
1788 | /* hcd->driver->start() reported can_wakeup, probably with | ||
1789 | * assistance from board's boot firmware. | ||
1790 | * NOTE: normal devices won't enable wakeup by default. | ||
1791 | */ | ||
1792 | if (hcd->can_wakeup) | ||
1793 | dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); | ||
1794 | hcd->remote_wakeup = hcd->can_wakeup; | ||
1795 | |||
1796 | if ((retval = register_root_hub(rhdev, hcd)) != 0) | ||
1797 | goto err_register_root_hub; | ||
1798 | |||
1799 | if (hcd->uses_new_polling && hcd->poll_rh) | ||
1800 | usb_hcd_poll_rh_status(hcd); | ||
1751 | return retval; | 1801 | return retval; |
1752 | 1802 | ||
1753 | err3: | 1803 | err_register_root_hub: |
1804 | hcd->driver->stop(hcd); | ||
1805 | |||
1806 | err_hcd_driver_start: | ||
1807 | usb_put_dev(rhdev); | ||
1808 | |||
1809 | err_allocate_root_hub: | ||
1754 | if (hcd->irq >= 0) | 1810 | if (hcd->irq >= 0) |
1755 | free_irq(irqnum, hcd); | 1811 | free_irq(irqnum, hcd); |
1756 | err2: | 1812 | |
1813 | err_request_irq: | ||
1757 | usb_deregister_bus(&hcd->self); | 1814 | usb_deregister_bus(&hcd->self); |
1758 | err1: | 1815 | |
1816 | err_register_bus: | ||
1759 | hcd_buffer_destroy(hcd); | 1817 | hcd_buffer_destroy(hcd); |
1760 | return retval; | 1818 | return retval; |
1761 | } | 1819 | } |
@@ -1782,6 +1840,9 @@ void usb_remove_hcd(struct usb_hcd *hcd) | |||
1782 | spin_unlock_irq (&hcd_root_hub_lock); | 1840 | spin_unlock_irq (&hcd_root_hub_lock); |
1783 | usb_disconnect(&hcd->self.root_hub); | 1841 | usb_disconnect(&hcd->self.root_hub); |
1784 | 1842 | ||
1843 | hcd->poll_rh = 0; | ||
1844 | del_timer_sync(&hcd->rh_timer); | ||
1845 | |||
1785 | hcd->driver->stop(hcd); | 1846 | hcd->driver->stop(hcd); |
1786 | hcd->state = HC_STATE_HALT; | 1847 | hcd->state = HC_STATE_HALT; |
1787 | 1848 | ||
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 325a51656c3f..8dc13cde2f73 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -65,7 +65,8 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ | |||
65 | const char *product_desc; /* product/vendor string */ | 65 | const char *product_desc; /* product/vendor string */ |
66 | char irq_descr[24]; /* driver + bus # */ | 66 | char irq_descr[24]; /* driver + bus # */ |
67 | 67 | ||
68 | struct timer_list rh_timer; /* drives root hub */ | 68 | struct timer_list rh_timer; /* drives root-hub polling */ |
69 | struct urb *status_urb; /* the current status urb */ | ||
69 | 70 | ||
70 | /* | 71 | /* |
71 | * hardware info/state | 72 | * hardware info/state |
@@ -76,10 +77,17 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ | |||
76 | unsigned remote_wakeup:1;/* sw should use wakeup? */ | 77 | unsigned remote_wakeup:1;/* sw should use wakeup? */ |
77 | unsigned rh_registered:1;/* is root hub registered? */ | 78 | unsigned rh_registered:1;/* is root hub registered? */ |
78 | 79 | ||
80 | /* The next flag is a stopgap, to be removed when all the HCDs | ||
81 | * support the new root-hub polling mechanism. */ | ||
82 | unsigned uses_new_polling:1; | ||
83 | unsigned poll_rh:1; /* poll for rh status? */ | ||
84 | unsigned poll_pending:1; /* status has changed? */ | ||
85 | |||
79 | int irq; /* irq allocated */ | 86 | int irq; /* irq allocated */ |
80 | void __iomem *regs; /* device memory/io */ | 87 | void __iomem *regs; /* device memory/io */ |
81 | u64 rsrc_start; /* memory/io resource start */ | 88 | u64 rsrc_start; /* memory/io resource start */ |
82 | u64 rsrc_len; /* memory/io resource length */ | 89 | u64 rsrc_len; /* memory/io resource length */ |
90 | unsigned power_budget; /* in mA, 0 = no limit */ | ||
83 | 91 | ||
84 | #define HCD_BUFFER_POOLS 4 | 92 | #define HCD_BUFFER_POOLS 4 |
85 | struct dma_pool *pool [HCD_BUFFER_POOLS]; | 93 | struct dma_pool *pool [HCD_BUFFER_POOLS]; |
@@ -207,6 +215,8 @@ struct hc_driver { | |||
207 | int (*hub_suspend)(struct usb_hcd *); | 215 | int (*hub_suspend)(struct usb_hcd *); |
208 | int (*hub_resume)(struct usb_hcd *); | 216 | int (*hub_resume)(struct usb_hcd *); |
209 | int (*start_port_reset)(struct usb_hcd *, unsigned port_num); | 217 | int (*start_port_reset)(struct usb_hcd *, unsigned port_num); |
218 | void (*hub_irq_enable)(struct usb_hcd *); | ||
219 | /* Needed only if port-change IRQs are level-triggered */ | ||
210 | }; | 220 | }; |
211 | 221 | ||
212 | extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); | 222 | extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); |
@@ -243,7 +253,9 @@ void hcd_buffer_free (struct usb_bus *bus, size_t size, | |||
243 | 253 | ||
244 | /* generic bus glue, needed for host controllers that don't use PCI */ | 254 | /* generic bus glue, needed for host controllers that don't use PCI */ |
245 | extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); | 255 | extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); |
256 | |||
246 | extern void usb_hc_died (struct usb_hcd *hcd); | 257 | extern void usb_hc_died (struct usb_hcd *hcd); |
258 | extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); | ||
247 | 259 | ||
248 | /* -------------------------------------------------------------------------- */ | 260 | /* -------------------------------------------------------------------------- */ |
249 | 261 | ||
@@ -341,9 +353,6 @@ extern long usb_calc_bus_time (int speed, int is_input, | |||
341 | 353 | ||
342 | extern struct usb_bus *usb_alloc_bus (struct usb_operations *); | 354 | extern struct usb_bus *usb_alloc_bus (struct usb_operations *); |
343 | 355 | ||
344 | extern int usb_hcd_register_root_hub (struct usb_device *usb_dev, | ||
345 | struct usb_hcd *hcd); | ||
346 | |||
347 | extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); | 356 | extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); |
348 | 357 | ||
349 | extern void usb_set_device_state(struct usb_device *udev, | 358 | extern void usb_set_device_state(struct usb_device *udev, |
@@ -360,6 +369,8 @@ extern wait_queue_head_t usb_kill_urb_queue; | |||
360 | extern struct usb_bus *usb_bus_get (struct usb_bus *bus); | 369 | extern struct usb_bus *usb_bus_get (struct usb_bus *bus); |
361 | extern void usb_bus_put (struct usb_bus *bus); | 370 | extern void usb_bus_put (struct usb_bus *bus); |
362 | 371 | ||
372 | extern void usb_enable_root_hub_irq (struct usb_bus *bus); | ||
373 | |||
363 | extern int usb_find_interface_driver (struct usb_device *dev, | 374 | extern int usb_find_interface_driver (struct usb_device *dev, |
364 | struct usb_interface *interface); | 375 | struct usb_interface *interface); |
365 | 376 | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a8d879a85d04..32ff32181852 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -643,15 +643,21 @@ static int hub_configure(struct usb_hub *hub, | |||
643 | message = "can't get hub status"; | 643 | message = "can't get hub status"; |
644 | goto fail; | 644 | goto fail; |
645 | } | 645 | } |
646 | cpu_to_le16s(&hubstatus); | 646 | le16_to_cpus(&hubstatus); |
647 | if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { | 647 | if (hdev == hdev->bus->root_hub) { |
648 | struct usb_hcd *hcd = | ||
649 | container_of(hdev->bus, struct usb_hcd, self); | ||
650 | |||
651 | hub->power_budget = min(500u, hcd->power_budget) / 2; | ||
652 | } else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { | ||
648 | dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", | 653 | dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", |
649 | hub->descriptor->bHubContrCurrent); | 654 | hub->descriptor->bHubContrCurrent); |
650 | hub->power_budget = (501 - hub->descriptor->bHubContrCurrent) | 655 | hub->power_budget = (501 - hub->descriptor->bHubContrCurrent) |
651 | / 2; | 656 | / 2; |
657 | } | ||
658 | if (hub->power_budget) | ||
652 | dev_dbg(hub_dev, "%dmA bus power budget for children\n", | 659 | dev_dbg(hub_dev, "%dmA bus power budget for children\n", |
653 | hub->power_budget * 2); | 660 | hub->power_budget * 2); |
654 | } | ||
655 | 661 | ||
656 | 662 | ||
657 | ret = hub_hub_status(hub, &hubstatus, &hubchange); | 663 | ret = hub_hub_status(hub, &hubstatus, &hubchange); |
@@ -1727,7 +1733,7 @@ static int finish_port_resume(struct usb_device *udev) | |||
1727 | struct usb_driver *driver; | 1733 | struct usb_driver *driver; |
1728 | 1734 | ||
1729 | intf = udev->actconfig->interface[i]; | 1735 | intf = udev->actconfig->interface[i]; |
1730 | if (intf->dev.power.power_state == PMSG_SUSPEND) | 1736 | if (intf->dev.power.power_state == PMSG_ON) |
1731 | continue; | 1737 | continue; |
1732 | if (!intf->dev.driver) { | 1738 | if (!intf->dev.driver) { |
1733 | /* FIXME maybe force to alt 0 */ | 1739 | /* FIXME maybe force to alt 0 */ |
@@ -2787,6 +2793,11 @@ static void hub_events(void) | |||
2787 | 2793 | ||
2788 | hub->activating = 0; | 2794 | hub->activating = 0; |
2789 | 2795 | ||
2796 | /* If this is a root hub, tell the HCD it's okay to | ||
2797 | * re-enable port-change interrupts now. */ | ||
2798 | if (!hdev->parent) | ||
2799 | usb_enable_root_hub_irq(hdev->bus); | ||
2800 | |||
2790 | loop: | 2801 | loop: |
2791 | usb_unlock_device(hdev); | 2802 | usb_unlock_device(hdev); |
2792 | usb_put_intf(intf); | 2803 | usb_put_intf(intf); |
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index d114b847d56f..53bf5649621e 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
@@ -224,15 +224,4 @@ struct usb_hub { | |||
224 | struct work_struct leds; | 224 | struct work_struct leds; |
225 | }; | 225 | }; |
226 | 226 | ||
227 | /* use this for low-powered root hubs */ | ||
228 | static inline void | ||
229 | hub_set_power_budget (struct usb_device *hubdev, unsigned mA) | ||
230 | { | ||
231 | struct usb_hub *hub; | ||
232 | |||
233 | hub = (struct usb_hub *) | ||
234 | usb_get_intfdata (hubdev->actconfig->interface[0]); | ||
235 | hub->power_budget = min(mA,(unsigned)500)/2; | ||
236 | } | ||
237 | |||
238 | #endif /* __LINUX_HUB_H */ | 227 | #endif /* __LINUX_HUB_H */ |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 3b24f9f2c234..ff075a53c8d6 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -53,6 +53,9 @@ config USB_GADGET_DEBUG_FILES | |||
53 | driver on a new board. Enable these files by choosing "Y" | 53 | driver on a new board. Enable these files by choosing "Y" |
54 | here. If in doubt, or to conserve kernel memory, say "N". | 54 | here. If in doubt, or to conserve kernel memory, say "N". |
55 | 55 | ||
56 | config USB_GADGET_SELECTED | ||
57 | boolean | ||
58 | |||
56 | # | 59 | # |
57 | # USB Peripheral Controller Support | 60 | # USB Peripheral Controller Support |
58 | # | 61 | # |
@@ -85,6 +88,7 @@ config USB_NET2280 | |||
85 | tristate | 88 | tristate |
86 | depends on USB_GADGET_NET2280 | 89 | depends on USB_GADGET_NET2280 |
87 | default USB_GADGET | 90 | default USB_GADGET |
91 | select USB_GADGET_SELECTED | ||
88 | 92 | ||
89 | config USB_GADGET_PXA2XX | 93 | config USB_GADGET_PXA2XX |
90 | boolean "PXA 25x or IXP 4xx" | 94 | boolean "PXA 25x or IXP 4xx" |
@@ -105,6 +109,7 @@ config USB_PXA2XX | |||
105 | tristate | 109 | tristate |
106 | depends on USB_GADGET_PXA2XX | 110 | depends on USB_GADGET_PXA2XX |
107 | default USB_GADGET | 111 | default USB_GADGET |
112 | select USB_GADGET_SELECTED | ||
108 | 113 | ||
109 | # if there's only one gadget driver, using only two bulk endpoints, | 114 | # if there's only one gadget driver, using only two bulk endpoints, |
110 | # don't waste memory for the other endpoints | 115 | # don't waste memory for the other endpoints |
@@ -134,6 +139,7 @@ config USB_GOKU | |||
134 | tristate | 139 | tristate |
135 | depends on USB_GADGET_GOKU | 140 | depends on USB_GADGET_GOKU |
136 | default USB_GADGET | 141 | default USB_GADGET |
142 | select USB_GADGET_SELECTED | ||
137 | 143 | ||
138 | 144 | ||
139 | config USB_GADGET_LH7A40X | 145 | config USB_GADGET_LH7A40X |
@@ -146,6 +152,7 @@ config USB_LH7A40X | |||
146 | tristate | 152 | tristate |
147 | depends on USB_GADGET_LH7A40X | 153 | depends on USB_GADGET_LH7A40X |
148 | default USB_GADGET | 154 | default USB_GADGET |
155 | select USB_GADGET_SELECTED | ||
149 | 156 | ||
150 | 157 | ||
151 | config USB_GADGET_OMAP | 158 | config USB_GADGET_OMAP |
@@ -167,6 +174,7 @@ config USB_OMAP | |||
167 | tristate | 174 | tristate |
168 | depends on USB_GADGET_OMAP | 175 | depends on USB_GADGET_OMAP |
169 | default USB_GADGET | 176 | default USB_GADGET |
177 | select USB_GADGET_SELECTED | ||
170 | 178 | ||
171 | config USB_OTG | 179 | config USB_OTG |
172 | boolean "OTG Support" | 180 | boolean "OTG Support" |
@@ -207,6 +215,7 @@ config USB_DUMMY_HCD | |||
207 | tristate | 215 | tristate |
208 | depends on USB_GADGET_DUMMY_HCD | 216 | depends on USB_GADGET_DUMMY_HCD |
209 | default USB_GADGET | 217 | default USB_GADGET |
218 | select USB_GADGET_SELECTED | ||
210 | 219 | ||
211 | # NOTE: Please keep dummy_hcd LAST so that "real hardware" appears | 220 | # NOTE: Please keep dummy_hcd LAST so that "real hardware" appears |
212 | # first and will be selected by default. | 221 | # first and will be selected by default. |
@@ -226,7 +235,7 @@ config USB_GADGET_DUALSPEED | |||
226 | # | 235 | # |
227 | choice | 236 | choice |
228 | tristate "USB Gadget Drivers" | 237 | tristate "USB Gadget Drivers" |
229 | depends on USB_GADGET | 238 | depends on USB_GADGET && USB_GADGET_SELECTED |
230 | default USB_ETH | 239 | default USB_ETH |
231 | help | 240 | help |
232 | A Linux "Gadget Driver" talks to the USB Peripheral Controller | 241 | A Linux "Gadget Driver" talks to the USB Peripheral Controller |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index c039d2fbe7ab..4d692670f288 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -65,7 +65,7 @@ | |||
65 | 65 | ||
66 | 66 | ||
67 | #define DRIVER_DESC "USB Host+Gadget Emulator" | 67 | #define DRIVER_DESC "USB Host+Gadget Emulator" |
68 | #define DRIVER_VERSION "17 Dec 2004" | 68 | #define DRIVER_VERSION "02 May 2005" |
69 | 69 | ||
70 | static const char driver_name [] = "dummy_hcd"; | 70 | static const char driver_name [] = "dummy_hcd"; |
71 | static const char driver_desc [] = "USB Host+Gadget Emulator"; | 71 | static const char driver_desc [] = "USB Host+Gadget Emulator"; |
@@ -141,6 +141,8 @@ static const char *const ep_name [] = { | |||
141 | }; | 141 | }; |
142 | #define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *)) | 142 | #define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *)) |
143 | 143 | ||
144 | /*-------------------------------------------------------------------------*/ | ||
145 | |||
144 | #define FIFO_SIZE 64 | 146 | #define FIFO_SIZE 64 |
145 | 147 | ||
146 | struct urbp { | 148 | struct urbp { |
@@ -148,6 +150,13 @@ struct urbp { | |||
148 | struct list_head urbp_list; | 150 | struct list_head urbp_list; |
149 | }; | 151 | }; |
150 | 152 | ||
153 | |||
154 | enum dummy_rh_state { | ||
155 | DUMMY_RH_RESET, | ||
156 | DUMMY_RH_SUSPENDED, | ||
157 | DUMMY_RH_RUNNING | ||
158 | }; | ||
159 | |||
151 | struct dummy { | 160 | struct dummy { |
152 | spinlock_t lock; | 161 | spinlock_t lock; |
153 | 162 | ||
@@ -161,12 +170,18 @@ struct dummy { | |||
161 | struct dummy_request fifo_req; | 170 | struct dummy_request fifo_req; |
162 | u8 fifo_buf [FIFO_SIZE]; | 171 | u8 fifo_buf [FIFO_SIZE]; |
163 | u16 devstatus; | 172 | u16 devstatus; |
173 | unsigned udc_suspended:1; | ||
174 | unsigned pullup:1; | ||
175 | unsigned active:1; | ||
176 | unsigned old_active:1; | ||
164 | 177 | ||
165 | /* | 178 | /* |
166 | * MASTER/HOST side support | 179 | * MASTER/HOST side support |
167 | */ | 180 | */ |
181 | enum dummy_rh_state rh_state; | ||
168 | struct timer_list timer; | 182 | struct timer_list timer; |
169 | u32 port_status; | 183 | u32 port_status; |
184 | u32 old_status; | ||
170 | unsigned resuming:1; | 185 | unsigned resuming:1; |
171 | unsigned long re_timeout; | 186 | unsigned long re_timeout; |
172 | 187 | ||
@@ -189,6 +204,11 @@ static inline struct device *dummy_dev (struct dummy *dum) | |||
189 | return dummy_to_hcd(dum)->self.controller; | 204 | return dummy_to_hcd(dum)->self.controller; |
190 | } | 205 | } |
191 | 206 | ||
207 | static inline struct device *udc_dev (struct dummy *dum) | ||
208 | { | ||
209 | return dum->gadget.dev.parent; | ||
210 | } | ||
211 | |||
192 | static inline struct dummy *ep_to_dummy (struct dummy_ep *ep) | 212 | static inline struct dummy *ep_to_dummy (struct dummy_ep *ep) |
193 | { | 213 | { |
194 | return container_of (ep->gadget, struct dummy, gadget); | 214 | return container_of (ep->gadget, struct dummy, gadget); |
@@ -208,16 +228,98 @@ static struct dummy *the_controller; | |||
208 | 228 | ||
209 | /*-------------------------------------------------------------------------*/ | 229 | /*-------------------------------------------------------------------------*/ |
210 | 230 | ||
211 | /* | 231 | /* SLAVE/GADGET SIDE UTILITY ROUTINES */ |
212 | * This "hardware" may look a bit odd in diagnostics since it's got both | ||
213 | * host and device sides; and it binds different drivers to each side. | ||
214 | */ | ||
215 | static struct platform_device the_pdev; | ||
216 | 232 | ||
217 | static struct device_driver dummy_driver = { | 233 | /* called with spinlock held */ |
218 | .name = (char *) driver_name, | 234 | static void nuke (struct dummy *dum, struct dummy_ep *ep) |
219 | .bus = &platform_bus_type, | 235 | { |
220 | }; | 236 | while (!list_empty (&ep->queue)) { |
237 | struct dummy_request *req; | ||
238 | |||
239 | req = list_entry (ep->queue.next, struct dummy_request, queue); | ||
240 | list_del_init (&req->queue); | ||
241 | req->req.status = -ESHUTDOWN; | ||
242 | |||
243 | spin_unlock (&dum->lock); | ||
244 | req->req.complete (&ep->ep, &req->req); | ||
245 | spin_lock (&dum->lock); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | /* caller must hold lock */ | ||
250 | static void | ||
251 | stop_activity (struct dummy *dum) | ||
252 | { | ||
253 | struct dummy_ep *ep; | ||
254 | |||
255 | /* prevent any more requests */ | ||
256 | dum->address = 0; | ||
257 | |||
258 | /* The timer is left running so that outstanding URBs can fail */ | ||
259 | |||
260 | /* nuke any pending requests first, so driver i/o is quiesced */ | ||
261 | list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list) | ||
262 | nuke (dum, ep); | ||
263 | |||
264 | /* driver now does any non-usb quiescing necessary */ | ||
265 | } | ||
266 | |||
267 | /* caller must hold lock */ | ||
268 | static void | ||
269 | set_link_state (struct dummy *dum) | ||
270 | { | ||
271 | dum->active = 0; | ||
272 | if ((dum->port_status & USB_PORT_STAT_POWER) == 0) | ||
273 | dum->port_status = 0; | ||
274 | |||
275 | /* UDC suspend must cause a disconnect */ | ||
276 | else if (!dum->pullup || dum->udc_suspended) { | ||
277 | dum->port_status &= ~(USB_PORT_STAT_CONNECTION | | ||
278 | USB_PORT_STAT_ENABLE | | ||
279 | USB_PORT_STAT_LOW_SPEED | | ||
280 | USB_PORT_STAT_HIGH_SPEED | | ||
281 | USB_PORT_STAT_SUSPEND); | ||
282 | if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0) | ||
283 | dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); | ||
284 | } else { | ||
285 | dum->port_status |= USB_PORT_STAT_CONNECTION; | ||
286 | if ((dum->old_status & USB_PORT_STAT_CONNECTION) == 0) | ||
287 | dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); | ||
288 | if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0) | ||
289 | dum->port_status &= ~USB_PORT_STAT_SUSPEND; | ||
290 | else if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 && | ||
291 | dum->rh_state != DUMMY_RH_SUSPENDED) | ||
292 | dum->active = 1; | ||
293 | } | ||
294 | |||
295 | if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0 || dum->active) | ||
296 | dum->resuming = 0; | ||
297 | |||
298 | if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0 || | ||
299 | (dum->port_status & USB_PORT_STAT_RESET) != 0) { | ||
300 | if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0 && | ||
301 | (dum->old_status & USB_PORT_STAT_RESET) == 0 && | ||
302 | dum->driver) { | ||
303 | stop_activity (dum); | ||
304 | spin_unlock (&dum->lock); | ||
305 | dum->driver->disconnect (&dum->gadget); | ||
306 | spin_lock (&dum->lock); | ||
307 | } | ||
308 | } else if (dum->active != dum->old_active) { | ||
309 | if (dum->old_active && dum->driver->suspend) { | ||
310 | spin_unlock (&dum->lock); | ||
311 | dum->driver->suspend (&dum->gadget); | ||
312 | spin_lock (&dum->lock); | ||
313 | } else if (!dum->old_active && dum->driver->resume) { | ||
314 | spin_unlock (&dum->lock); | ||
315 | dum->driver->resume (&dum->gadget); | ||
316 | spin_lock (&dum->lock); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | dum->old_status = dum->port_status; | ||
321 | dum->old_active = dum->active; | ||
322 | } | ||
221 | 323 | ||
222 | /*-------------------------------------------------------------------------*/ | 324 | /*-------------------------------------------------------------------------*/ |
223 | 325 | ||
@@ -324,7 +426,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) | |||
324 | _ep->maxpacket = max; | 426 | _ep->maxpacket = max; |
325 | ep->desc = desc; | 427 | ep->desc = desc; |
326 | 428 | ||
327 | dev_dbg (dummy_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n", | 429 | dev_dbg (udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n", |
328 | _ep->name, | 430 | _ep->name, |
329 | desc->bEndpointAddress & 0x0f, | 431 | desc->bEndpointAddress & 0x0f, |
330 | (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", | 432 | (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", |
@@ -345,22 +447,6 @@ done: | |||
345 | return retval; | 447 | return retval; |
346 | } | 448 | } |
347 | 449 | ||
348 | /* called with spinlock held */ | ||
349 | static void nuke (struct dummy *dum, struct dummy_ep *ep) | ||
350 | { | ||
351 | while (!list_empty (&ep->queue)) { | ||
352 | struct dummy_request *req; | ||
353 | |||
354 | req = list_entry (ep->queue.next, struct dummy_request, queue); | ||
355 | list_del_init (&req->queue); | ||
356 | req->req.status = -ESHUTDOWN; | ||
357 | |||
358 | spin_unlock (&dum->lock); | ||
359 | req->req.complete (&ep->ep, &req->req); | ||
360 | spin_lock (&dum->lock); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static int dummy_disable (struct usb_ep *_ep) | 450 | static int dummy_disable (struct usb_ep *_ep) |
365 | { | 451 | { |
366 | struct dummy_ep *ep; | 452 | struct dummy_ep *ep; |
@@ -379,7 +465,7 @@ static int dummy_disable (struct usb_ep *_ep) | |||
379 | nuke (dum, ep); | 465 | nuke (dum, ep); |
380 | spin_unlock_irqrestore (&dum->lock, flags); | 466 | spin_unlock_irqrestore (&dum->lock, flags); |
381 | 467 | ||
382 | dev_dbg (dummy_dev(dum), "disabled %s\n", _ep->name); | 468 | dev_dbg (udc_dev(dum), "disabled %s\n", _ep->name); |
383 | return retval; | 469 | return retval; |
384 | } | 470 | } |
385 | 471 | ||
@@ -474,7 +560,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req, int mem_flags) | |||
474 | return -ESHUTDOWN; | 560 | return -ESHUTDOWN; |
475 | 561 | ||
476 | #if 0 | 562 | #if 0 |
477 | dev_dbg (dummy_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", | 563 | dev_dbg (udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", |
478 | ep, _req, _ep->name, _req->length, _req->buf); | 564 | ep, _req, _ep->name, _req->length, _req->buf); |
479 | #endif | 565 | #endif |
480 | 566 | ||
@@ -537,7 +623,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) | |||
537 | spin_unlock_irqrestore (&dum->lock, flags); | 623 | spin_unlock_irqrestore (&dum->lock, flags); |
538 | 624 | ||
539 | if (retval == 0) { | 625 | if (retval == 0) { |
540 | dev_dbg (dummy_dev(dum), | 626 | dev_dbg (udc_dev(dum), |
541 | "dequeued req %p from %s, len %d buf %p\n", | 627 | "dequeued req %p from %s, len %d buf %p\n", |
542 | req, _ep->name, _req->length, _req->buf); | 628 | req, _ep->name, _req->length, _req->buf); |
543 | _req->complete (_ep, _req); | 629 | _req->complete (_ep, _req); |
@@ -601,13 +687,21 @@ static int dummy_wakeup (struct usb_gadget *_gadget) | |||
601 | struct dummy *dum; | 687 | struct dummy *dum; |
602 | 688 | ||
603 | dum = gadget_to_dummy (_gadget); | 689 | dum = gadget_to_dummy (_gadget); |
604 | if ((dum->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) == 0 | 690 | if (!(dum->devstatus & ( (1 << USB_DEVICE_B_HNP_ENABLE) |
605 | || !(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))) | 691 | | (1 << USB_DEVICE_REMOTE_WAKEUP)))) |
606 | return -EINVAL; | 692 | return -EINVAL; |
693 | if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0) | ||
694 | return -ENOLINK; | ||
695 | if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 && | ||
696 | dum->rh_state != DUMMY_RH_SUSPENDED) | ||
697 | return -EIO; | ||
698 | |||
699 | /* FIXME: What if the root hub is suspended but the port isn't? */ | ||
607 | 700 | ||
608 | /* hub notices our request, issues downstream resume, etc */ | 701 | /* hub notices our request, issues downstream resume, etc */ |
609 | dum->resuming = 1; | 702 | dum->resuming = 1; |
610 | dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND); | 703 | dum->re_timeout = jiffies + msecs_to_jiffies(20); |
704 | mod_timer (&dummy_to_hcd (dum)->rh_timer, dum->re_timeout); | ||
611 | return 0; | 705 | return 0; |
612 | } | 706 | } |
613 | 707 | ||
@@ -623,10 +717,26 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value) | |||
623 | return 0; | 717 | return 0; |
624 | } | 718 | } |
625 | 719 | ||
720 | static int dummy_pullup (struct usb_gadget *_gadget, int value) | ||
721 | { | ||
722 | struct dummy *dum; | ||
723 | unsigned long flags; | ||
724 | |||
725 | dum = gadget_to_dummy (_gadget); | ||
726 | spin_lock_irqsave (&dum->lock, flags); | ||
727 | dum->pullup = (value != 0); | ||
728 | set_link_state (dum); | ||
729 | spin_unlock_irqrestore (&dum->lock, flags); | ||
730 | |||
731 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
732 | return 0; | ||
733 | } | ||
734 | |||
626 | static const struct usb_gadget_ops dummy_ops = { | 735 | static const struct usb_gadget_ops dummy_ops = { |
627 | .get_frame = dummy_g_get_frame, | 736 | .get_frame = dummy_g_get_frame, |
628 | .wakeup = dummy_wakeup, | 737 | .wakeup = dummy_wakeup, |
629 | .set_selfpowered = dummy_set_selfpowered, | 738 | .set_selfpowered = dummy_set_selfpowered, |
739 | .pullup = dummy_pullup, | ||
630 | }; | 740 | }; |
631 | 741 | ||
632 | /*-------------------------------------------------------------------------*/ | 742 | /*-------------------------------------------------------------------------*/ |
@@ -641,7 +751,7 @@ show_function (struct device *dev, struct device_attribute *attr, char *buf) | |||
641 | return 0; | 751 | return 0; |
642 | return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function); | 752 | return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function); |
643 | } | 753 | } |
644 | DEVICE_ATTR (function, S_IRUGO, show_function, NULL); | 754 | static DEVICE_ATTR (function, S_IRUGO, show_function, NULL); |
645 | 755 | ||
646 | /*-------------------------------------------------------------------------*/ | 756 | /*-------------------------------------------------------------------------*/ |
647 | 757 | ||
@@ -659,38 +769,6 @@ DEVICE_ATTR (function, S_IRUGO, show_function, NULL); | |||
659 | * for each driver that registers: just add to a big root hub. | 769 | * for each driver that registers: just add to a big root hub. |
660 | */ | 770 | */ |
661 | 771 | ||
662 | static void | ||
663 | dummy_udc_release (struct device *dev) | ||
664 | { | ||
665 | } | ||
666 | |||
667 | static void | ||
668 | dummy_pdev_release (struct device *dev) | ||
669 | { | ||
670 | } | ||
671 | |||
672 | static int | ||
673 | dummy_register_udc (struct dummy *dum) | ||
674 | { | ||
675 | int rc; | ||
676 | |||
677 | strcpy (dum->gadget.dev.bus_id, "udc"); | ||
678 | dum->gadget.dev.parent = dummy_dev(dum); | ||
679 | dum->gadget.dev.release = dummy_udc_release; | ||
680 | |||
681 | rc = device_register (&dum->gadget.dev); | ||
682 | if (rc == 0) | ||
683 | device_create_file (&dum->gadget.dev, &dev_attr_function); | ||
684 | return rc; | ||
685 | } | ||
686 | |||
687 | static void | ||
688 | dummy_unregister_udc (struct dummy *dum) | ||
689 | { | ||
690 | device_remove_file (&dum->gadget.dev, &dev_attr_function); | ||
691 | device_unregister (&dum->gadget.dev); | ||
692 | } | ||
693 | |||
694 | int | 772 | int |
695 | usb_gadget_register_driver (struct usb_gadget_driver *driver) | 773 | usb_gadget_register_driver (struct usb_gadget_driver *driver) |
696 | { | 774 | { |
@@ -709,12 +787,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
709 | * SLAVE side init ... the layer above hardware, which | 787 | * SLAVE side init ... the layer above hardware, which |
710 | * can't enumerate without help from the driver we're binding. | 788 | * can't enumerate without help from the driver we're binding. |
711 | */ | 789 | */ |
712 | dum->gadget.name = gadget_name; | ||
713 | dum->gadget.ops = &dummy_ops; | ||
714 | dum->gadget.is_dualspeed = 1; | ||
715 | 790 | ||
716 | dum->devstatus = 0; | 791 | dum->devstatus = 0; |
717 | dum->resuming = 0; | ||
718 | 792 | ||
719 | INIT_LIST_HEAD (&dum->gadget.ep_list); | 793 | INIT_LIST_HEAD (&dum->gadget.ep_list); |
720 | for (i = 0; i < DUMMY_ENDPOINTS; i++) { | 794 | for (i = 0; i < DUMMY_ENDPOINTS; i++) { |
@@ -740,7 +814,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
740 | 814 | ||
741 | dum->driver = driver; | 815 | dum->driver = driver; |
742 | dum->gadget.dev.driver = &driver->driver; | 816 | dum->gadget.dev.driver = &driver->driver; |
743 | dev_dbg (dummy_dev(dum), "binding gadget driver '%s'\n", | 817 | dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n", |
744 | driver->driver.name); | 818 | driver->driver.name); |
745 | if ((retval = driver->bind (&dum->gadget)) != 0) { | 819 | if ((retval = driver->bind (&dum->gadget)) != 0) { |
746 | dum->driver = NULL; | 820 | dum->driver = NULL; |
@@ -748,42 +822,21 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
748 | return retval; | 822 | return retval; |
749 | } | 823 | } |
750 | 824 | ||
751 | // FIXME: Check these calls for errors and re-order | ||
752 | driver->driver.bus = dum->gadget.dev.parent->bus; | 825 | driver->driver.bus = dum->gadget.dev.parent->bus; |
753 | driver_register (&driver->driver); | 826 | driver_register (&driver->driver); |
754 | |||
755 | device_bind_driver (&dum->gadget.dev); | 827 | device_bind_driver (&dum->gadget.dev); |
756 | 828 | ||
757 | /* khubd will enumerate this in a while */ | 829 | /* khubd will enumerate this in a while */ |
758 | dum->port_status |= USB_PORT_STAT_CONNECTION | 830 | spin_lock_irq (&dum->lock); |
759 | | (1 << USB_PORT_FEAT_C_CONNECTION); | 831 | dum->pullup = 1; |
832 | set_link_state (dum); | ||
833 | spin_unlock_irq (&dum->lock); | ||
834 | |||
835 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
760 | return 0; | 836 | return 0; |
761 | } | 837 | } |
762 | EXPORT_SYMBOL (usb_gadget_register_driver); | 838 | EXPORT_SYMBOL (usb_gadget_register_driver); |
763 | 839 | ||
764 | /* caller must hold lock */ | ||
765 | static void | ||
766 | stop_activity (struct dummy *dum, struct usb_gadget_driver *driver) | ||
767 | { | ||
768 | struct dummy_ep *ep; | ||
769 | |||
770 | /* prevent any more requests */ | ||
771 | dum->address = 0; | ||
772 | |||
773 | /* The timer is left running so that outstanding URBs can fail */ | ||
774 | |||
775 | /* nuke any pending requests first, so driver i/o is quiesced */ | ||
776 | list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list) | ||
777 | nuke (dum, ep); | ||
778 | |||
779 | /* driver now does any non-usb quiescing necessary */ | ||
780 | if (driver) { | ||
781 | spin_unlock (&dum->lock); | ||
782 | driver->disconnect (&dum->gadget); | ||
783 | spin_lock (&dum->lock); | ||
784 | } | ||
785 | } | ||
786 | |||
787 | int | 840 | int |
788 | usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | 841 | usb_gadget_unregister_driver (struct usb_gadget_driver *driver) |
789 | { | 842 | { |
@@ -795,35 +848,138 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
795 | if (!driver || driver != dum->driver) | 848 | if (!driver || driver != dum->driver) |
796 | return -EINVAL; | 849 | return -EINVAL; |
797 | 850 | ||
798 | dev_dbg (dummy_dev(dum), "unregister gadget driver '%s'\n", | 851 | dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n", |
799 | driver->driver.name); | 852 | driver->driver.name); |
800 | 853 | ||
801 | spin_lock_irqsave (&dum->lock, flags); | 854 | spin_lock_irqsave (&dum->lock, flags); |
802 | stop_activity (dum, driver); | 855 | dum->pullup = 0; |
803 | dum->port_status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | | 856 | set_link_state (dum); |
804 | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); | ||
805 | dum->port_status |= (1 << USB_PORT_FEAT_C_CONNECTION); | ||
806 | spin_unlock_irqrestore (&dum->lock, flags); | 857 | spin_unlock_irqrestore (&dum->lock, flags); |
807 | 858 | ||
808 | driver->unbind (&dum->gadget); | 859 | driver->unbind (&dum->gadget); |
809 | dum->driver = NULL; | 860 | dum->driver = NULL; |
810 | 861 | ||
811 | device_release_driver (&dum->gadget.dev); | 862 | device_release_driver (&dum->gadget.dev); |
812 | |||
813 | driver_unregister (&driver->driver); | 863 | driver_unregister (&driver->driver); |
814 | 864 | ||
865 | spin_lock_irqsave (&dum->lock, flags); | ||
866 | dum->pullup = 0; | ||
867 | set_link_state (dum); | ||
868 | spin_unlock_irqrestore (&dum->lock, flags); | ||
869 | |||
870 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
815 | return 0; | 871 | return 0; |
816 | } | 872 | } |
817 | EXPORT_SYMBOL (usb_gadget_unregister_driver); | 873 | EXPORT_SYMBOL (usb_gadget_unregister_driver); |
818 | 874 | ||
819 | #undef is_enabled | 875 | #undef is_enabled |
820 | 876 | ||
877 | /* just declare this in any driver that really need it */ | ||
878 | extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); | ||
879 | |||
821 | int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode) | 880 | int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode) |
822 | { | 881 | { |
823 | return -ENOSYS; | 882 | return -ENOSYS; |
824 | } | 883 | } |
825 | EXPORT_SYMBOL (net2280_set_fifo_mode); | 884 | EXPORT_SYMBOL (net2280_set_fifo_mode); |
826 | 885 | ||
886 | |||
887 | /* The gadget structure is stored inside the hcd structure and will be | ||
888 | * released along with it. */ | ||
889 | static void | ||
890 | dummy_gadget_release (struct device *dev) | ||
891 | { | ||
892 | #if 0 /* usb_bus_put isn't EXPORTed! */ | ||
893 | struct dummy *dum = gadget_dev_to_dummy (dev); | ||
894 | |||
895 | usb_bus_put (&dummy_to_hcd (dum)->self); | ||
896 | #endif | ||
897 | } | ||
898 | |||
899 | static int dummy_udc_probe (struct device *dev) | ||
900 | { | ||
901 | struct dummy *dum = the_controller; | ||
902 | int rc; | ||
903 | |||
904 | dum->gadget.name = gadget_name; | ||
905 | dum->gadget.ops = &dummy_ops; | ||
906 | dum->gadget.is_dualspeed = 1; | ||
907 | |||
908 | /* maybe claim OTG support, though we won't complete HNP */ | ||
909 | dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0); | ||
910 | |||
911 | strcpy (dum->gadget.dev.bus_id, "gadget"); | ||
912 | dum->gadget.dev.parent = dev; | ||
913 | dum->gadget.dev.release = dummy_gadget_release; | ||
914 | rc = device_register (&dum->gadget.dev); | ||
915 | if (rc < 0) | ||
916 | return rc; | ||
917 | |||
918 | #if 0 /* usb_bus_get isn't EXPORTed! */ | ||
919 | usb_bus_get (&dummy_to_hcd (dum)->self); | ||
920 | #endif | ||
921 | |||
922 | dev_set_drvdata (dev, dum); | ||
923 | device_create_file (&dum->gadget.dev, &dev_attr_function); | ||
924 | return rc; | ||
925 | } | ||
926 | |||
927 | static int dummy_udc_remove (struct device *dev) | ||
928 | { | ||
929 | struct dummy *dum = dev_get_drvdata (dev); | ||
930 | |||
931 | dev_set_drvdata (dev, NULL); | ||
932 | device_remove_file (&dum->gadget.dev, &dev_attr_function); | ||
933 | device_unregister (&dum->gadget.dev); | ||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | static int dummy_udc_suspend (struct device *dev, pm_message_t state, | ||
938 | u32 level) | ||
939 | { | ||
940 | struct dummy *dum = dev_get_drvdata(dev); | ||
941 | |||
942 | if (level != SUSPEND_DISABLE) | ||
943 | return 0; | ||
944 | |||
945 | dev_dbg (dev, "%s\n", __FUNCTION__); | ||
946 | spin_lock_irq (&dum->lock); | ||
947 | dum->udc_suspended = 1; | ||
948 | set_link_state (dum); | ||
949 | spin_unlock_irq (&dum->lock); | ||
950 | |||
951 | dev->power.power_state = state; | ||
952 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | static int dummy_udc_resume (struct device *dev, u32 level) | ||
957 | { | ||
958 | struct dummy *dum = dev_get_drvdata(dev); | ||
959 | |||
960 | if (level != RESUME_ENABLE) | ||
961 | return 0; | ||
962 | |||
963 | dev_dbg (dev, "%s\n", __FUNCTION__); | ||
964 | spin_lock_irq (&dum->lock); | ||
965 | dum->udc_suspended = 0; | ||
966 | set_link_state (dum); | ||
967 | spin_unlock_irq (&dum->lock); | ||
968 | |||
969 | dev->power.power_state = PMSG_ON; | ||
970 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | static struct device_driver dummy_udc_driver = { | ||
975 | .name = (char *) gadget_name, | ||
976 | .bus = &platform_bus_type, | ||
977 | .probe = dummy_udc_probe, | ||
978 | .remove = dummy_udc_remove, | ||
979 | .suspend = dummy_udc_suspend, | ||
980 | .resume = dummy_udc_resume, | ||
981 | }; | ||
982 | |||
827 | /*-------------------------------------------------------------------------*/ | 983 | /*-------------------------------------------------------------------------*/ |
828 | 984 | ||
829 | /* MASTER/HOST SIDE DRIVER | 985 | /* MASTER/HOST SIDE DRIVER |
@@ -880,7 +1036,16 @@ static int dummy_urb_enqueue ( | |||
880 | 1036 | ||
881 | static int dummy_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | 1037 | static int dummy_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) |
882 | { | 1038 | { |
883 | /* giveback happens automatically in timer callback */ | 1039 | struct dummy *dum; |
1040 | unsigned long flags; | ||
1041 | |||
1042 | /* giveback happens automatically in timer callback, | ||
1043 | * so make sure the callback happens */ | ||
1044 | dum = hcd_to_dummy (hcd); | ||
1045 | spin_lock_irqsave (&dum->lock, flags); | ||
1046 | if (dum->rh_state != DUMMY_RH_RUNNING && !list_empty(&dum->urbp_list)) | ||
1047 | mod_timer (&dum->timer, jiffies); | ||
1048 | spin_unlock_irqrestore (&dum->lock, flags); | ||
884 | return 0; | 1049 | return 0; |
885 | } | 1050 | } |
886 | 1051 | ||
@@ -1025,7 +1190,6 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep) | |||
1025 | 1190 | ||
1026 | /* high bandwidth mode */ | 1191 | /* high bandwidth mode */ |
1027 | tmp = le16_to_cpu(ep->desc->wMaxPacketSize); | 1192 | tmp = le16_to_cpu(ep->desc->wMaxPacketSize); |
1028 | tmp = le16_to_cpu (tmp); | ||
1029 | tmp = (tmp >> 11) & 0x03; | 1193 | tmp = (tmp >> 11) & 0x03; |
1030 | tmp *= 8 /* applies to entire frame */; | 1194 | tmp *= 8 /* applies to entire frame */; |
1031 | limit += limit * tmp; | 1195 | limit += limit * tmp; |
@@ -1123,7 +1287,8 @@ restart: | |||
1123 | if (urb->status != -EINPROGRESS) { | 1287 | if (urb->status != -EINPROGRESS) { |
1124 | /* likely it was just unlinked */ | 1288 | /* likely it was just unlinked */ |
1125 | goto return_urb; | 1289 | goto return_urb; |
1126 | } | 1290 | } else if (dum->rh_state != DUMMY_RH_RUNNING) |
1291 | continue; | ||
1127 | type = usb_pipetype (urb->pipe); | 1292 | type = usb_pipetype (urb->pipe); |
1128 | 1293 | ||
1129 | /* used up this frame's non-periodic bandwidth? | 1294 | /* used up this frame's non-periodic bandwidth? |
@@ -1168,12 +1333,14 @@ restart: | |||
1168 | struct usb_ctrlrequest setup; | 1333 | struct usb_ctrlrequest setup; |
1169 | int value = 1; | 1334 | int value = 1; |
1170 | struct dummy_ep *ep2; | 1335 | struct dummy_ep *ep2; |
1336 | unsigned w_index; | ||
1337 | unsigned w_value; | ||
1171 | 1338 | ||
1172 | setup = *(struct usb_ctrlrequest*) urb->setup_packet; | 1339 | setup = *(struct usb_ctrlrequest*) urb->setup_packet; |
1173 | le16_to_cpus (&setup.wIndex); | 1340 | w_index = le16_to_cpu(setup.wIndex); |
1174 | le16_to_cpus (&setup.wValue); | 1341 | w_value = le16_to_cpu(setup.wValue); |
1175 | le16_to_cpus (&setup.wLength); | 1342 | if (le16_to_cpu(setup.wLength) != |
1176 | if (setup.wLength != urb->transfer_buffer_length) { | 1343 | urb->transfer_buffer_length) { |
1177 | maybe_set_status (urb, -EOVERFLOW); | 1344 | maybe_set_status (urb, -EOVERFLOW); |
1178 | goto return_urb; | 1345 | goto return_urb; |
1179 | } | 1346 | } |
@@ -1182,7 +1349,7 @@ restart: | |||
1182 | list_for_each_entry (req, &ep->queue, queue) { | 1349 | list_for_each_entry (req, &ep->queue, queue) { |
1183 | list_del_init (&req->queue); | 1350 | list_del_init (&req->queue); |
1184 | req->req.status = -EOVERFLOW; | 1351 | req->req.status = -EOVERFLOW; |
1185 | dev_dbg (dummy_dev(dum), "stale req = %p\n", | 1352 | dev_dbg (udc_dev(dum), "stale req = %p\n", |
1186 | req); | 1353 | req); |
1187 | 1354 | ||
1188 | spin_unlock (&dum->lock); | 1355 | spin_unlock (&dum->lock); |
@@ -1203,31 +1370,40 @@ restart: | |||
1203 | case USB_REQ_SET_ADDRESS: | 1370 | case USB_REQ_SET_ADDRESS: |
1204 | if (setup.bRequestType != Dev_Request) | 1371 | if (setup.bRequestType != Dev_Request) |
1205 | break; | 1372 | break; |
1206 | dum->address = setup.wValue; | 1373 | dum->address = w_value; |
1207 | maybe_set_status (urb, 0); | 1374 | maybe_set_status (urb, 0); |
1208 | dev_dbg (dummy_dev(dum), "set_address = %d\n", | 1375 | dev_dbg (udc_dev(dum), "set_address = %d\n", |
1209 | setup.wValue); | 1376 | w_value); |
1210 | value = 0; | 1377 | value = 0; |
1211 | break; | 1378 | break; |
1212 | case USB_REQ_SET_FEATURE: | 1379 | case USB_REQ_SET_FEATURE: |
1213 | if (setup.bRequestType == Dev_Request) { | 1380 | if (setup.bRequestType == Dev_Request) { |
1214 | value = 0; | 1381 | value = 0; |
1215 | switch (setup.wValue) { | 1382 | switch (w_value) { |
1216 | case USB_DEVICE_REMOTE_WAKEUP: | 1383 | case USB_DEVICE_REMOTE_WAKEUP: |
1217 | break; | 1384 | break; |
1385 | case USB_DEVICE_B_HNP_ENABLE: | ||
1386 | dum->gadget.b_hnp_enable = 1; | ||
1387 | break; | ||
1388 | case USB_DEVICE_A_HNP_SUPPORT: | ||
1389 | dum->gadget.a_hnp_support = 1; | ||
1390 | break; | ||
1391 | case USB_DEVICE_A_ALT_HNP_SUPPORT: | ||
1392 | dum->gadget.a_alt_hnp_support | ||
1393 | = 1; | ||
1394 | break; | ||
1218 | default: | 1395 | default: |
1219 | value = -EOPNOTSUPP; | 1396 | value = -EOPNOTSUPP; |
1220 | } | 1397 | } |
1221 | if (value == 0) { | 1398 | if (value == 0) { |
1222 | dum->devstatus |= | 1399 | dum->devstatus |= |
1223 | (1 << setup.wValue); | 1400 | (1 << w_value); |
1224 | maybe_set_status (urb, 0); | 1401 | maybe_set_status (urb, 0); |
1225 | } | 1402 | } |
1226 | 1403 | ||
1227 | } else if (setup.bRequestType == Ep_Request) { | 1404 | } else if (setup.bRequestType == Ep_Request) { |
1228 | // endpoint halt | 1405 | // endpoint halt |
1229 | ep2 = find_endpoint (dum, | 1406 | ep2 = find_endpoint (dum, w_index); |
1230 | setup.wIndex); | ||
1231 | if (!ep2) { | 1407 | if (!ep2) { |
1232 | value = -EOPNOTSUPP; | 1408 | value = -EOPNOTSUPP; |
1233 | break; | 1409 | break; |
@@ -1239,7 +1415,7 @@ restart: | |||
1239 | break; | 1415 | break; |
1240 | case USB_REQ_CLEAR_FEATURE: | 1416 | case USB_REQ_CLEAR_FEATURE: |
1241 | if (setup.bRequestType == Dev_Request) { | 1417 | if (setup.bRequestType == Dev_Request) { |
1242 | switch (setup.wValue) { | 1418 | switch (w_value) { |
1243 | case USB_DEVICE_REMOTE_WAKEUP: | 1419 | case USB_DEVICE_REMOTE_WAKEUP: |
1244 | dum->devstatus &= ~(1 << | 1420 | dum->devstatus &= ~(1 << |
1245 | USB_DEVICE_REMOTE_WAKEUP); | 1421 | USB_DEVICE_REMOTE_WAKEUP); |
@@ -1252,8 +1428,7 @@ restart: | |||
1252 | } | 1428 | } |
1253 | } else if (setup.bRequestType == Ep_Request) { | 1429 | } else if (setup.bRequestType == Ep_Request) { |
1254 | // endpoint halt | 1430 | // endpoint halt |
1255 | ep2 = find_endpoint (dum, | 1431 | ep2 = find_endpoint (dum, w_index); |
1256 | setup.wIndex); | ||
1257 | if (!ep2) { | 1432 | if (!ep2) { |
1258 | value = -EOPNOTSUPP; | 1433 | value = -EOPNOTSUPP; |
1259 | break; | 1434 | break; |
@@ -1279,7 +1454,7 @@ restart: | |||
1279 | if (urb->transfer_buffer_length > 0) { | 1454 | if (urb->transfer_buffer_length > 0) { |
1280 | if (setup.bRequestType == | 1455 | if (setup.bRequestType == |
1281 | Ep_InRequest) { | 1456 | Ep_InRequest) { |
1282 | ep2 = find_endpoint (dum, setup.wIndex); | 1457 | ep2 = find_endpoint (dum, w_index); |
1283 | if (!ep2) { | 1458 | if (!ep2) { |
1284 | value = -EOPNOTSUPP; | 1459 | value = -EOPNOTSUPP; |
1285 | break; | 1460 | break; |
@@ -1321,7 +1496,7 @@ restart: | |||
1321 | 1496 | ||
1322 | if (value < 0) { | 1497 | if (value < 0) { |
1323 | if (value != -EOPNOTSUPP) | 1498 | if (value != -EOPNOTSUPP) |
1324 | dev_dbg (dummy_dev(dum), | 1499 | dev_dbg (udc_dev(dum), |
1325 | "setup --> %d\n", | 1500 | "setup --> %d\n", |
1326 | value); | 1501 | value); |
1327 | maybe_set_status (urb, -EPIPE); | 1502 | maybe_set_status (urb, -EPIPE); |
@@ -1377,12 +1552,12 @@ return_urb: | |||
1377 | goto restart; | 1552 | goto restart; |
1378 | } | 1553 | } |
1379 | 1554 | ||
1380 | /* want a 1 msec delay here */ | 1555 | if (list_empty (&dum->urbp_list)) { |
1381 | if (!list_empty (&dum->urbp_list)) | ||
1382 | mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1)); | ||
1383 | else { | ||
1384 | usb_put_dev (dum->udev); | 1556 | usb_put_dev (dum->udev); |
1385 | dum->udev = NULL; | 1557 | dum->udev = NULL; |
1558 | } else if (dum->rh_state == DUMMY_RH_RUNNING) { | ||
1559 | /* want a 1 msec delay here */ | ||
1560 | mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1)); | ||
1386 | } | 1561 | } |
1387 | 1562 | ||
1388 | spin_unlock_irqrestore (&dum->lock, flags); | 1563 | spin_unlock_irqrestore (&dum->lock, flags); |
@@ -1391,29 +1566,39 @@ return_urb: | |||
1391 | /*-------------------------------------------------------------------------*/ | 1566 | /*-------------------------------------------------------------------------*/ |
1392 | 1567 | ||
1393 | #define PORT_C_MASK \ | 1568 | #define PORT_C_MASK \ |
1394 | ((1 << USB_PORT_FEAT_C_CONNECTION) \ | 1569 | ((USB_PORT_STAT_C_CONNECTION \ |
1395 | | (1 << USB_PORT_FEAT_C_ENABLE) \ | 1570 | | USB_PORT_STAT_C_ENABLE \ |
1396 | | (1 << USB_PORT_FEAT_C_SUSPEND) \ | 1571 | | USB_PORT_STAT_C_SUSPEND \ |
1397 | | (1 << USB_PORT_FEAT_C_OVER_CURRENT) \ | 1572 | | USB_PORT_STAT_C_OVERCURRENT \ |
1398 | | (1 << USB_PORT_FEAT_C_RESET)) | 1573 | | USB_PORT_STAT_C_RESET) << 16) |
1399 | 1574 | ||
1400 | static int dummy_hub_status (struct usb_hcd *hcd, char *buf) | 1575 | static int dummy_hub_status (struct usb_hcd *hcd, char *buf) |
1401 | { | 1576 | { |
1402 | struct dummy *dum; | 1577 | struct dummy *dum; |
1403 | unsigned long flags; | 1578 | unsigned long flags; |
1404 | int retval; | 1579 | int retval = 0; |
1405 | 1580 | ||
1406 | dum = hcd_to_dummy (hcd); | 1581 | dum = hcd_to_dummy (hcd); |
1407 | 1582 | ||
1408 | spin_lock_irqsave (&dum->lock, flags); | 1583 | spin_lock_irqsave (&dum->lock, flags); |
1409 | if (!(dum->port_status & PORT_C_MASK)) | 1584 | if (hcd->state != HC_STATE_RUNNING) |
1410 | retval = 0; | 1585 | goto done; |
1411 | else { | 1586 | |
1587 | if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) { | ||
1588 | dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16); | ||
1589 | dum->port_status &= ~USB_PORT_STAT_SUSPEND; | ||
1590 | set_link_state (dum); | ||
1591 | } | ||
1592 | |||
1593 | if ((dum->port_status & PORT_C_MASK) != 0) { | ||
1412 | *buf = (1 << 1); | 1594 | *buf = (1 << 1); |
1413 | dev_dbg (dummy_dev(dum), "port status 0x%08x has changes\n", | 1595 | dev_dbg (dummy_dev(dum), "port status 0x%08x has changes\n", |
1414 | dum->port_status); | 1596 | dum->port_status); |
1415 | retval = 1; | 1597 | retval = 1; |
1598 | if (dum->rh_state == DUMMY_RH_SUSPENDED) | ||
1599 | usb_hcd_resume_root_hub (hcd); | ||
1416 | } | 1600 | } |
1601 | done: | ||
1417 | spin_unlock_irqrestore (&dum->lock, flags); | 1602 | spin_unlock_irqrestore (&dum->lock, flags); |
1418 | return retval; | 1603 | return retval; |
1419 | } | 1604 | } |
@@ -1424,7 +1609,8 @@ hub_descriptor (struct usb_hub_descriptor *desc) | |||
1424 | memset (desc, 0, sizeof *desc); | 1609 | memset (desc, 0, sizeof *desc); |
1425 | desc->bDescriptorType = 0x29; | 1610 | desc->bDescriptorType = 0x29; |
1426 | desc->bDescLength = 9; | 1611 | desc->bDescLength = 9; |
1427 | desc->wHubCharacteristics = __constant_cpu_to_le16 (0x0001); | 1612 | desc->wHubCharacteristics = (__force __u16) |
1613 | (__constant_cpu_to_le16 (0x0001)); | ||
1428 | desc->bNbrPorts = 1; | 1614 | desc->bNbrPorts = 1; |
1429 | desc->bitmap [0] = 0xff; | 1615 | desc->bitmap [0] = 0xff; |
1430 | desc->bitmap [1] = 0xff; | 1616 | desc->bitmap [1] = 0xff; |
@@ -1442,6 +1628,9 @@ static int dummy_hub_control ( | |||
1442 | int retval = 0; | 1628 | int retval = 0; |
1443 | unsigned long flags; | 1629 | unsigned long flags; |
1444 | 1630 | ||
1631 | if (hcd->state != HC_STATE_RUNNING) | ||
1632 | return -ETIMEDOUT; | ||
1633 | |||
1445 | dum = hcd_to_dummy (hcd); | 1634 | dum = hcd_to_dummy (hcd); |
1446 | spin_lock_irqsave (&dum->lock, flags); | 1635 | spin_lock_irqsave (&dum->lock, flags); |
1447 | switch (typeReq) { | 1636 | switch (typeReq) { |
@@ -1450,27 +1639,27 @@ static int dummy_hub_control ( | |||
1450 | case ClearPortFeature: | 1639 | case ClearPortFeature: |
1451 | switch (wValue) { | 1640 | switch (wValue) { |
1452 | case USB_PORT_FEAT_SUSPEND: | 1641 | case USB_PORT_FEAT_SUSPEND: |
1453 | if (dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)) { | 1642 | if (dum->port_status & USB_PORT_STAT_SUSPEND) { |
1454 | /* 20msec resume signaling */ | 1643 | /* 20msec resume signaling */ |
1455 | dum->resuming = 1; | 1644 | dum->resuming = 1; |
1456 | dum->re_timeout = jiffies + | 1645 | dum->re_timeout = jiffies + |
1457 | msecs_to_jiffies(20); | 1646 | msecs_to_jiffies(20); |
1458 | } | 1647 | } |
1459 | break; | 1648 | break; |
1460 | case USB_PORT_FEAT_POWER: | 1649 | case USB_PORT_FEAT_POWER: |
1461 | dum->port_status = 0; | 1650 | if (dum->port_status & USB_PORT_STAT_POWER) |
1462 | dum->resuming = 0; | 1651 | dev_dbg (dummy_dev(dum), "power-off\n"); |
1463 | stop_activity(dum, dum->driver); | 1652 | /* FALLS THROUGH */ |
1464 | break; | ||
1465 | default: | 1653 | default: |
1466 | dum->port_status &= ~(1 << wValue); | 1654 | dum->port_status &= ~(1 << wValue); |
1655 | set_link_state (dum); | ||
1467 | } | 1656 | } |
1468 | break; | 1657 | break; |
1469 | case GetHubDescriptor: | 1658 | case GetHubDescriptor: |
1470 | hub_descriptor ((struct usb_hub_descriptor *) buf); | 1659 | hub_descriptor ((struct usb_hub_descriptor *) buf); |
1471 | break; | 1660 | break; |
1472 | case GetHubStatus: | 1661 | case GetHubStatus: |
1473 | *(u32 *) buf = __constant_cpu_to_le32 (0); | 1662 | *(__le32 *) buf = __constant_cpu_to_le32 (0); |
1474 | break; | 1663 | break; |
1475 | case GetPortStatus: | 1664 | case GetPortStatus: |
1476 | if (wIndex != 1) | 1665 | if (wIndex != 1) |
@@ -1479,23 +1668,16 @@ static int dummy_hub_control ( | |||
1479 | /* whoever resets or resumes must GetPortStatus to | 1668 | /* whoever resets or resumes must GetPortStatus to |
1480 | * complete it!! | 1669 | * complete it!! |
1481 | */ | 1670 | */ |
1482 | if (dum->resuming && time_after (jiffies, dum->re_timeout)) { | 1671 | if (dum->resuming && |
1483 | dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND); | 1672 | time_after_eq (jiffies, dum->re_timeout)) { |
1484 | dum->port_status &= ~(1 << USB_PORT_FEAT_SUSPEND); | 1673 | dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16); |
1485 | dum->resuming = 0; | 1674 | dum->port_status &= ~USB_PORT_STAT_SUSPEND; |
1486 | dum->re_timeout = 0; | ||
1487 | if (dum->driver && dum->driver->resume) { | ||
1488 | spin_unlock (&dum->lock); | ||
1489 | dum->driver->resume (&dum->gadget); | ||
1490 | spin_lock (&dum->lock); | ||
1491 | } | ||
1492 | } | 1675 | } |
1493 | if ((dum->port_status & (1 << USB_PORT_FEAT_RESET)) != 0 | 1676 | if ((dum->port_status & USB_PORT_STAT_RESET) != 0 && |
1494 | && time_after (jiffies, dum->re_timeout)) { | 1677 | time_after_eq (jiffies, dum->re_timeout)) { |
1495 | dum->port_status |= (1 << USB_PORT_FEAT_C_RESET); | 1678 | dum->port_status |= (USB_PORT_STAT_C_RESET << 16); |
1496 | dum->port_status &= ~(1 << USB_PORT_FEAT_RESET); | 1679 | dum->port_status &= ~USB_PORT_STAT_RESET; |
1497 | dum->re_timeout = 0; | 1680 | if (dum->pullup) { |
1498 | if (dum->driver) { | ||
1499 | dum->port_status |= USB_PORT_STAT_ENABLE; | 1681 | dum->port_status |= USB_PORT_STAT_ENABLE; |
1500 | /* give it the best speed we agree on */ | 1682 | /* give it the best speed we agree on */ |
1501 | dum->gadget.speed = dum->driver->speed; | 1683 | dum->gadget.speed = dum->driver->speed; |
@@ -1516,8 +1698,9 @@ static int dummy_hub_control ( | |||
1516 | } | 1698 | } |
1517 | } | 1699 | } |
1518 | } | 1700 | } |
1519 | ((u16 *) buf)[0] = cpu_to_le16 (dum->port_status); | 1701 | set_link_state (dum); |
1520 | ((u16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16); | 1702 | ((__le16 *) buf)[0] = cpu_to_le16 (dum->port_status); |
1703 | ((__le16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16); | ||
1521 | break; | 1704 | break; |
1522 | case SetHubFeature: | 1705 | case SetHubFeature: |
1523 | retval = -EPIPE; | 1706 | retval = -EPIPE; |
@@ -1525,36 +1708,37 @@ static int dummy_hub_control ( | |||
1525 | case SetPortFeature: | 1708 | case SetPortFeature: |
1526 | switch (wValue) { | 1709 | switch (wValue) { |
1527 | case USB_PORT_FEAT_SUSPEND: | 1710 | case USB_PORT_FEAT_SUSPEND: |
1528 | if ((dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)) | 1711 | if (dum->active) { |
1529 | == 0) { | 1712 | dum->port_status |= USB_PORT_STAT_SUSPEND; |
1530 | dum->port_status |= | 1713 | |
1531 | (1 << USB_PORT_FEAT_SUSPEND); | 1714 | /* HNP would happen here; for now we |
1532 | if (dum->driver && dum->driver->suspend) { | 1715 | * assume b_bus_req is always true. |
1533 | spin_unlock (&dum->lock); | 1716 | */ |
1534 | dum->driver->suspend (&dum->gadget); | 1717 | set_link_state (dum); |
1535 | spin_lock (&dum->lock); | 1718 | if (((1 << USB_DEVICE_B_HNP_ENABLE) |
1536 | } | 1719 | & dum->devstatus) != 0) |
1720 | dev_dbg (dummy_dev(dum), | ||
1721 | "no HNP yet!\n"); | ||
1537 | } | 1722 | } |
1538 | break; | 1723 | break; |
1724 | case USB_PORT_FEAT_POWER: | ||
1725 | dum->port_status |= USB_PORT_STAT_POWER; | ||
1726 | set_link_state (dum); | ||
1727 | break; | ||
1539 | case USB_PORT_FEAT_RESET: | 1728 | case USB_PORT_FEAT_RESET: |
1540 | /* if it's already running, disconnect first */ | 1729 | /* if it's already enabled, disable */ |
1541 | if (dum->port_status & USB_PORT_STAT_ENABLE) { | 1730 | dum->port_status &= ~(USB_PORT_STAT_ENABLE |
1542 | dum->port_status &= ~(USB_PORT_STAT_ENABLE | 1731 | | USB_PORT_STAT_LOW_SPEED |
1543 | | USB_PORT_STAT_LOW_SPEED | 1732 | | USB_PORT_STAT_HIGH_SPEED); |
1544 | | USB_PORT_STAT_HIGH_SPEED); | 1733 | dum->devstatus = 0; |
1545 | if (dum->driver) { | ||
1546 | dev_dbg (dummy_dev(dum), | ||
1547 | "disconnect\n"); | ||
1548 | stop_activity (dum, dum->driver); | ||
1549 | } | ||
1550 | |||
1551 | /* FIXME test that code path! */ | ||
1552 | } | ||
1553 | /* 50msec reset signaling */ | 1734 | /* 50msec reset signaling */ |
1554 | dum->re_timeout = jiffies + msecs_to_jiffies(50); | 1735 | dum->re_timeout = jiffies + msecs_to_jiffies(50); |
1555 | /* FALLTHROUGH */ | 1736 | /* FALLS THROUGH */ |
1556 | default: | 1737 | default: |
1557 | dum->port_status |= (1 << wValue); | 1738 | if ((dum->port_status & USB_PORT_STAT_POWER) != 0) { |
1739 | dum->port_status |= (1 << wValue); | ||
1740 | set_link_state (dum); | ||
1741 | } | ||
1558 | } | 1742 | } |
1559 | break; | 1743 | break; |
1560 | 1744 | ||
@@ -1567,9 +1751,35 @@ static int dummy_hub_control ( | |||
1567 | retval = -EPIPE; | 1751 | retval = -EPIPE; |
1568 | } | 1752 | } |
1569 | spin_unlock_irqrestore (&dum->lock, flags); | 1753 | spin_unlock_irqrestore (&dum->lock, flags); |
1754 | |||
1755 | if ((dum->port_status & PORT_C_MASK) != 0) | ||
1756 | usb_hcd_poll_rh_status (hcd); | ||
1570 | return retval; | 1757 | return retval; |
1571 | } | 1758 | } |
1572 | 1759 | ||
1760 | static int dummy_hub_suspend (struct usb_hcd *hcd) | ||
1761 | { | ||
1762 | struct dummy *dum = hcd_to_dummy (hcd); | ||
1763 | |||
1764 | spin_lock_irq (&dum->lock); | ||
1765 | dum->rh_state = DUMMY_RH_SUSPENDED; | ||
1766 | set_link_state (dum); | ||
1767 | spin_unlock_irq (&dum->lock); | ||
1768 | return 0; | ||
1769 | } | ||
1770 | |||
1771 | static int dummy_hub_resume (struct usb_hcd *hcd) | ||
1772 | { | ||
1773 | struct dummy *dum = hcd_to_dummy (hcd); | ||
1774 | |||
1775 | spin_lock_irq (&dum->lock); | ||
1776 | dum->rh_state = DUMMY_RH_RUNNING; | ||
1777 | set_link_state (dum); | ||
1778 | if (!list_empty(&dum->urbp_list)) | ||
1779 | mod_timer (&dum->timer, jiffies); | ||
1780 | spin_unlock_irq (&dum->lock); | ||
1781 | return 0; | ||
1782 | } | ||
1573 | 1783 | ||
1574 | /*-------------------------------------------------------------------------*/ | 1784 | /*-------------------------------------------------------------------------*/ |
1575 | 1785 | ||
@@ -1625,8 +1835,6 @@ static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL); | |||
1625 | static int dummy_start (struct usb_hcd *hcd) | 1835 | static int dummy_start (struct usb_hcd *hcd) |
1626 | { | 1836 | { |
1627 | struct dummy *dum; | 1837 | struct dummy *dum; |
1628 | struct usb_device *root; | ||
1629 | int retval; | ||
1630 | 1838 | ||
1631 | dum = hcd_to_dummy (hcd); | 1839 | dum = hcd_to_dummy (hcd); |
1632 | 1840 | ||
@@ -1639,38 +1847,22 @@ static int dummy_start (struct usb_hcd *hcd) | |||
1639 | init_timer (&dum->timer); | 1847 | init_timer (&dum->timer); |
1640 | dum->timer.function = dummy_timer; | 1848 | dum->timer.function = dummy_timer; |
1641 | dum->timer.data = (unsigned long) dum; | 1849 | dum->timer.data = (unsigned long) dum; |
1850 | dum->rh_state = DUMMY_RH_RUNNING; | ||
1642 | 1851 | ||
1643 | INIT_LIST_HEAD (&dum->urbp_list); | 1852 | INIT_LIST_HEAD (&dum->urbp_list); |
1644 | 1853 | ||
1645 | root = usb_alloc_dev (NULL, &hcd->self, 0); | ||
1646 | if (!root) | ||
1647 | return -ENOMEM; | ||
1648 | |||
1649 | /* root hub enters addressed state... */ | ||
1650 | hcd->state = HC_STATE_RUNNING; | ||
1651 | root->speed = USB_SPEED_HIGH; | ||
1652 | |||
1653 | /* ...then configured, so khubd sees us. */ | ||
1654 | if ((retval = usb_hcd_register_root_hub (root, hcd)) != 0) { | ||
1655 | goto err1; | ||
1656 | } | ||
1657 | |||
1658 | /* only show a low-power port: just 8mA */ | 1854 | /* only show a low-power port: just 8mA */ |
1659 | hub_set_power_budget (root, 8); | 1855 | hcd->power_budget = 8; |
1856 | hcd->state = HC_STATE_RUNNING; | ||
1857 | hcd->uses_new_polling = 1; | ||
1660 | 1858 | ||
1661 | if ((retval = dummy_register_udc (dum)) != 0) | 1859 | #ifdef CONFIG_USB_OTG |
1662 | goto err2; | 1860 | hcd->self.otg_port = 1; |
1861 | #endif | ||
1663 | 1862 | ||
1664 | /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ | 1863 | /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ |
1665 | device_create_file (dummy_dev(dum), &dev_attr_urbs); | 1864 | device_create_file (dummy_dev(dum), &dev_attr_urbs); |
1666 | return 0; | 1865 | return 0; |
1667 | |||
1668 | err2: | ||
1669 | usb_disconnect (&hcd->self.root_hub); | ||
1670 | err1: | ||
1671 | usb_put_dev (root); | ||
1672 | hcd->state = HC_STATE_QUIESCING; | ||
1673 | return retval; | ||
1674 | } | 1866 | } |
1675 | 1867 | ||
1676 | static void dummy_stop (struct usb_hcd *hcd) | 1868 | static void dummy_stop (struct usb_hcd *hcd) |
@@ -1680,10 +1872,7 @@ static void dummy_stop (struct usb_hcd *hcd) | |||
1680 | dum = hcd_to_dummy (hcd); | 1872 | dum = hcd_to_dummy (hcd); |
1681 | 1873 | ||
1682 | device_remove_file (dummy_dev(dum), &dev_attr_urbs); | 1874 | device_remove_file (dummy_dev(dum), &dev_attr_urbs); |
1683 | |||
1684 | usb_gadget_unregister_driver (dum->driver); | 1875 | usb_gadget_unregister_driver (dum->driver); |
1685 | dummy_unregister_udc (dum); | ||
1686 | |||
1687 | dev_info (dummy_dev(dum), "stopped\n"); | 1876 | dev_info (dummy_dev(dum), "stopped\n"); |
1688 | } | 1877 | } |
1689 | 1878 | ||
@@ -1711,9 +1900,11 @@ static const struct hc_driver dummy_hcd = { | |||
1711 | 1900 | ||
1712 | .hub_status_data = dummy_hub_status, | 1901 | .hub_status_data = dummy_hub_status, |
1713 | .hub_control = dummy_hub_control, | 1902 | .hub_control = dummy_hub_control, |
1903 | .hub_suspend = dummy_hub_suspend, | ||
1904 | .hub_resume = dummy_hub_resume, | ||
1714 | }; | 1905 | }; |
1715 | 1906 | ||
1716 | static int dummy_probe (struct device *dev) | 1907 | static int dummy_hcd_probe (struct device *dev) |
1717 | { | 1908 | { |
1718 | struct usb_hcd *hcd; | 1909 | struct usb_hcd *hcd; |
1719 | int retval; | 1910 | int retval; |
@@ -1733,7 +1924,7 @@ static int dummy_probe (struct device *dev) | |||
1733 | return retval; | 1924 | return retval; |
1734 | } | 1925 | } |
1735 | 1926 | ||
1736 | static void dummy_remove (struct device *dev) | 1927 | static int dummy_hcd_remove (struct device *dev) |
1737 | { | 1928 | { |
1738 | struct usb_hcd *hcd; | 1929 | struct usb_hcd *hcd; |
1739 | 1930 | ||
@@ -1741,53 +1932,127 @@ static void dummy_remove (struct device *dev) | |||
1741 | usb_remove_hcd (hcd); | 1932 | usb_remove_hcd (hcd); |
1742 | usb_put_hcd (hcd); | 1933 | usb_put_hcd (hcd); |
1743 | the_controller = NULL; | 1934 | the_controller = NULL; |
1935 | return 0; | ||
1744 | } | 1936 | } |
1745 | 1937 | ||
1746 | /*-------------------------------------------------------------------------*/ | 1938 | static int dummy_hcd_suspend (struct device *dev, pm_message_t state, |
1747 | 1939 | u32 level) | |
1748 | static int dummy_pdev_detect (void) | ||
1749 | { | 1940 | { |
1750 | int retval; | 1941 | struct usb_hcd *hcd; |
1751 | 1942 | ||
1752 | retval = driver_register (&dummy_driver); | 1943 | if (level != SUSPEND_DISABLE) |
1753 | if (retval < 0) | 1944 | return 0; |
1754 | return retval; | 1945 | |
1946 | dev_dbg (dev, "%s\n", __FUNCTION__); | ||
1947 | hcd = dev_get_drvdata (dev); | ||
1755 | 1948 | ||
1756 | the_pdev.name = "hc"; | 1949 | #ifndef CONFIG_USB_SUSPEND |
1757 | the_pdev.dev.driver = &dummy_driver; | 1950 | /* Otherwise this would never happen */ |
1758 | the_pdev.dev.release = dummy_pdev_release; | 1951 | usb_lock_device (hcd->self.root_hub); |
1952 | dummy_hub_suspend (hcd); | ||
1953 | usb_unlock_device (hcd->self.root_hub); | ||
1954 | #endif | ||
1759 | 1955 | ||
1760 | retval = platform_device_register (&the_pdev); | 1956 | hcd->state = HC_STATE_SUSPENDED; |
1761 | if (retval < 0) | 1957 | return 0; |
1762 | driver_unregister (&dummy_driver); | ||
1763 | return retval; | ||
1764 | } | 1958 | } |
1765 | 1959 | ||
1766 | static void dummy_pdev_remove (void) | 1960 | static int dummy_hcd_resume (struct device *dev, u32 level) |
1767 | { | 1961 | { |
1768 | platform_device_unregister (&the_pdev); | 1962 | struct usb_hcd *hcd; |
1769 | driver_unregister (&dummy_driver); | 1963 | |
1964 | if (level != RESUME_ENABLE) | ||
1965 | return 0; | ||
1966 | |||
1967 | dev_dbg (dev, "%s\n", __FUNCTION__); | ||
1968 | hcd = dev_get_drvdata (dev); | ||
1969 | hcd->state = HC_STATE_RUNNING; | ||
1970 | |||
1971 | #ifndef CONFIG_USB_SUSPEND | ||
1972 | /* Otherwise this would never happen */ | ||
1973 | usb_lock_device (hcd->self.root_hub); | ||
1974 | dummy_hub_resume (hcd); | ||
1975 | usb_unlock_device (hcd->self.root_hub); | ||
1976 | #endif | ||
1977 | |||
1978 | usb_hcd_poll_rh_status (hcd); | ||
1979 | return 0; | ||
1770 | } | 1980 | } |
1771 | 1981 | ||
1982 | static struct device_driver dummy_hcd_driver = { | ||
1983 | .name = (char *) driver_name, | ||
1984 | .bus = &platform_bus_type, | ||
1985 | .probe = dummy_hcd_probe, | ||
1986 | .remove = dummy_hcd_remove, | ||
1987 | .suspend = dummy_hcd_suspend, | ||
1988 | .resume = dummy_hcd_resume, | ||
1989 | }; | ||
1990 | |||
1772 | /*-------------------------------------------------------------------------*/ | 1991 | /*-------------------------------------------------------------------------*/ |
1773 | 1992 | ||
1993 | /* These don't need to do anything because the pdev structures are | ||
1994 | * statically allocated. */ | ||
1995 | static void | ||
1996 | dummy_udc_release (struct device *dev) {} | ||
1997 | |||
1998 | static void | ||
1999 | dummy_hcd_release (struct device *dev) {} | ||
2000 | |||
2001 | static struct platform_device the_udc_pdev = { | ||
2002 | .name = (char *) gadget_name, | ||
2003 | .id = -1, | ||
2004 | .dev = { | ||
2005 | .release = dummy_udc_release, | ||
2006 | }, | ||
2007 | }; | ||
2008 | |||
2009 | static struct platform_device the_hcd_pdev = { | ||
2010 | .name = (char *) driver_name, | ||
2011 | .id = -1, | ||
2012 | .dev = { | ||
2013 | .release = dummy_hcd_release, | ||
2014 | }, | ||
2015 | }; | ||
2016 | |||
1774 | static int __init init (void) | 2017 | static int __init init (void) |
1775 | { | 2018 | { |
1776 | int retval; | 2019 | int retval; |
1777 | 2020 | ||
1778 | if (usb_disabled ()) | 2021 | if (usb_disabled ()) |
1779 | return -ENODEV; | 2022 | return -ENODEV; |
1780 | if ((retval = dummy_pdev_detect ()) != 0) | 2023 | |
2024 | retval = driver_register (&dummy_hcd_driver); | ||
2025 | if (retval < 0) | ||
1781 | return retval; | 2026 | return retval; |
1782 | if ((retval = dummy_probe (&the_pdev.dev)) != 0) | 2027 | |
1783 | dummy_pdev_remove (); | 2028 | retval = driver_register (&dummy_udc_driver); |
2029 | if (retval < 0) | ||
2030 | goto err_register_udc_driver; | ||
2031 | |||
2032 | retval = platform_device_register (&the_hcd_pdev); | ||
2033 | if (retval < 0) | ||
2034 | goto err_register_hcd; | ||
2035 | |||
2036 | retval = platform_device_register (&the_udc_pdev); | ||
2037 | if (retval < 0) | ||
2038 | goto err_register_udc; | ||
2039 | return retval; | ||
2040 | |||
2041 | err_register_udc: | ||
2042 | platform_device_unregister (&the_hcd_pdev); | ||
2043 | err_register_hcd: | ||
2044 | driver_unregister (&dummy_udc_driver); | ||
2045 | err_register_udc_driver: | ||
2046 | driver_unregister (&dummy_hcd_driver); | ||
1784 | return retval; | 2047 | return retval; |
1785 | } | 2048 | } |
1786 | module_init (init); | 2049 | module_init (init); |
1787 | 2050 | ||
1788 | static void __exit cleanup (void) | 2051 | static void __exit cleanup (void) |
1789 | { | 2052 | { |
1790 | dummy_remove (&the_pdev.dev); | 2053 | platform_device_unregister (&the_udc_pdev); |
1791 | dummy_pdev_remove (); | 2054 | platform_device_unregister (&the_hcd_pdev); |
2055 | driver_unregister (&dummy_udc_driver); | ||
2056 | driver_unregister (&dummy_hcd_driver); | ||
1792 | } | 2057 | } |
1793 | module_exit (cleanup); | 2058 | module_exit (cleanup); |
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 3f783cbdc7c3..5bb53ae88969 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -84,18 +84,19 @@ | |||
84 | */ | 84 | */ |
85 | 85 | ||
86 | #define DRIVER_DESC "Ethernet Gadget" | 86 | #define DRIVER_DESC "Ethernet Gadget" |
87 | #define DRIVER_VERSION "Equinox 2004" | 87 | #define DRIVER_VERSION "May Day 2005" |
88 | 88 | ||
89 | static const char shortname [] = "ether"; | 89 | static const char shortname [] = "ether"; |
90 | static const char driver_desc [] = DRIVER_DESC; | 90 | static const char driver_desc [] = DRIVER_DESC; |
91 | 91 | ||
92 | #define RX_EXTRA 20 /* guard against rx overflows */ | 92 | #define RX_EXTRA 20 /* guard against rx overflows */ |
93 | 93 | ||
94 | #ifdef CONFIG_USB_ETH_RNDIS | ||
95 | #include "rndis.h" | 94 | #include "rndis.h" |
96 | #else | 95 | |
97 | #define rndis_init() 0 | 96 | #ifndef CONFIG_USB_ETH_RNDIS |
98 | #define rndis_exit() do{}while(0) | 97 | #define rndis_uninit(x) do{}while(0) |
98 | #define rndis_deregister(c) do{}while(0) | ||
99 | #define rndis_exit() do{}while(0) | ||
99 | #endif | 100 | #endif |
100 | 101 | ||
101 | /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ | 102 | /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ |
@@ -140,9 +141,6 @@ struct eth_dev { | |||
140 | * It also ASSUMES a self-powered device, without remote wakeup, | 141 | * It also ASSUMES a self-powered device, without remote wakeup, |
141 | * although remote wakeup support would make sense. | 142 | * although remote wakeup support would make sense. |
142 | */ | 143 | */ |
143 | static const char *EP_IN_NAME; | ||
144 | static const char *EP_OUT_NAME; | ||
145 | static const char *EP_STATUS_NAME; | ||
146 | 144 | ||
147 | /*-------------------------------------------------------------------------*/ | 145 | /*-------------------------------------------------------------------------*/ |
148 | 146 | ||
@@ -312,6 +310,7 @@ static inline int rndis_active(struct eth_dev *dev) | |||
312 | #define FS_BPS (19 * 64 * 1 * 1000 * 8) | 310 | #define FS_BPS (19 * 64 * 1 * 1000 * 8) |
313 | 311 | ||
314 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 312 | #ifdef CONFIG_USB_GADGET_DUALSPEED |
313 | #define DEVSPEED USB_SPEED_HIGH | ||
315 | 314 | ||
316 | static unsigned qmult = 5; | 315 | static unsigned qmult = 5; |
317 | module_param (qmult, uint, S_IRUGO|S_IWUSR); | 316 | module_param (qmult, uint, S_IRUGO|S_IWUSR); |
@@ -330,6 +329,8 @@ static inline int BITRATE(struct usb_gadget *g) | |||
330 | } | 329 | } |
331 | 330 | ||
332 | #else /* full speed (low speed doesn't do bulk) */ | 331 | #else /* full speed (low speed doesn't do bulk) */ |
332 | #define DEVSPEED USB_SPEED_FULL | ||
333 | |||
333 | #define qlen(gadget) DEFAULT_QLEN | 334 | #define qlen(gadget) DEFAULT_QLEN |
334 | 335 | ||
335 | static inline int BITRATE(struct usb_gadget *g) | 336 | static inline int BITRATE(struct usb_gadget *g) |
@@ -395,7 +396,8 @@ static inline int BITRATE(struct usb_gadget *g) | |||
395 | #define STRING_SUBSET 8 | 396 | #define STRING_SUBSET 8 |
396 | #define STRING_RNDIS 9 | 397 | #define STRING_RNDIS 9 |
397 | 398 | ||
398 | #define USB_BUFSIZ 256 /* holds our biggest descriptor */ | 399 | /* holds our biggest descriptor (or RNDIS response) */ |
400 | #define USB_BUFSIZ 256 | ||
399 | 401 | ||
400 | /* | 402 | /* |
401 | * This device advertises one configuration, eth_config, unless RNDIS | 403 | * This device advertises one configuration, eth_config, unless RNDIS |
@@ -538,7 +540,7 @@ static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { | |||
538 | .bDataInterface = 0x01, | 540 | .bDataInterface = 0x01, |
539 | }; | 541 | }; |
540 | 542 | ||
541 | static struct usb_cdc_acm_descriptor acm_descriptor = { | 543 | static const struct usb_cdc_acm_descriptor acm_descriptor = { |
542 | .bLength = sizeof acm_descriptor, | 544 | .bLength = sizeof acm_descriptor, |
543 | .bDescriptorType = USB_DT_CS_INTERFACE, | 545 | .bDescriptorType = USB_DT_CS_INTERFACE, |
544 | .bDescriptorSubType = USB_CDC_ACM_TYPE, | 546 | .bDescriptorSubType = USB_CDC_ACM_TYPE, |
@@ -846,7 +848,7 @@ static const struct usb_descriptor_header *hs_rndis_function [] = { | |||
846 | #else | 848 | #else |
847 | 849 | ||
848 | /* if there's no high speed support, maxpacket doesn't change. */ | 850 | /* if there's no high speed support, maxpacket doesn't change. */ |
849 | #define ep_desc(g,hs,fs) fs | 851 | #define ep_desc(g,hs,fs) (((void)(g)), (fs)) |
850 | 852 | ||
851 | static inline void __init hs_subset_descriptors(void) | 853 | static inline void __init hs_subset_descriptors(void) |
852 | { | 854 | { |
@@ -946,10 +948,31 @@ config_buf (enum usb_device_speed speed, | |||
946 | static void eth_start (struct eth_dev *dev, int gfp_flags); | 948 | static void eth_start (struct eth_dev *dev, int gfp_flags); |
947 | static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags); | 949 | static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags); |
948 | 950 | ||
949 | #ifdef DEV_CONFIG_CDC | 951 | static int |
950 | static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep) | 952 | set_ether_config (struct eth_dev *dev, int gfp_flags) |
951 | { | 953 | { |
952 | const struct usb_endpoint_descriptor *d; | 954 | int result = 0; |
955 | struct usb_gadget *gadget = dev->gadget; | ||
956 | |||
957 | /* status endpoint used for RNDIS and (optionally) CDC */ | ||
958 | if (!subset_active(dev) && dev->status_ep) { | ||
959 | dev->status = ep_desc (gadget, &hs_status_desc, | ||
960 | &fs_status_desc); | ||
961 | dev->status_ep->driver_data = dev; | ||
962 | |||
963 | result = usb_ep_enable (dev->status_ep, dev->status); | ||
964 | if (result != 0) { | ||
965 | DEBUG (dev, "enable %s --> %d\n", | ||
966 | dev->status_ep->name, result); | ||
967 | goto done; | ||
968 | } | ||
969 | } | ||
970 | |||
971 | dev->in = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); | ||
972 | dev->in_ep->driver_data = dev; | ||
973 | |||
974 | dev->out = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); | ||
975 | dev->out_ep->driver_data = dev; | ||
953 | 976 | ||
954 | /* With CDC, the host isn't allowed to use these two data | 977 | /* With CDC, the host isn't allowed to use these two data |
955 | * endpoints in the default altsetting for the interface. | 978 | * endpoints in the default altsetting for the interface. |
@@ -959,135 +982,33 @@ static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep) | |||
959 | * a side effect of setting a packet filter. Deactivation is | 982 | * a side effect of setting a packet filter. Deactivation is |
960 | * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG. | 983 | * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG. |
961 | */ | 984 | */ |
962 | 985 | if (!cdc_active(dev)) { | |
963 | /* one endpoint writes data back IN to the host */ | 986 | result = usb_ep_enable (dev->in_ep, dev->in); |
964 | if (strcmp (ep->name, EP_IN_NAME) == 0) { | 987 | if (result != 0) { |
965 | d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); | 988 | DEBUG(dev, "enable %s --> %d\n", |
966 | ep->driver_data = dev; | 989 | dev->in_ep->name, result); |
967 | dev->in = d; | 990 | goto done; |
968 | |||
969 | /* one endpoint just reads OUT packets */ | ||
970 | } else if (strcmp (ep->name, EP_OUT_NAME) == 0) { | ||
971 | d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); | ||
972 | ep->driver_data = dev; | ||
973 | dev->out = d; | ||
974 | |||
975 | /* optional status/notification endpoint */ | ||
976 | } else if (EP_STATUS_NAME && | ||
977 | strcmp (ep->name, EP_STATUS_NAME) == 0) { | ||
978 | int result; | ||
979 | |||
980 | d = ep_desc (dev->gadget, &hs_status_desc, &fs_status_desc); | ||
981 | result = usb_ep_enable (ep, d); | ||
982 | if (result < 0) | ||
983 | return result; | ||
984 | |||
985 | ep->driver_data = dev; | ||
986 | dev->status = d; | ||
987 | } | ||
988 | return 0; | ||
989 | } | ||
990 | #endif | ||
991 | |||
992 | #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS) | ||
993 | static inline int ether_ep_setup (struct eth_dev *dev, struct usb_ep *ep) | ||
994 | { | ||
995 | int result; | ||
996 | const struct usb_endpoint_descriptor *d; | ||
997 | |||
998 | /* CDC subset is simpler: if the device is there, | ||
999 | * it's live with rx and tx endpoints. | ||
1000 | * | ||
1001 | * Do this as a shortcut for RNDIS too. | ||
1002 | */ | ||
1003 | |||
1004 | /* one endpoint writes data back IN to the host */ | ||
1005 | if (strcmp (ep->name, EP_IN_NAME) == 0) { | ||
1006 | d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); | ||
1007 | result = usb_ep_enable (ep, d); | ||
1008 | if (result < 0) | ||
1009 | return result; | ||
1010 | |||
1011 | ep->driver_data = dev; | ||
1012 | dev->in = d; | ||
1013 | |||
1014 | /* one endpoint just reads OUT packets */ | ||
1015 | } else if (strcmp (ep->name, EP_OUT_NAME) == 0) { | ||
1016 | d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); | ||
1017 | result = usb_ep_enable (ep, d); | ||
1018 | if (result < 0) | ||
1019 | return result; | ||
1020 | |||
1021 | ep->driver_data = dev; | ||
1022 | dev->out = d; | ||
1023 | } | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | #endif | ||
1028 | |||
1029 | static int | ||
1030 | set_ether_config (struct eth_dev *dev, int gfp_flags) | ||
1031 | { | ||
1032 | int result = 0; | ||
1033 | struct usb_ep *ep; | ||
1034 | struct usb_gadget *gadget = dev->gadget; | ||
1035 | |||
1036 | gadget_for_each_ep (ep, gadget) { | ||
1037 | #ifdef DEV_CONFIG_CDC | ||
1038 | if (!dev->rndis && dev->cdc) { | ||
1039 | result = ether_alt_ep_setup (dev, ep); | ||
1040 | if (result == 0) | ||
1041 | continue; | ||
1042 | } | 991 | } |
1043 | #endif | ||
1044 | |||
1045 | #ifdef CONFIG_USB_ETH_RNDIS | ||
1046 | if (dev->rndis && strcmp (ep->name, EP_STATUS_NAME) == 0) { | ||
1047 | const struct usb_endpoint_descriptor *d; | ||
1048 | d = ep_desc (gadget, &hs_status_desc, &fs_status_desc); | ||
1049 | result = usb_ep_enable (ep, d); | ||
1050 | if (result == 0) { | ||
1051 | ep->driver_data = dev; | ||
1052 | dev->status = d; | ||
1053 | continue; | ||
1054 | } | ||
1055 | } else | ||
1056 | #endif | ||
1057 | 992 | ||
1058 | { | 993 | result = usb_ep_enable (dev->out_ep, dev->out); |
1059 | #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS) | 994 | if (result != 0) { |
1060 | result = ether_ep_setup (dev, ep); | 995 | DEBUG (dev, "enable %s --> %d\n", |
1061 | if (result == 0) | 996 | dev->in_ep->name, result); |
1062 | continue; | 997 | goto done; |
1063 | #endif | ||
1064 | } | 998 | } |
1065 | |||
1066 | /* stop on error */ | ||
1067 | ERROR (dev, "can't enable %s, result %d\n", ep->name, result); | ||
1068 | break; | ||
1069 | } | 999 | } |
1070 | if (!result && (!dev->in_ep || !dev->out_ep)) | ||
1071 | result = -ENODEV; | ||
1072 | 1000 | ||
1001 | done: | ||
1073 | if (result == 0) | 1002 | if (result == 0) |
1074 | result = alloc_requests (dev, qlen (gadget), gfp_flags); | 1003 | result = alloc_requests (dev, qlen (gadget), gfp_flags); |
1075 | 1004 | ||
1076 | /* on error, disable any endpoints */ | 1005 | /* on error, disable any endpoints */ |
1077 | if (result < 0) { | 1006 | if (result < 0) { |
1078 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) | 1007 | if (!subset_active(dev)) |
1079 | if (dev->status) | ||
1080 | (void) usb_ep_disable (dev->status_ep); | 1008 | (void) usb_ep_disable (dev->status_ep); |
1081 | #endif | ||
1082 | dev->status = NULL; | 1009 | dev->status = NULL; |
1083 | #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS) | 1010 | (void) usb_ep_disable (dev->in_ep); |
1084 | if (dev->rndis || !dev->cdc) { | 1011 | (void) usb_ep_disable (dev->out_ep); |
1085 | if (dev->in) | ||
1086 | (void) usb_ep_disable (dev->in_ep); | ||
1087 | if (dev->out) | ||
1088 | (void) usb_ep_disable (dev->out_ep); | ||
1089 | } | ||
1090 | #endif | ||
1091 | dev->in = NULL; | 1012 | dev->in = NULL; |
1092 | dev->out = NULL; | 1013 | dev->out = NULL; |
1093 | } else | 1014 | } else |
@@ -1095,8 +1016,7 @@ set_ether_config (struct eth_dev *dev, int gfp_flags) | |||
1095 | /* activate non-CDC configs right away | 1016 | /* activate non-CDC configs right away |
1096 | * this isn't strictly according to the RNDIS spec | 1017 | * this isn't strictly according to the RNDIS spec |
1097 | */ | 1018 | */ |
1098 | #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS) | 1019 | if (!cdc_active (dev)) { |
1099 | if (dev->rndis || !dev->cdc) { | ||
1100 | netif_carrier_on (dev->net); | 1020 | netif_carrier_on (dev->net); |
1101 | if (netif_running (dev->net)) { | 1021 | if (netif_running (dev->net)) { |
1102 | spin_unlock (&dev->lock); | 1022 | spin_unlock (&dev->lock); |
@@ -1104,7 +1024,6 @@ set_ether_config (struct eth_dev *dev, int gfp_flags) | |||
1104 | spin_lock (&dev->lock); | 1024 | spin_lock (&dev->lock); |
1105 | } | 1025 | } |
1106 | } | 1026 | } |
1107 | #endif | ||
1108 | 1027 | ||
1109 | if (result == 0) | 1028 | if (result == 0) |
1110 | DEBUG (dev, "qlen %d\n", qlen (gadget)); | 1029 | DEBUG (dev, "qlen %d\n", qlen (gadget)); |
@@ -1124,6 +1043,7 @@ static void eth_reset_config (struct eth_dev *dev) | |||
1124 | 1043 | ||
1125 | netif_stop_queue (dev->net); | 1044 | netif_stop_queue (dev->net); |
1126 | netif_carrier_off (dev->net); | 1045 | netif_carrier_off (dev->net); |
1046 | rndis_uninit(dev->rndis_config); | ||
1127 | 1047 | ||
1128 | /* disable endpoints, forcing (synchronous) completion of | 1048 | /* disable endpoints, forcing (synchronous) completion of |
1129 | * pending i/o. then free the requests. | 1049 | * pending i/o. then free the requests. |
@@ -1150,6 +1070,8 @@ static void eth_reset_config (struct eth_dev *dev) | |||
1150 | if (dev->status) { | 1070 | if (dev->status) { |
1151 | usb_ep_disable (dev->status_ep); | 1071 | usb_ep_disable (dev->status_ep); |
1152 | } | 1072 | } |
1073 | dev->rndis = 0; | ||
1074 | dev->cdc_filter = 0; | ||
1153 | dev->config = 0; | 1075 | dev->config = 0; |
1154 | } | 1076 | } |
1155 | 1077 | ||
@@ -1162,9 +1084,6 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) | |||
1162 | int result = 0; | 1084 | int result = 0; |
1163 | struct usb_gadget *gadget = dev->gadget; | 1085 | struct usb_gadget *gadget = dev->gadget; |
1164 | 1086 | ||
1165 | if (number == dev->config) | ||
1166 | return 0; | ||
1167 | |||
1168 | if (gadget_is_sa1100 (gadget) | 1087 | if (gadget_is_sa1100 (gadget) |
1169 | && dev->config | 1088 | && dev->config |
1170 | && atomic_read (&dev->tx_qlen) != 0) { | 1089 | && atomic_read (&dev->tx_qlen) != 0) { |
@@ -1174,12 +1093,8 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) | |||
1174 | } | 1093 | } |
1175 | eth_reset_config (dev); | 1094 | eth_reset_config (dev); |
1176 | 1095 | ||
1177 | /* default: pass all packets, no multicast filtering */ | ||
1178 | dev->cdc_filter = DEFAULT_FILTER; | ||
1179 | |||
1180 | switch (number) { | 1096 | switch (number) { |
1181 | case DEV_CONFIG_VALUE: | 1097 | case DEV_CONFIG_VALUE: |
1182 | dev->rndis = 0; | ||
1183 | result = set_ether_config (dev, gfp_flags); | 1098 | result = set_ether_config (dev, gfp_flags); |
1184 | break; | 1099 | break; |
1185 | #ifdef CONFIG_USB_ETH_RNDIS | 1100 | #ifdef CONFIG_USB_ETH_RNDIS |
@@ -1218,9 +1133,9 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) | |||
1218 | dev->config = number; | 1133 | dev->config = number; |
1219 | INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n", | 1134 | INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n", |
1220 | speed, number, power, driver_desc, | 1135 | speed, number, power, driver_desc, |
1221 | dev->rndis | 1136 | rndis_active(dev) |
1222 | ? "RNDIS" | 1137 | ? "RNDIS" |
1223 | : (dev->cdc | 1138 | : (cdc_active(dev) |
1224 | ? "CDC Ethernet" | 1139 | ? "CDC Ethernet" |
1225 | : "CDC Ethernet Subset")); | 1140 | : "CDC Ethernet Subset")); |
1226 | } | 1141 | } |
@@ -1231,6 +1146,13 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) | |||
1231 | 1146 | ||
1232 | #ifdef DEV_CONFIG_CDC | 1147 | #ifdef DEV_CONFIG_CDC |
1233 | 1148 | ||
1149 | /* The interrupt endpoint is used in CDC networking models (Ethernet, ATM) | ||
1150 | * only to notify the host about link status changes (which we support) or | ||
1151 | * report completion of some encapsulated command (as used in RNDIS). Since | ||
1152 | * we want this CDC Ethernet code to be vendor-neutral, we don't use that | ||
1153 | * command mechanism; and only one status request is ever queued. | ||
1154 | */ | ||
1155 | |||
1234 | static void eth_status_complete (struct usb_ep *ep, struct usb_request *req) | 1156 | static void eth_status_complete (struct usb_ep *ep, struct usb_request *req) |
1235 | { | 1157 | { |
1236 | struct usb_cdc_notification *event = req->buf; | 1158 | struct usb_cdc_notification *event = req->buf; |
@@ -1259,7 +1181,7 @@ static void eth_status_complete (struct usb_ep *ep, struct usb_request *req) | |||
1259 | } else if (value != -ECONNRESET) | 1181 | } else if (value != -ECONNRESET) |
1260 | DEBUG (dev, "event %02x --> %d\n", | 1182 | DEBUG (dev, "event %02x --> %d\n", |
1261 | event->bNotificationType, value); | 1183 | event->bNotificationType, value); |
1262 | event->bmRequestType = 0xff; | 1184 | req->context = NULL; |
1263 | } | 1185 | } |
1264 | 1186 | ||
1265 | static void issue_start_status (struct eth_dev *dev) | 1187 | static void issue_start_status (struct eth_dev *dev) |
@@ -1276,6 +1198,8 @@ static void issue_start_status (struct eth_dev *dev) | |||
1276 | * a "cancel the whole queue" primitive since any | 1198 | * a "cancel the whole queue" primitive since any |
1277 | * unlink-one primitive has way too many error modes. | 1199 | * unlink-one primitive has way too many error modes. |
1278 | * here, we "know" toggle is already clear... | 1200 | * here, we "know" toggle is already clear... |
1201 | * | ||
1202 | * FIXME iff req->context != null just dequeue it | ||
1279 | */ | 1203 | */ |
1280 | usb_ep_disable (dev->status_ep); | 1204 | usb_ep_disable (dev->status_ep); |
1281 | usb_ep_enable (dev->status_ep, dev->status); | 1205 | usb_ep_enable (dev->status_ep, dev->status); |
@@ -1292,6 +1216,8 @@ static void issue_start_status (struct eth_dev *dev) | |||
1292 | 1216 | ||
1293 | req->length = sizeof *event; | 1217 | req->length = sizeof *event; |
1294 | req->complete = eth_status_complete; | 1218 | req->complete = eth_status_complete; |
1219 | req->context = dev; | ||
1220 | |||
1295 | value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC); | 1221 | value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC); |
1296 | if (value < 0) | 1222 | if (value < 0) |
1297 | DEBUG (dev, "status buf queue --> %d\n", value); | 1223 | DEBUG (dev, "status buf queue --> %d\n", value); |
@@ -1351,9 +1277,9 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1351 | struct eth_dev *dev = get_gadget_data (gadget); | 1277 | struct eth_dev *dev = get_gadget_data (gadget); |
1352 | struct usb_request *req = dev->req; | 1278 | struct usb_request *req = dev->req; |
1353 | int value = -EOPNOTSUPP; | 1279 | int value = -EOPNOTSUPP; |
1354 | u16 wIndex = (__force u16) ctrl->wIndex; | 1280 | u16 wIndex = le16_to_cpu(ctrl->wIndex); |
1355 | u16 wValue = (__force u16) ctrl->wValue; | 1281 | u16 wValue = le16_to_cpu(ctrl->wValue); |
1356 | u16 wLength = (__force u16) ctrl->wLength; | 1282 | u16 wLength = le16_to_cpu(ctrl->wLength); |
1357 | 1283 | ||
1358 | /* descriptors just go into the pre-allocated ep0 buffer, | 1284 | /* descriptors just go into the pre-allocated ep0 buffer, |
1359 | * while config change events may enable network traffic. | 1285 | * while config change events may enable network traffic. |
@@ -1424,7 +1350,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1424 | || !dev->config | 1350 | || !dev->config |
1425 | || wIndex > 1) | 1351 | || wIndex > 1) |
1426 | break; | 1352 | break; |
1427 | if (!dev->cdc && wIndex != 0) | 1353 | if (!cdc_active(dev) && wIndex != 0) |
1428 | break; | 1354 | break; |
1429 | spin_lock (&dev->lock); | 1355 | spin_lock (&dev->lock); |
1430 | 1356 | ||
@@ -1456,9 +1382,11 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1456 | 1382 | ||
1457 | /* CDC requires the data transfers not be done from | 1383 | /* CDC requires the data transfers not be done from |
1458 | * the default interface setting ... also, setting | 1384 | * the default interface setting ... also, setting |
1459 | * the non-default interface clears filters etc. | 1385 | * the non-default interface resets filters etc. |
1460 | */ | 1386 | */ |
1461 | if (wValue == 1) { | 1387 | if (wValue == 1) { |
1388 | if (!cdc_active (dev)) | ||
1389 | break; | ||
1462 | usb_ep_enable (dev->in_ep, dev->in); | 1390 | usb_ep_enable (dev->in_ep, dev->in); |
1463 | usb_ep_enable (dev->out_ep, dev->out); | 1391 | usb_ep_enable (dev->out_ep, dev->out); |
1464 | dev->cdc_filter = DEFAULT_FILTER; | 1392 | dev->cdc_filter = DEFAULT_FILTER; |
@@ -1492,11 +1420,11 @@ done_set_intf: | |||
1492 | || !dev->config | 1420 | || !dev->config |
1493 | || wIndex > 1) | 1421 | || wIndex > 1) |
1494 | break; | 1422 | break; |
1495 | if (!(dev->cdc || dev->rndis) && wIndex != 0) | 1423 | if (!(cdc_active(dev) || rndis_active(dev)) && wIndex != 0) |
1496 | break; | 1424 | break; |
1497 | 1425 | ||
1498 | /* for CDC, iff carrier is on, data interface is active. */ | 1426 | /* for CDC, iff carrier is on, data interface is active. */ |
1499 | if (dev->rndis || wIndex != 1) | 1427 | if (rndis_active(dev) || wIndex != 1) |
1500 | *(u8 *)req->buf = 0; | 1428 | *(u8 *)req->buf = 0; |
1501 | else | 1429 | else |
1502 | *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0; | 1430 | *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0; |
@@ -1509,8 +1437,7 @@ done_set_intf: | |||
1509 | * wValue = packet filter bitmap | 1437 | * wValue = packet filter bitmap |
1510 | */ | 1438 | */ |
1511 | if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) | 1439 | if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) |
1512 | || !dev->cdc | 1440 | || !cdc_active(dev) |
1513 | || dev->rndis | ||
1514 | || wLength != 0 | 1441 | || wLength != 0 |
1515 | || wIndex > 1) | 1442 | || wIndex > 1) |
1516 | break; | 1443 | break; |
@@ -1534,7 +1461,7 @@ done_set_intf: | |||
1534 | */ | 1461 | */ |
1535 | case USB_CDC_SEND_ENCAPSULATED_COMMAND: | 1462 | case USB_CDC_SEND_ENCAPSULATED_COMMAND: |
1536 | if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) | 1463 | if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) |
1537 | || !dev->rndis | 1464 | || !rndis_active(dev) |
1538 | || wLength > USB_BUFSIZ | 1465 | || wLength > USB_BUFSIZ |
1539 | || wValue | 1466 | || wValue |
1540 | || rndis_control_intf.bInterfaceNumber | 1467 | || rndis_control_intf.bInterfaceNumber |
@@ -1549,7 +1476,7 @@ done_set_intf: | |||
1549 | case USB_CDC_GET_ENCAPSULATED_RESPONSE: | 1476 | case USB_CDC_GET_ENCAPSULATED_RESPONSE: |
1550 | if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) | 1477 | if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) |
1551 | == ctrl->bRequestType | 1478 | == ctrl->bRequestType |
1552 | && dev->rndis | 1479 | && rndis_active(dev) |
1553 | // && wLength >= 0x0400 | 1480 | // && wLength >= 0x0400 |
1554 | && !wValue | 1481 | && !wValue |
1555 | && rndis_control_intf.bInterfaceNumber | 1482 | && rndis_control_intf.bInterfaceNumber |
@@ -1688,10 +1615,8 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags) | |||
1688 | */ | 1615 | */ |
1689 | size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA); | 1616 | size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA); |
1690 | size += dev->out_ep->maxpacket - 1; | 1617 | size += dev->out_ep->maxpacket - 1; |
1691 | #ifdef CONFIG_USB_ETH_RNDIS | 1618 | if (rndis_active(dev)) |
1692 | if (dev->rndis) | ||
1693 | size += sizeof (struct rndis_packet_msg_type); | 1619 | size += sizeof (struct rndis_packet_msg_type); |
1694 | #endif | ||
1695 | size -= size % dev->out_ep->maxpacket; | 1620 | size -= size % dev->out_ep->maxpacket; |
1696 | 1621 | ||
1697 | if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) { | 1622 | if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) { |
@@ -1735,11 +1660,9 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req) | |||
1735 | /* normal completion */ | 1660 | /* normal completion */ |
1736 | case 0: | 1661 | case 0: |
1737 | skb_put (skb, req->actual); | 1662 | skb_put (skb, req->actual); |
1738 | #ifdef CONFIG_USB_ETH_RNDIS | ||
1739 | /* we know MaxPacketsPerTransfer == 1 here */ | 1663 | /* we know MaxPacketsPerTransfer == 1 here */ |
1740 | if (dev->rndis) | 1664 | if (rndis_active(dev)) |
1741 | status = rndis_rm_hdr (skb); | 1665 | status = rndis_rm_hdr (skb); |
1742 | #endif | ||
1743 | if (status < 0 | 1666 | if (status < 0 |
1744 | || ETH_HLEN > skb->len | 1667 | || ETH_HLEN > skb->len |
1745 | || skb->len > ETH_FRAME_LEN) { | 1668 | || skb->len > ETH_FRAME_LEN) { |
@@ -1859,8 +1782,6 @@ static void rx_fill (struct eth_dev *dev, int gfp_flags) | |||
1859 | struct usb_request *req; | 1782 | struct usb_request *req; |
1860 | unsigned long flags; | 1783 | unsigned long flags; |
1861 | 1784 | ||
1862 | clear_bit (WORK_RX_MEMORY, &dev->todo); | ||
1863 | |||
1864 | /* fill unused rxq slots with some skb */ | 1785 | /* fill unused rxq slots with some skb */ |
1865 | spin_lock_irqsave (&dev->lock, flags); | 1786 | spin_lock_irqsave (&dev->lock, flags); |
1866 | while (!list_empty (&dev->rx_reqs)) { | 1787 | while (!list_empty (&dev->rx_reqs)) { |
@@ -1883,11 +1804,9 @@ static void eth_work (void *_dev) | |||
1883 | { | 1804 | { |
1884 | struct eth_dev *dev = _dev; | 1805 | struct eth_dev *dev = _dev; |
1885 | 1806 | ||
1886 | if (test_bit (WORK_RX_MEMORY, &dev->todo)) { | 1807 | if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) { |
1887 | if (netif_running (dev->net)) | 1808 | if (netif_running (dev->net)) |
1888 | rx_fill (dev, GFP_KERNEL); | 1809 | rx_fill (dev, GFP_KERNEL); |
1889 | else | ||
1890 | clear_bit (WORK_RX_MEMORY, &dev->todo); | ||
1891 | } | 1810 | } |
1892 | 1811 | ||
1893 | if (dev->todo) | 1812 | if (dev->todo) |
@@ -1971,8 +1890,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
1971 | * or the hardware can't use skb buffers. | 1890 | * or the hardware can't use skb buffers. |
1972 | * or there's not enough space for any RNDIS headers we need | 1891 | * or there's not enough space for any RNDIS headers we need |
1973 | */ | 1892 | */ |
1974 | #ifdef CONFIG_USB_ETH_RNDIS | 1893 | if (rndis_active(dev)) { |
1975 | if (dev->rndis) { | ||
1976 | struct sk_buff *skb_rndis; | 1894 | struct sk_buff *skb_rndis; |
1977 | 1895 | ||
1978 | skb_rndis = skb_realloc_headroom (skb, | 1896 | skb_rndis = skb_realloc_headroom (skb, |
@@ -1985,7 +1903,6 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
1985 | rndis_add_hdr (skb); | 1903 | rndis_add_hdr (skb); |
1986 | length = skb->len; | 1904 | length = skb->len; |
1987 | } | 1905 | } |
1988 | #endif | ||
1989 | req->buf = skb->data; | 1906 | req->buf = skb->data; |
1990 | req->context = skb; | 1907 | req->context = skb; |
1991 | req->complete = tx_complete; | 1908 | req->complete = tx_complete; |
@@ -2018,9 +1935,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
2018 | } | 1935 | } |
2019 | 1936 | ||
2020 | if (retval) { | 1937 | if (retval) { |
2021 | #ifdef CONFIG_USB_ETH_RNDIS | ||
2022 | drop: | 1938 | drop: |
2023 | #endif | ||
2024 | dev->stats.tx_dropped++; | 1939 | dev->stats.tx_dropped++; |
2025 | dev_kfree_skb_any (skb); | 1940 | dev_kfree_skb_any (skb); |
2026 | spin_lock_irqsave (&dev->lock, flags); | 1941 | spin_lock_irqsave (&dev->lock, flags); |
@@ -2036,27 +1951,31 @@ drop: | |||
2036 | 1951 | ||
2037 | #ifdef CONFIG_USB_ETH_RNDIS | 1952 | #ifdef CONFIG_USB_ETH_RNDIS |
2038 | 1953 | ||
2039 | static void rndis_send_media_state (struct eth_dev *dev, int connect) | 1954 | /* The interrupt endpoint is used in RNDIS to notify the host when messages |
2040 | { | 1955 | * other than data packets are available ... notably the REMOTE_NDIS_*_CMPLT |
2041 | if (!dev) | 1956 | * messages, but also REMOTE_NDIS_INDICATE_STATUS_MSG and potentially even |
2042 | return; | 1957 | * REMOTE_NDIS_KEEPALIVE_MSG. |
2043 | 1958 | * | |
2044 | if (connect) { | 1959 | * The RNDIS control queue is processed by GET_ENCAPSULATED_RESPONSE, and |
2045 | if (rndis_signal_connect (dev->rndis_config)) | 1960 | * normally just one notification will be queued. |
2046 | return; | 1961 | */ |
2047 | } else { | 1962 | |
2048 | if (rndis_signal_disconnect (dev->rndis_config)) | 1963 | static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, unsigned); |
2049 | return; | 1964 | static void eth_req_free (struct usb_ep *ep, struct usb_request *req); |
2050 | } | ||
2051 | } | ||
2052 | 1965 | ||
2053 | static void | 1966 | static void |
2054 | rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) | 1967 | rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) |
2055 | { | 1968 | { |
1969 | struct eth_dev *dev = ep->driver_data; | ||
1970 | |||
2056 | if (req->status || req->actual != req->length) | 1971 | if (req->status || req->actual != req->length) |
2057 | DEBUG ((struct eth_dev *) ep->driver_data, | 1972 | DEBUG (dev, |
2058 | "rndis control ack complete --> %d, %d/%d\n", | 1973 | "rndis control ack complete --> %d, %d/%d\n", |
2059 | req->status, req->actual, req->length); | 1974 | req->status, req->actual, req->length); |
1975 | req->context = NULL; | ||
1976 | |||
1977 | if (req != dev->stat_req) | ||
1978 | eth_req_free(ep, req); | ||
2060 | } | 1979 | } |
2061 | 1980 | ||
2062 | static int rndis_control_ack (struct net_device *net) | 1981 | static int rndis_control_ack (struct net_device *net) |
@@ -2071,11 +1990,19 @@ static int rndis_control_ack (struct net_device *net) | |||
2071 | return -ENODEV; | 1990 | return -ENODEV; |
2072 | } | 1991 | } |
2073 | 1992 | ||
1993 | /* in case queue length > 1 */ | ||
1994 | if (resp->context) { | ||
1995 | resp = eth_req_alloc (dev->status_ep, 8, GFP_ATOMIC); | ||
1996 | if (!resp) | ||
1997 | return -ENOMEM; | ||
1998 | } | ||
1999 | |||
2074 | /* Send RNDIS RESPONSE_AVAILABLE notification; | 2000 | /* Send RNDIS RESPONSE_AVAILABLE notification; |
2075 | * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too | 2001 | * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too |
2076 | */ | 2002 | */ |
2077 | resp->length = 8; | 2003 | resp->length = 8; |
2078 | resp->complete = rndis_control_ack_complete; | 2004 | resp->complete = rndis_control_ack_complete; |
2005 | resp->context = dev; | ||
2079 | 2006 | ||
2080 | *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1); | 2007 | *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1); |
2081 | *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); | 2008 | *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); |
@@ -2089,6 +2016,10 @@ static int rndis_control_ack (struct net_device *net) | |||
2089 | return 0; | 2016 | return 0; |
2090 | } | 2017 | } |
2091 | 2018 | ||
2019 | #else | ||
2020 | |||
2021 | #define rndis_control_ack NULL | ||
2022 | |||
2092 | #endif /* RNDIS */ | 2023 | #endif /* RNDIS */ |
2093 | 2024 | ||
2094 | static void eth_start (struct eth_dev *dev, int gfp_flags) | 2025 | static void eth_start (struct eth_dev *dev, int gfp_flags) |
@@ -2101,14 +2032,12 @@ static void eth_start (struct eth_dev *dev, int gfp_flags) | |||
2101 | /* and open the tx floodgates */ | 2032 | /* and open the tx floodgates */ |
2102 | atomic_set (&dev->tx_qlen, 0); | 2033 | atomic_set (&dev->tx_qlen, 0); |
2103 | netif_wake_queue (dev->net); | 2034 | netif_wake_queue (dev->net); |
2104 | #ifdef CONFIG_USB_ETH_RNDIS | 2035 | if (rndis_active(dev)) { |
2105 | if (dev->rndis) { | ||
2106 | rndis_set_param_medium (dev->rndis_config, | 2036 | rndis_set_param_medium (dev->rndis_config, |
2107 | NDIS_MEDIUM_802_3, | 2037 | NDIS_MEDIUM_802_3, |
2108 | BITRATE(dev->gadget)/100); | 2038 | BITRATE(dev->gadget)/100); |
2109 | rndis_send_media_state (dev, 1); | 2039 | (void) rndis_signal_connect (dev->rndis_config); |
2110 | } | 2040 | } |
2111 | #endif | ||
2112 | } | 2041 | } |
2113 | 2042 | ||
2114 | static int eth_open (struct net_device *net) | 2043 | static int eth_open (struct net_device *net) |
@@ -2149,28 +2078,27 @@ static int eth_stop (struct net_device *net) | |||
2149 | } | 2078 | } |
2150 | } | 2079 | } |
2151 | 2080 | ||
2152 | #ifdef CONFIG_USB_ETH_RNDIS | 2081 | if (rndis_active(dev)) { |
2153 | if (dev->rndis) { | ||
2154 | rndis_set_param_medium (dev->rndis_config, | 2082 | rndis_set_param_medium (dev->rndis_config, |
2155 | NDIS_MEDIUM_802_3, 0); | 2083 | NDIS_MEDIUM_802_3, 0); |
2156 | rndis_send_media_state (dev, 0); | 2084 | (void) rndis_signal_disconnect (dev->rndis_config); |
2157 | } | 2085 | } |
2158 | #endif | ||
2159 | 2086 | ||
2160 | return 0; | 2087 | return 0; |
2161 | } | 2088 | } |
2162 | 2089 | ||
2163 | /*-------------------------------------------------------------------------*/ | 2090 | /*-------------------------------------------------------------------------*/ |
2164 | 2091 | ||
2165 | static struct usb_request *eth_req_alloc (struct usb_ep *ep, unsigned size) | 2092 | static struct usb_request * |
2093 | eth_req_alloc (struct usb_ep *ep, unsigned size, unsigned gfp_flags) | ||
2166 | { | 2094 | { |
2167 | struct usb_request *req; | 2095 | struct usb_request *req; |
2168 | 2096 | ||
2169 | req = usb_ep_alloc_request (ep, GFP_KERNEL); | 2097 | req = usb_ep_alloc_request (ep, gfp_flags); |
2170 | if (!req) | 2098 | if (!req) |
2171 | return NULL; | 2099 | return NULL; |
2172 | 2100 | ||
2173 | req->buf = kmalloc (size, GFP_KERNEL); | 2101 | req->buf = kmalloc (size, gfp_flags); |
2174 | if (!req->buf) { | 2102 | if (!req->buf) { |
2175 | usb_ep_free_request (ep, req); | 2103 | usb_ep_free_request (ep, req); |
2176 | req = NULL; | 2104 | req = NULL; |
@@ -2192,10 +2120,8 @@ eth_unbind (struct usb_gadget *gadget) | |||
2192 | struct eth_dev *dev = get_gadget_data (gadget); | 2120 | struct eth_dev *dev = get_gadget_data (gadget); |
2193 | 2121 | ||
2194 | DEBUG (dev, "unbind\n"); | 2122 | DEBUG (dev, "unbind\n"); |
2195 | #ifdef CONFIG_USB_ETH_RNDIS | ||
2196 | rndis_deregister (dev->rndis_config); | 2123 | rndis_deregister (dev->rndis_config); |
2197 | rndis_exit (); | 2124 | rndis_exit (); |
2198 | #endif | ||
2199 | 2125 | ||
2200 | /* we've already been disconnected ... no i/o is active */ | 2126 | /* we've already been disconnected ... no i/o is active */ |
2201 | if (dev->req) { | 2127 | if (dev->req) { |
@@ -2368,13 +2294,11 @@ autoconf_fail: | |||
2368 | gadget->name); | 2294 | gadget->name); |
2369 | return -ENODEV; | 2295 | return -ENODEV; |
2370 | } | 2296 | } |
2371 | EP_IN_NAME = in_ep->name; | ||
2372 | in_ep->driver_data = in_ep; /* claim */ | 2297 | in_ep->driver_data = in_ep; /* claim */ |
2373 | 2298 | ||
2374 | out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); | 2299 | out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); |
2375 | if (!out_ep) | 2300 | if (!out_ep) |
2376 | goto autoconf_fail; | 2301 | goto autoconf_fail; |
2377 | EP_OUT_NAME = out_ep->name; | ||
2378 | out_ep->driver_data = out_ep; /* claim */ | 2302 | out_ep->driver_data = out_ep; /* claim */ |
2379 | 2303 | ||
2380 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) | 2304 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) |
@@ -2384,7 +2308,6 @@ autoconf_fail: | |||
2384 | if (cdc || rndis) { | 2308 | if (cdc || rndis) { |
2385 | status_ep = usb_ep_autoconfig (gadget, &fs_status_desc); | 2309 | status_ep = usb_ep_autoconfig (gadget, &fs_status_desc); |
2386 | if (status_ep) { | 2310 | if (status_ep) { |
2387 | EP_STATUS_NAME = status_ep->name; | ||
2388 | status_ep->driver_data = status_ep; /* claim */ | 2311 | status_ep->driver_data = status_ep; /* claim */ |
2389 | } else if (rndis) { | 2312 | } else if (rndis) { |
2390 | dev_err (&gadget->dev, | 2313 | dev_err (&gadget->dev, |
@@ -2426,7 +2349,7 @@ autoconf_fail: | |||
2426 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; | 2349 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; |
2427 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; | 2350 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; |
2428 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) | 2351 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) |
2429 | if (EP_STATUS_NAME) | 2352 | if (status_ep) |
2430 | hs_status_desc.bEndpointAddress = | 2353 | hs_status_desc.bEndpointAddress = |
2431 | fs_status_desc.bEndpointAddress; | 2354 | fs_status_desc.bEndpointAddress; |
2432 | #endif | 2355 | #endif |
@@ -2499,20 +2422,23 @@ autoconf_fail: | |||
2499 | SET_ETHTOOL_OPS(net, &ops); | 2422 | SET_ETHTOOL_OPS(net, &ops); |
2500 | 2423 | ||
2501 | /* preallocate control message data and buffer */ | 2424 | /* preallocate control message data and buffer */ |
2502 | dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ); | 2425 | dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ, GFP_KERNEL); |
2503 | if (!dev->req) | 2426 | if (!dev->req) |
2504 | goto fail; | 2427 | goto fail; |
2505 | dev->req->complete = eth_setup_complete; | 2428 | dev->req->complete = eth_setup_complete; |
2506 | 2429 | ||
2507 | /* ... and maybe likewise for status transfer */ | 2430 | /* ... and maybe likewise for status transfer */ |
2431 | #ifdef DEV_CONFIG_CDC | ||
2508 | if (dev->status_ep) { | 2432 | if (dev->status_ep) { |
2509 | dev->stat_req = eth_req_alloc (dev->status_ep, | 2433 | dev->stat_req = eth_req_alloc (dev->status_ep, |
2510 | STATUS_BYTECOUNT); | 2434 | STATUS_BYTECOUNT, GFP_KERNEL); |
2511 | if (!dev->stat_req) { | 2435 | if (!dev->stat_req) { |
2512 | eth_req_free (gadget->ep0, dev->req); | 2436 | eth_req_free (gadget->ep0, dev->req); |
2513 | goto fail; | 2437 | goto fail; |
2514 | } | 2438 | } |
2439 | dev->stat_req->context = NULL; | ||
2515 | } | 2440 | } |
2441 | #endif | ||
2516 | 2442 | ||
2517 | /* finish hookup to lower layer ... */ | 2443 | /* finish hookup to lower layer ... */ |
2518 | dev->gadget = gadget; | 2444 | dev->gadget = gadget; |
@@ -2526,16 +2452,16 @@ autoconf_fail: | |||
2526 | netif_stop_queue (dev->net); | 2452 | netif_stop_queue (dev->net); |
2527 | netif_carrier_off (dev->net); | 2453 | netif_carrier_off (dev->net); |
2528 | 2454 | ||
2529 | // SET_NETDEV_DEV (dev->net, &gadget->dev); | 2455 | SET_NETDEV_DEV (dev->net, &gadget->dev); |
2530 | status = register_netdev (dev->net); | 2456 | status = register_netdev (dev->net); |
2531 | if (status < 0) | 2457 | if (status < 0) |
2532 | goto fail1; | 2458 | goto fail1; |
2533 | 2459 | ||
2534 | INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); | 2460 | INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); |
2535 | INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name, | 2461 | INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name, |
2536 | EP_OUT_NAME, EP_IN_NAME, | 2462 | out_ep->name, in_ep->name, |
2537 | EP_STATUS_NAME ? " STATUS " : "", | 2463 | status_ep ? " STATUS " : "", |
2538 | EP_STATUS_NAME ? EP_STATUS_NAME : "" | 2464 | status_ep ? status_ep->name : "" |
2539 | ); | 2465 | ); |
2540 | INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", | 2466 | INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", |
2541 | net->dev_addr [0], net->dev_addr [1], | 2467 | net->dev_addr [0], net->dev_addr [1], |
@@ -2548,7 +2474,6 @@ autoconf_fail: | |||
2548 | dev->host_mac [2], dev->host_mac [3], | 2474 | dev->host_mac [2], dev->host_mac [3], |
2549 | dev->host_mac [4], dev->host_mac [5]); | 2475 | dev->host_mac [4], dev->host_mac [5]); |
2550 | 2476 | ||
2551 | #ifdef CONFIG_USB_ETH_RNDIS | ||
2552 | if (rndis) { | 2477 | if (rndis) { |
2553 | u32 vendorID = 0; | 2478 | u32 vendorID = 0; |
2554 | 2479 | ||
@@ -2565,7 +2490,7 @@ fail0: | |||
2565 | /* these set up a lot of the OIDs that RNDIS needs */ | 2490 | /* these set up a lot of the OIDs that RNDIS needs */ |
2566 | rndis_set_host_mac (dev->rndis_config, dev->host_mac); | 2491 | rndis_set_host_mac (dev->rndis_config, dev->host_mac); |
2567 | if (rndis_set_param_dev (dev->rndis_config, dev->net, | 2492 | if (rndis_set_param_dev (dev->rndis_config, dev->net, |
2568 | &dev->stats)) | 2493 | &dev->stats, &dev->cdc_filter)) |
2569 | goto fail0; | 2494 | goto fail0; |
2570 | if (rndis_set_param_vendor (dev->rndis_config, vendorID, | 2495 | if (rndis_set_param_vendor (dev->rndis_config, vendorID, |
2571 | manufacturer)) | 2496 | manufacturer)) |
@@ -2576,7 +2501,6 @@ fail0: | |||
2576 | goto fail0; | 2501 | goto fail0; |
2577 | INFO (dev, "RNDIS ready\n"); | 2502 | INFO (dev, "RNDIS ready\n"); |
2578 | } | 2503 | } |
2579 | #endif | ||
2580 | 2504 | ||
2581 | return status; | 2505 | return status; |
2582 | 2506 | ||
@@ -2610,11 +2534,8 @@ eth_resume (struct usb_gadget *gadget) | |||
2610 | /*-------------------------------------------------------------------------*/ | 2534 | /*-------------------------------------------------------------------------*/ |
2611 | 2535 | ||
2612 | static struct usb_gadget_driver eth_driver = { | 2536 | static struct usb_gadget_driver eth_driver = { |
2613 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 2537 | .speed = DEVSPEED, |
2614 | .speed = USB_SPEED_HIGH, | 2538 | |
2615 | #else | ||
2616 | .speed = USB_SPEED_FULL, | ||
2617 | #endif | ||
2618 | .function = (char *) driver_desc, | 2539 | .function = (char *) driver_desc, |
2619 | .bind = eth_bind, | 2540 | .bind = eth_bind, |
2620 | .unbind = eth_unbind, | 2541 | .unbind = eth_unbind, |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a9be85103d23..4f57085619b4 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -81,6 +81,10 @@ | |||
81 | * removable Default false, boolean for removable media | 81 | * removable Default false, boolean for removable media |
82 | * luns=N Default N = number of filenames, number of | 82 | * luns=N Default N = number of filenames, number of |
83 | * LUNs to support | 83 | * LUNs to support |
84 | * stall Default determined according to the type of | ||
85 | * USB device controller (usually true), | ||
86 | * boolean to permit the driver to halt | ||
87 | * bulk endpoints | ||
84 | * transport=XXX Default BBB, transport name (CB, CBI, or BBB) | 88 | * transport=XXX Default BBB, transport name (CB, CBI, or BBB) |
85 | * protocol=YYY Default SCSI, protocol name (RBC, 8020 or | 89 | * protocol=YYY Default SCSI, protocol name (RBC, 8020 or |
86 | * ATAPI, QIC, UFI, 8070, or SCSI; | 90 | * ATAPI, QIC, UFI, 8070, or SCSI; |
@@ -91,14 +95,10 @@ | |||
91 | * buflen=N Default N=16384, buffer size used (will be | 95 | * buflen=N Default N=16384, buffer size used (will be |
92 | * rounded down to a multiple of | 96 | * rounded down to a multiple of |
93 | * PAGE_CACHE_SIZE) | 97 | * PAGE_CACHE_SIZE) |
94 | * stall Default determined according to the type of | ||
95 | * USB device controller (usually true), | ||
96 | * boolean to permit the driver to halt | ||
97 | * bulk endpoints | ||
98 | * | 98 | * |
99 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", | 99 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", |
100 | * "removable", and "luns" options are available; default values are used | 100 | * "removable", "luns", and "stall" options are available; default values |
101 | * for everything else. | 101 | * are used for everything else. |
102 | * | 102 | * |
103 | * The pathnames of the backing files and the ro settings are available in | 103 | * The pathnames of the backing files and the ro settings are available in |
104 | * the attribute files "file" and "ro" in the lun<n> subdirectory of the | 104 | * the attribute files "file" and "ro" in the lun<n> subdirectory of the |
@@ -342,14 +342,15 @@ static struct { | |||
342 | int num_ros; | 342 | int num_ros; |
343 | unsigned int nluns; | 343 | unsigned int nluns; |
344 | 344 | ||
345 | int removable; | ||
346 | int can_stall; | ||
347 | |||
345 | char *transport_parm; | 348 | char *transport_parm; |
346 | char *protocol_parm; | 349 | char *protocol_parm; |
347 | int removable; | ||
348 | unsigned short vendor; | 350 | unsigned short vendor; |
349 | unsigned short product; | 351 | unsigned short product; |
350 | unsigned short release; | 352 | unsigned short release; |
351 | unsigned int buflen; | 353 | unsigned int buflen; |
352 | int can_stall; | ||
353 | 354 | ||
354 | int transport_type; | 355 | int transport_type; |
355 | char *transport_name; | 356 | char *transport_name; |
@@ -360,11 +361,11 @@ static struct { | |||
360 | .transport_parm = "BBB", | 361 | .transport_parm = "BBB", |
361 | .protocol_parm = "SCSI", | 362 | .protocol_parm = "SCSI", |
362 | .removable = 0, | 363 | .removable = 0, |
364 | .can_stall = 1, | ||
363 | .vendor = DRIVER_VENDOR_ID, | 365 | .vendor = DRIVER_VENDOR_ID, |
364 | .product = DRIVER_PRODUCT_ID, | 366 | .product = DRIVER_PRODUCT_ID, |
365 | .release = 0xffff, // Use controller chip type | 367 | .release = 0xffff, // Use controller chip type |
366 | .buflen = 16384, | 368 | .buflen = 16384, |
367 | .can_stall = 1, | ||
368 | }; | 369 | }; |
369 | 370 | ||
370 | 371 | ||
@@ -380,6 +381,9 @@ MODULE_PARM_DESC(luns, "number of LUNs"); | |||
380 | module_param_named(removable, mod_data.removable, bool, S_IRUGO); | 381 | module_param_named(removable, mod_data.removable, bool, S_IRUGO); |
381 | MODULE_PARM_DESC(removable, "true to simulate removable media"); | 382 | MODULE_PARM_DESC(removable, "true to simulate removable media"); |
382 | 383 | ||
384 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); | ||
385 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); | ||
386 | |||
383 | 387 | ||
384 | /* In the non-TEST version, only the module parameters listed above | 388 | /* In the non-TEST version, only the module parameters listed above |
385 | * are available. */ | 389 | * are available. */ |
@@ -404,9 +408,6 @@ MODULE_PARM_DESC(release, "USB release number"); | |||
404 | module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); | 408 | module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); |
405 | MODULE_PARM_DESC(buflen, "I/O buffer size"); | 409 | MODULE_PARM_DESC(buflen, "I/O buffer size"); |
406 | 410 | ||
407 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); | ||
408 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); | ||
409 | |||
410 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ | 411 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ |
411 | 412 | ||
412 | 413 | ||
@@ -818,7 +819,7 @@ static void inline put_be32(u8 *buf, u32 val) | |||
818 | buf[0] = val >> 24; | 819 | buf[0] = val >> 24; |
819 | buf[1] = val >> 16; | 820 | buf[1] = val >> 16; |
820 | buf[2] = val >> 8; | 821 | buf[2] = val >> 8; |
821 | buf[3] = val; | 822 | buf[3] = val & 0xff; |
822 | } | 823 | } |
823 | 824 | ||
824 | 825 | ||
@@ -1276,8 +1277,8 @@ static int class_setup_req(struct fsg_dev *fsg, | |||
1276 | { | 1277 | { |
1277 | struct usb_request *req = fsg->ep0req; | 1278 | struct usb_request *req = fsg->ep0req; |
1278 | int value = -EOPNOTSUPP; | 1279 | int value = -EOPNOTSUPP; |
1279 | u16 w_index = ctrl->wIndex; | 1280 | u16 w_index = le16_to_cpu(ctrl->wIndex); |
1280 | u16 w_length = ctrl->wLength; | 1281 | u16 w_length = le16_to_cpu(ctrl->wLength); |
1281 | 1282 | ||
1282 | if (!fsg->config) | 1283 | if (!fsg->config) |
1283 | return value; | 1284 | return value; |
@@ -1312,7 +1313,7 @@ static int class_setup_req(struct fsg_dev *fsg, | |||
1312 | } | 1313 | } |
1313 | VDBG(fsg, "get max LUN\n"); | 1314 | VDBG(fsg, "get max LUN\n"); |
1314 | *(u8 *) req->buf = fsg->nluns - 1; | 1315 | *(u8 *) req->buf = fsg->nluns - 1; |
1315 | value = min(w_length, (u16) 1); | 1316 | value = 1; |
1316 | break; | 1317 | break; |
1317 | } | 1318 | } |
1318 | } | 1319 | } |
@@ -1344,7 +1345,7 @@ static int class_setup_req(struct fsg_dev *fsg, | |||
1344 | "unknown class-specific control req " | 1345 | "unknown class-specific control req " |
1345 | "%02x.%02x v%04x i%04x l%u\n", | 1346 | "%02x.%02x v%04x i%04x l%u\n", |
1346 | ctrl->bRequestType, ctrl->bRequest, | 1347 | ctrl->bRequestType, ctrl->bRequest, |
1347 | ctrl->wValue, w_index, w_length); | 1348 | le16_to_cpu(ctrl->wValue), w_index, w_length); |
1348 | return value; | 1349 | return value; |
1349 | } | 1350 | } |
1350 | 1351 | ||
@@ -1358,9 +1359,8 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1358 | { | 1359 | { |
1359 | struct usb_request *req = fsg->ep0req; | 1360 | struct usb_request *req = fsg->ep0req; |
1360 | int value = -EOPNOTSUPP; | 1361 | int value = -EOPNOTSUPP; |
1361 | u16 w_index = ctrl->wIndex; | 1362 | u16 w_index = le16_to_cpu(ctrl->wIndex); |
1362 | u16 w_value = ctrl->wValue; | 1363 | u16 w_value = le16_to_cpu(ctrl->wValue); |
1363 | u16 w_length = ctrl->wLength; | ||
1364 | 1364 | ||
1365 | /* Usually this just stores reply data in the pre-allocated ep0 buffer, | 1365 | /* Usually this just stores reply data in the pre-allocated ep0 buffer, |
1366 | * but config change events will also reconfigure hardware. */ | 1366 | * but config change events will also reconfigure hardware. */ |
@@ -1374,7 +1374,7 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1374 | 1374 | ||
1375 | case USB_DT_DEVICE: | 1375 | case USB_DT_DEVICE: |
1376 | VDBG(fsg, "get device descriptor\n"); | 1376 | VDBG(fsg, "get device descriptor\n"); |
1377 | value = min(w_length, (u16) sizeof device_desc); | 1377 | value = sizeof device_desc; |
1378 | memcpy(req->buf, &device_desc, value); | 1378 | memcpy(req->buf, &device_desc, value); |
1379 | break; | 1379 | break; |
1380 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1380 | #ifdef CONFIG_USB_GADGET_DUALSPEED |
@@ -1382,7 +1382,7 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1382 | VDBG(fsg, "get device qualifier\n"); | 1382 | VDBG(fsg, "get device qualifier\n"); |
1383 | if (!fsg->gadget->is_dualspeed) | 1383 | if (!fsg->gadget->is_dualspeed) |
1384 | break; | 1384 | break; |
1385 | value = min(w_length, (u16) sizeof dev_qualifier); | 1385 | value = sizeof dev_qualifier; |
1386 | memcpy(req->buf, &dev_qualifier, value); | 1386 | memcpy(req->buf, &dev_qualifier, value); |
1387 | break; | 1387 | break; |
1388 | 1388 | ||
@@ -1401,8 +1401,6 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1401 | req->buf, | 1401 | req->buf, |
1402 | w_value >> 8, | 1402 | w_value >> 8, |
1403 | w_value & 0xff); | 1403 | w_value & 0xff); |
1404 | if (value >= 0) | ||
1405 | value = min(w_length, (u16) value); | ||
1406 | break; | 1404 | break; |
1407 | 1405 | ||
1408 | case USB_DT_STRING: | 1406 | case USB_DT_STRING: |
@@ -1411,8 +1409,6 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1411 | /* wIndex == language code */ | 1409 | /* wIndex == language code */ |
1412 | value = usb_gadget_get_string(&stringtab, | 1410 | value = usb_gadget_get_string(&stringtab, |
1413 | w_value & 0xff, req->buf); | 1411 | w_value & 0xff, req->buf); |
1414 | if (value >= 0) | ||
1415 | value = min(w_length, (u16) value); | ||
1416 | break; | 1412 | break; |
1417 | } | 1413 | } |
1418 | break; | 1414 | break; |
@@ -1438,7 +1434,7 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1438 | break; | 1434 | break; |
1439 | VDBG(fsg, "get configuration\n"); | 1435 | VDBG(fsg, "get configuration\n"); |
1440 | *(u8 *) req->buf = fsg->config; | 1436 | *(u8 *) req->buf = fsg->config; |
1441 | value = min(w_length, (u16) 1); | 1437 | value = 1; |
1442 | break; | 1438 | break; |
1443 | 1439 | ||
1444 | case USB_REQ_SET_INTERFACE: | 1440 | case USB_REQ_SET_INTERFACE: |
@@ -1466,14 +1462,14 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1466 | } | 1462 | } |
1467 | VDBG(fsg, "get interface\n"); | 1463 | VDBG(fsg, "get interface\n"); |
1468 | *(u8 *) req->buf = 0; | 1464 | *(u8 *) req->buf = 0; |
1469 | value = min(w_length, (u16) 1); | 1465 | value = 1; |
1470 | break; | 1466 | break; |
1471 | 1467 | ||
1472 | default: | 1468 | default: |
1473 | VDBG(fsg, | 1469 | VDBG(fsg, |
1474 | "unknown control req %02x.%02x v%04x i%04x l%u\n", | 1470 | "unknown control req %02x.%02x v%04x i%04x l%u\n", |
1475 | ctrl->bRequestType, ctrl->bRequest, | 1471 | ctrl->bRequestType, ctrl->bRequest, |
1476 | w_value, w_index, w_length); | 1472 | w_value, w_index, le16_to_cpu(ctrl->wLength)); |
1477 | } | 1473 | } |
1478 | 1474 | ||
1479 | return value; | 1475 | return value; |
@@ -1485,6 +1481,7 @@ static int fsg_setup(struct usb_gadget *gadget, | |||
1485 | { | 1481 | { |
1486 | struct fsg_dev *fsg = get_gadget_data(gadget); | 1482 | struct fsg_dev *fsg = get_gadget_data(gadget); |
1487 | int rc; | 1483 | int rc; |
1484 | int w_length = le16_to_cpu(ctrl->wLength); | ||
1488 | 1485 | ||
1489 | ++fsg->ep0_req_tag; // Record arrival of a new request | 1486 | ++fsg->ep0_req_tag; // Record arrival of a new request |
1490 | fsg->ep0req->context = NULL; | 1487 | fsg->ep0req->context = NULL; |
@@ -1498,9 +1495,9 @@ static int fsg_setup(struct usb_gadget *gadget, | |||
1498 | 1495 | ||
1499 | /* Respond with data/status or defer until later? */ | 1496 | /* Respond with data/status or defer until later? */ |
1500 | if (rc >= 0 && rc != DELAYED_STATUS) { | 1497 | if (rc >= 0 && rc != DELAYED_STATUS) { |
1498 | rc = min(rc, w_length); | ||
1501 | fsg->ep0req->length = rc; | 1499 | fsg->ep0req->length = rc; |
1502 | fsg->ep0req->zero = (rc < ctrl->wLength && | 1500 | fsg->ep0req->zero = rc < w_length; |
1503 | (rc % gadget->ep0->maxpacket) == 0); | ||
1504 | fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? | 1501 | fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? |
1505 | "ep0-in" : "ep0-out"); | 1502 | "ep0-in" : "ep0-out"); |
1506 | rc = ep0_queue(fsg); | 1503 | rc = ep0_queue(fsg); |
@@ -2660,7 +2657,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, | |||
2660 | } | 2657 | } |
2661 | } | 2658 | } |
2662 | 2659 | ||
2663 | /* Check that the LUN values are oonsistent */ | 2660 | /* Check that the LUN values are consistent */ |
2664 | if (transport_is_bbb()) { | 2661 | if (transport_is_bbb()) { |
2665 | if (fsg->lun != lun) | 2662 | if (fsg->lun != lun) |
2666 | DBG(fsg, "using LUN %d from CBW, " | 2663 | DBG(fsg, "using LUN %d from CBW, " |
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 005db7cca292..ed773a9111de 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
@@ -70,7 +70,7 @@ MODULE_LICENSE("GPL"); | |||
70 | * seem to behave quite as expected. Used by default. | 70 | * seem to behave quite as expected. Used by default. |
71 | * | 71 | * |
72 | * OUT dma documents design problems handling the common "short packet" | 72 | * OUT dma documents design problems handling the common "short packet" |
73 | * transfer termination policy; it couldn't enabled by default, even | 73 | * transfer termination policy; it couldn't be enabled by default, even |
74 | * if the OUT-dma abort problems had a resolution. | 74 | * if the OUT-dma abort problems had a resolution. |
75 | */ | 75 | */ |
76 | static unsigned use_dma = 1; | 76 | static unsigned use_dma = 1; |
@@ -313,7 +313,7 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req) | |||
313 | #if defined(CONFIG_X86) | 313 | #if defined(CONFIG_X86) |
314 | #define USE_KMALLOC | 314 | #define USE_KMALLOC |
315 | 315 | ||
316 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_NONCOHERENT_IO) | 316 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT) |
317 | #define USE_KMALLOC | 317 | #define USE_KMALLOC |
318 | 318 | ||
319 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) | 319 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) |
@@ -1524,9 +1524,12 @@ static void ep0_setup(struct goku_udc *dev) | |||
1524 | /* read SETUP packet and enter DATA stage */ | 1524 | /* read SETUP packet and enter DATA stage */ |
1525 | ctrl.bRequestType = readl(®s->bRequestType); | 1525 | ctrl.bRequestType = readl(®s->bRequestType); |
1526 | ctrl.bRequest = readl(®s->bRequest); | 1526 | ctrl.bRequest = readl(®s->bRequest); |
1527 | ctrl.wValue = (readl(®s->wValueH) << 8) | readl(®s->wValueL); | 1527 | ctrl.wValue = cpu_to_le16((readl(®s->wValueH) << 8) |
1528 | ctrl.wIndex = (readl(®s->wIndexH) << 8) | readl(®s->wIndexL); | 1528 | | readl(®s->wValueL)); |
1529 | ctrl.wLength = (readl(®s->wLengthH) << 8) | readl(®s->wLengthL); | 1529 | ctrl.wIndex = cpu_to_le16((readl(®s->wIndexH) << 8) |
1530 | | readl(®s->wIndexL)); | ||
1531 | ctrl.wLength = cpu_to_le16((readl(®s->wLengthH) << 8) | ||
1532 | | readl(®s->wLengthL)); | ||
1530 | writel(0, ®s->SetupRecv); | 1533 | writel(0, ®s->SetupRecv); |
1531 | 1534 | ||
1532 | nuke(&dev->ep[0], 0); | 1535 | nuke(&dev->ep[0], 0); |
@@ -1548,18 +1551,20 @@ static void ep0_setup(struct goku_udc *dev) | |||
1548 | case USB_REQ_CLEAR_FEATURE: | 1551 | case USB_REQ_CLEAR_FEATURE: |
1549 | switch (ctrl.bRequestType) { | 1552 | switch (ctrl.bRequestType) { |
1550 | case USB_RECIP_ENDPOINT: | 1553 | case USB_RECIP_ENDPOINT: |
1551 | tmp = ctrl.wIndex & 0x0f; | 1554 | tmp = le16_to_cpu(ctrl.wIndex) & 0x0f; |
1552 | /* active endpoint */ | 1555 | /* active endpoint */ |
1553 | if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0)) | 1556 | if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0)) |
1554 | goto stall; | 1557 | goto stall; |
1555 | if (ctrl.wIndex & USB_DIR_IN) { | 1558 | if (ctrl.wIndex & __constant_cpu_to_le16( |
1559 | USB_DIR_IN)) { | ||
1556 | if (!dev->ep[tmp].is_in) | 1560 | if (!dev->ep[tmp].is_in) |
1557 | goto stall; | 1561 | goto stall; |
1558 | } else { | 1562 | } else { |
1559 | if (dev->ep[tmp].is_in) | 1563 | if (dev->ep[tmp].is_in) |
1560 | goto stall; | 1564 | goto stall; |
1561 | } | 1565 | } |
1562 | if (ctrl.wValue != USB_ENDPOINT_HALT) | 1566 | if (ctrl.wValue != __constant_cpu_to_le16( |
1567 | USB_ENDPOINT_HALT)) | ||
1563 | goto stall; | 1568 | goto stall; |
1564 | if (tmp) | 1569 | if (tmp) |
1565 | goku_clear_halt(&dev->ep[tmp]); | 1570 | goku_clear_halt(&dev->ep[tmp]); |
@@ -1571,7 +1576,7 @@ succeed: | |||
1571 | return; | 1576 | return; |
1572 | case USB_RECIP_DEVICE: | 1577 | case USB_RECIP_DEVICE: |
1573 | /* device remote wakeup: always clear */ | 1578 | /* device remote wakeup: always clear */ |
1574 | if (ctrl.wValue != 1) | 1579 | if (ctrl.wValue != __constant_cpu_to_le16(1)) |
1575 | goto stall; | 1580 | goto stall; |
1576 | VDBG(dev, "clear dev remote wakeup\n"); | 1581 | VDBG(dev, "clear dev remote wakeup\n"); |
1577 | goto succeed; | 1582 | goto succeed; |
@@ -1589,14 +1594,15 @@ succeed: | |||
1589 | #ifdef USB_TRACE | 1594 | #ifdef USB_TRACE |
1590 | VDBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", | 1595 | VDBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", |
1591 | ctrl.bRequestType, ctrl.bRequest, | 1596 | ctrl.bRequestType, ctrl.bRequest, |
1592 | ctrl.wValue, ctrl.wIndex, ctrl.wLength); | 1597 | le16_to_cpu(ctrl.wValue), le16_to_cpu(ctrl.wIndex), |
1598 | le16_to_cpu(ctrl.wLength)); | ||
1593 | #endif | 1599 | #endif |
1594 | 1600 | ||
1595 | /* hw wants to know when we're configured (or not) */ | 1601 | /* hw wants to know when we're configured (or not) */ |
1596 | dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION | 1602 | dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION |
1597 | && ctrl.bRequestType == USB_RECIP_DEVICE); | 1603 | && ctrl.bRequestType == USB_RECIP_DEVICE); |
1598 | if (unlikely(dev->req_config)) | 1604 | if (unlikely(dev->req_config)) |
1599 | dev->configured = (ctrl.wValue != 0); | 1605 | dev->configured = (ctrl.wValue != __constant_cpu_to_le16(0)); |
1600 | 1606 | ||
1601 | /* delegate everything to the gadget driver. | 1607 | /* delegate everything to the gadget driver. |
1602 | * it may respond after this irq handler returns. | 1608 | * it may respond after this irq handler returns. |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 1e5e6ddef787..020815397a49 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -417,8 +417,8 @@ ep_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) | |||
417 | goto free1; | 417 | goto free1; |
418 | 418 | ||
419 | value = ep_io (data, kbuf, len); | 419 | value = ep_io (data, kbuf, len); |
420 | VDEBUG (data->dev, "%s read %d OUT, status %d\n", | 420 | VDEBUG (data->dev, "%s read %zu OUT, status %d\n", |
421 | data->name, len, value); | 421 | data->name, len, (int) value); |
422 | if (value >= 0 && copy_to_user (buf, kbuf, value)) | 422 | if (value >= 0 && copy_to_user (buf, kbuf, value)) |
423 | value = -EFAULT; | 423 | value = -EFAULT; |
424 | 424 | ||
@@ -465,8 +465,8 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
465 | } | 465 | } |
466 | 466 | ||
467 | value = ep_io (data, kbuf, len); | 467 | value = ep_io (data, kbuf, len); |
468 | VDEBUG (data->dev, "%s write %d IN, status %d\n", | 468 | VDEBUG (data->dev, "%s write %zu IN, status %d\n", |
469 | data->name, len, value); | 469 | data->name, len, (int) value); |
470 | free1: | 470 | free1: |
471 | up (&data->lock); | 471 | up (&data->lock); |
472 | kfree (kbuf); | 472 | kfree (kbuf); |
@@ -1318,8 +1318,8 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1318 | struct usb_request *req = dev->req; | 1318 | struct usb_request *req = dev->req; |
1319 | int value = -EOPNOTSUPP; | 1319 | int value = -EOPNOTSUPP; |
1320 | struct usb_gadgetfs_event *event; | 1320 | struct usb_gadgetfs_event *event; |
1321 | u16 w_value = ctrl->wValue; | 1321 | u16 w_value = le16_to_cpu(ctrl->wValue); |
1322 | u16 w_length = ctrl->wLength; | 1322 | u16 w_length = le16_to_cpu(ctrl->wLength); |
1323 | 1323 | ||
1324 | spin_lock (&dev->lock); | 1324 | spin_lock (&dev->lock); |
1325 | dev->setup_abort = 0; | 1325 | dev->setup_abort = 0; |
diff --git a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/ndis.h index c553bbf68cab..09e3ee4eeae1 100644 --- a/drivers/usb/gadget/ndis.h +++ b/drivers/usb/gadget/ndis.h | |||
@@ -47,17 +47,17 @@ struct NDIS_PM_WAKE_UP_CAPABILITIES { | |||
47 | #define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 | 47 | #define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 |
48 | 48 | ||
49 | struct NDIS_PNP_CAPABILITIES { | 49 | struct NDIS_PNP_CAPABILITIES { |
50 | u32 Flags; | 50 | __le32 Flags; |
51 | struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; | 51 | struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | struct NDIS_PM_PACKET_PATTERN { | 54 | struct NDIS_PM_PACKET_PATTERN { |
55 | u32 Priority; | 55 | __le32 Priority; |
56 | u32 Reserved; | 56 | __le32 Reserved; |
57 | u32 MaskSize; | 57 | __le32 MaskSize; |
58 | u32 PatternOffset; | 58 | __le32 PatternOffset; |
59 | u32 PatternSize; | 59 | __le32 PatternSize; |
60 | u32 PatternFlags; | 60 | __le32 PatternFlags; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | 63 | ||
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index e47e398daeb5..13a3dbc9949b 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -448,7 +448,7 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req) | |||
448 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) | 448 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) |
449 | #define USE_KMALLOC | 449 | #define USE_KMALLOC |
450 | 450 | ||
451 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_NONCOHERENT_IO) | 451 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT) |
452 | #define USE_KMALLOC | 452 | #define USE_KMALLOC |
453 | 453 | ||
454 | /* FIXME there are other cases, including an x86-64 one ... */ | 454 | /* FIXME there are other cases, including an x86-64 one ... */ |
@@ -1113,7 +1113,7 @@ static void restart_dma (struct net2280_ep *ep) | |||
1113 | if (ep->in_fifo_validate) | 1113 | if (ep->in_fifo_validate) |
1114 | dmactl |= (1 << DMA_FIFO_VALIDATE); | 1114 | dmactl |= (1 << DMA_FIFO_VALIDATE); |
1115 | list_for_each_entry (entry, &ep->queue, queue) { | 1115 | list_for_each_entry (entry, &ep->queue, queue) { |
1116 | u32 dmacount; | 1116 | __le32 dmacount; |
1117 | 1117 | ||
1118 | if (entry == req) | 1118 | if (entry == req) |
1119 | continue; | 1119 | continue; |
@@ -1238,7 +1238,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req) | |||
1238 | &ep->dma->dmadesc); | 1238 | &ep->dma->dmadesc); |
1239 | if (req->td->dmacount & dma_done_ie) | 1239 | if (req->td->dmacount & dma_done_ie) |
1240 | writel (readl (&ep->dma->dmacount) | 1240 | writel (readl (&ep->dma->dmacount) |
1241 | | dma_done_ie, | 1241 | | le32_to_cpu(dma_done_ie), |
1242 | &ep->dma->dmacount); | 1242 | &ep->dma->dmacount); |
1243 | } else { | 1243 | } else { |
1244 | struct net2280_request *prev; | 1244 | struct net2280_request *prev; |
@@ -1779,6 +1779,9 @@ static void set_fifo_mode (struct net2280 *dev, int mode) | |||
1779 | list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list); | 1779 | list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list); |
1780 | } | 1780 | } |
1781 | 1781 | ||
1782 | /* just declare this in any driver that really need it */ | ||
1783 | extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); | ||
1784 | |||
1782 | /** | 1785 | /** |
1783 | * net2280_set_fifo_mode - change allocation of fifo buffers | 1786 | * net2280_set_fifo_mode - change allocation of fifo buffers |
1784 | * @gadget: access to the net2280 device that will be updated | 1787 | * @gadget: access to the net2280 device that will be updated |
@@ -2382,9 +2385,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2382 | cpu_to_le32s (&u.raw [0]); | 2385 | cpu_to_le32s (&u.raw [0]); |
2383 | cpu_to_le32s (&u.raw [1]); | 2386 | cpu_to_le32s (&u.raw [1]); |
2384 | 2387 | ||
2385 | le16_to_cpus (&u.r.wValue); | 2388 | #define w_value le16_to_cpup (&u.r.wValue) |
2386 | le16_to_cpus (&u.r.wIndex); | 2389 | #define w_index le16_to_cpup (&u.r.wIndex) |
2387 | le16_to_cpus (&u.r.wLength); | 2390 | #define w_length le16_to_cpup (&u.r.wLength) |
2388 | 2391 | ||
2389 | /* ack the irq */ | 2392 | /* ack the irq */ |
2390 | writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0); | 2393 | writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0); |
@@ -2413,25 +2416,25 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2413 | switch (u.r.bRequest) { | 2416 | switch (u.r.bRequest) { |
2414 | case USB_REQ_GET_STATUS: { | 2417 | case USB_REQ_GET_STATUS: { |
2415 | struct net2280_ep *e; | 2418 | struct net2280_ep *e; |
2416 | u16 status; | 2419 | __le32 status; |
2417 | 2420 | ||
2418 | /* hw handles device and interface status */ | 2421 | /* hw handles device and interface status */ |
2419 | if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT)) | 2422 | if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT)) |
2420 | goto delegate; | 2423 | goto delegate; |
2421 | if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0 | 2424 | if ((e = get_ep_by_addr (dev, w_index)) == 0 |
2422 | || u.r.wLength > 2) | 2425 | || w_length > 2) |
2423 | goto do_stall; | 2426 | goto do_stall; |
2424 | 2427 | ||
2425 | if (readl (&e->regs->ep_rsp) | 2428 | if (readl (&e->regs->ep_rsp) |
2426 | & (1 << SET_ENDPOINT_HALT)) | 2429 | & (1 << SET_ENDPOINT_HALT)) |
2427 | status = __constant_cpu_to_le16 (1); | 2430 | status = __constant_cpu_to_le32 (1); |
2428 | else | 2431 | else |
2429 | status = __constant_cpu_to_le16 (0); | 2432 | status = __constant_cpu_to_le32 (0); |
2430 | 2433 | ||
2431 | /* don't bother with a request object! */ | 2434 | /* don't bother with a request object! */ |
2432 | writel (0, &dev->epregs [0].ep_irqenb); | 2435 | writel (0, &dev->epregs [0].ep_irqenb); |
2433 | set_fifo_bytecount (ep, u.r.wLength); | 2436 | set_fifo_bytecount (ep, w_length); |
2434 | writel (status, &dev->epregs [0].ep_data); | 2437 | writel ((__force u32)status, &dev->epregs [0].ep_data); |
2435 | allow_status (ep); | 2438 | allow_status (ep); |
2436 | VDEBUG (dev, "%s stat %02x\n", ep->ep.name, status); | 2439 | VDEBUG (dev, "%s stat %02x\n", ep->ep.name, status); |
2437 | goto next_endpoints; | 2440 | goto next_endpoints; |
@@ -2443,10 +2446,10 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2443 | /* hw handles device features */ | 2446 | /* hw handles device features */ |
2444 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) | 2447 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) |
2445 | goto delegate; | 2448 | goto delegate; |
2446 | if (u.r.wValue != USB_ENDPOINT_HALT | 2449 | if (w_value != USB_ENDPOINT_HALT |
2447 | || u.r.wLength != 0) | 2450 | || w_length != 0) |
2448 | goto do_stall; | 2451 | goto do_stall; |
2449 | if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0) | 2452 | if ((e = get_ep_by_addr (dev, w_index)) == 0) |
2450 | goto do_stall; | 2453 | goto do_stall; |
2451 | clear_halt (e); | 2454 | clear_halt (e); |
2452 | allow_status (ep); | 2455 | allow_status (ep); |
@@ -2460,10 +2463,10 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2460 | /* hw handles device features */ | 2463 | /* hw handles device features */ |
2461 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) | 2464 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) |
2462 | goto delegate; | 2465 | goto delegate; |
2463 | if (u.r.wValue != USB_ENDPOINT_HALT | 2466 | if (w_value != USB_ENDPOINT_HALT |
2464 | || u.r.wLength != 0) | 2467 | || w_length != 0) |
2465 | goto do_stall; | 2468 | goto do_stall; |
2466 | if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0) | 2469 | if ((e = get_ep_by_addr (dev, w_index)) == 0) |
2467 | goto do_stall; | 2470 | goto do_stall; |
2468 | set_halt (e); | 2471 | set_halt (e); |
2469 | allow_status (ep); | 2472 | allow_status (ep); |
@@ -2473,10 +2476,10 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2473 | break; | 2476 | break; |
2474 | default: | 2477 | default: |
2475 | delegate: | 2478 | delegate: |
2476 | VDEBUG (dev, "setup %02x.%02x v%04x i%04x " | 2479 | VDEBUG (dev, "setup %02x.%02x v%04x i%04x l%04x" |
2477 | "ep_cfg %08x\n", | 2480 | "ep_cfg %08x\n", |
2478 | u.r.bRequestType, u.r.bRequest, | 2481 | u.r.bRequestType, u.r.bRequest, |
2479 | u.r.wValue, u.r.wIndex, | 2482 | w_value, w_index, w_length, |
2480 | readl (&ep->regs->ep_cfg)); | 2483 | readl (&ep->regs->ep_cfg)); |
2481 | spin_unlock (&dev->lock); | 2484 | spin_unlock (&dev->lock); |
2482 | tmp = dev->driver->setup (&dev->gadget, &u.r); | 2485 | tmp = dev->driver->setup (&dev->gadget, &u.r); |
@@ -2497,6 +2500,10 @@ do_stall: | |||
2497 | */ | 2500 | */ |
2498 | } | 2501 | } |
2499 | 2502 | ||
2503 | #undef w_value | ||
2504 | #undef w_index | ||
2505 | #undef w_length | ||
2506 | |||
2500 | next_endpoints: | 2507 | next_endpoints: |
2501 | /* endpoint data irq ? */ | 2508 | /* endpoint data irq ? */ |
2502 | scratch = stat & 0x7f; | 2509 | scratch = stat & 0x7f; |
@@ -2653,7 +2660,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) | |||
2653 | restart_dma (ep); | 2660 | restart_dma (ep); |
2654 | else if (ep->is_in && use_dma_chaining) { | 2661 | else if (ep->is_in && use_dma_chaining) { |
2655 | struct net2280_request *req; | 2662 | struct net2280_request *req; |
2656 | u32 dmacount; | 2663 | __le32 dmacount; |
2657 | 2664 | ||
2658 | /* the descriptor at the head of the chain | 2665 | /* the descriptor at the head of the chain |
2659 | * may still have VALID_BIT clear; that's | 2666 | * may still have VALID_BIT clear; that's |
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 98cbcbc16cc1..a2b812af6e66 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <asm/mach-types.h> | 52 | #include <asm/mach-types.h> |
53 | 53 | ||
54 | #include <asm/arch/dma.h> | 54 | #include <asm/arch/dma.h> |
55 | #include <asm/arch/mux.h> | ||
56 | #include <asm/arch/usb.h> | 55 | #include <asm/arch/usb.h> |
57 | 56 | ||
58 | #include "omap_udc.h" | 57 | #include "omap_udc.h" |
@@ -167,7 +166,7 @@ static int omap_ep_enable(struct usb_ep *_ep, | |||
167 | maxp = le16_to_cpu (desc->wMaxPacketSize); | 166 | maxp = le16_to_cpu (desc->wMaxPacketSize); |
168 | if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK | 167 | if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK |
169 | && maxp != ep->maxpacket) | 168 | && maxp != ep->maxpacket) |
170 | || desc->wMaxPacketSize > ep->maxpacket | 169 | || le16_to_cpu(desc->wMaxPacketSize) > ep->maxpacket |
171 | || !desc->wMaxPacketSize) { | 170 | || !desc->wMaxPacketSize) { |
172 | DBG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name); | 171 | DBG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name); |
173 | return -ERANGE; | 172 | return -ERANGE; |
@@ -214,7 +213,7 @@ static int omap_ep_enable(struct usb_ep *_ep, | |||
214 | ep->has_dma = 0; | 213 | ep->has_dma = 0; |
215 | ep->lch = -1; | 214 | ep->lch = -1; |
216 | use_ep(ep, UDC_EP_SEL); | 215 | use_ep(ep, UDC_EP_SEL); |
217 | UDC_CTRL_REG = UDC_RESET_EP; | 216 | UDC_CTRL_REG = udc->clr_halt; |
218 | ep->ackwait = 0; | 217 | ep->ackwait = 0; |
219 | deselect_ep(); | 218 | deselect_ep(); |
220 | 219 | ||
@@ -253,7 +252,7 @@ static int omap_ep_disable(struct usb_ep *_ep) | |||
253 | } | 252 | } |
254 | 253 | ||
255 | spin_lock_irqsave(&ep->udc->lock, flags); | 254 | spin_lock_irqsave(&ep->udc->lock, flags); |
256 | ep->desc = 0; | 255 | ep->desc = NULL; |
257 | nuke (ep, -ESHUTDOWN); | 256 | nuke (ep, -ESHUTDOWN); |
258 | ep->ep.maxpacket = ep->maxpacket; | 257 | ep->ep.maxpacket = ep->maxpacket; |
259 | ep->has_dma = 0; | 258 | ep->has_dma = 0; |
@@ -388,8 +387,8 @@ done(struct omap_ep *ep, struct omap_req *req, int status) | |||
388 | 387 | ||
389 | /*-------------------------------------------------------------------------*/ | 388 | /*-------------------------------------------------------------------------*/ |
390 | 389 | ||
391 | #define FIFO_FULL (UDC_NON_ISO_FIFO_FULL | UDC_ISO_FIFO_FULL) | 390 | #define UDC_FIFO_FULL (UDC_NON_ISO_FIFO_FULL | UDC_ISO_FIFO_FULL) |
392 | #define FIFO_UNWRITABLE (UDC_EP_HALTED | FIFO_FULL) | 391 | #define UDC_FIFO_UNWRITABLE (UDC_EP_HALTED | UDC_FIFO_FULL) |
393 | 392 | ||
394 | #define FIFO_EMPTY (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY) | 393 | #define FIFO_EMPTY (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY) |
395 | #define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY) | 394 | #define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY) |
@@ -433,7 +432,7 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req) | |||
433 | 432 | ||
434 | /* PIO-IN isn't double buffered except for iso */ | 433 | /* PIO-IN isn't double buffered except for iso */ |
435 | ep_stat = UDC_STAT_FLG_REG; | 434 | ep_stat = UDC_STAT_FLG_REG; |
436 | if (ep_stat & FIFO_UNWRITABLE) | 435 | if (ep_stat & UDC_FIFO_UNWRITABLE) |
437 | return 0; | 436 | return 0; |
438 | 437 | ||
439 | count = ep->ep.maxpacket; | 438 | count = ep->ep.maxpacket; |
@@ -504,7 +503,7 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) | |||
504 | if (ep_stat & UDC_EP_HALTED) | 503 | if (ep_stat & UDC_EP_HALTED) |
505 | break; | 504 | break; |
506 | 505 | ||
507 | if (ep_stat & FIFO_FULL) | 506 | if (ep_stat & UDC_FIFO_FULL) |
508 | avail = ep->ep.maxpacket; | 507 | avail = ep->ep.maxpacket; |
509 | else { | 508 | else { |
510 | avail = UDC_RXFSTAT_REG; | 509 | avail = UDC_RXFSTAT_REG; |
@@ -538,6 +537,32 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) | |||
538 | 537 | ||
539 | /*-------------------------------------------------------------------------*/ | 538 | /*-------------------------------------------------------------------------*/ |
540 | 539 | ||
540 | static inline dma_addr_t dma_csac(unsigned lch) | ||
541 | { | ||
542 | dma_addr_t csac; | ||
543 | |||
544 | /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is | ||
545 | * read before the DMA controller finished disabling the channel. | ||
546 | */ | ||
547 | csac = omap_readw(OMAP_DMA_CSAC(lch)); | ||
548 | if (csac == 0) | ||
549 | csac = omap_readw(OMAP_DMA_CSAC(lch)); | ||
550 | return csac; | ||
551 | } | ||
552 | |||
553 | static inline dma_addr_t dma_cdac(unsigned lch) | ||
554 | { | ||
555 | dma_addr_t cdac; | ||
556 | |||
557 | /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is | ||
558 | * read before the DMA controller finished disabling the channel. | ||
559 | */ | ||
560 | cdac = omap_readw(OMAP_DMA_CDAC(lch)); | ||
561 | if (cdac == 0) | ||
562 | cdac = omap_readw(OMAP_DMA_CDAC(lch)); | ||
563 | return cdac; | ||
564 | } | ||
565 | |||
541 | static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) | 566 | static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) |
542 | { | 567 | { |
543 | dma_addr_t end; | 568 | dma_addr_t end; |
@@ -548,7 +573,7 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) | |||
548 | if (cpu_is_omap15xx()) | 573 | if (cpu_is_omap15xx()) |
549 | return 0; | 574 | return 0; |
550 | 575 | ||
551 | end = omap_readw(OMAP_DMA_CSAC(ep->lch)); | 576 | end = dma_csac(ep->lch); |
552 | if (end == ep->dma_counter) | 577 | if (end == ep->dma_counter) |
553 | return 0; | 578 | return 0; |
554 | 579 | ||
@@ -559,14 +584,14 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) | |||
559 | } | 584 | } |
560 | 585 | ||
561 | #define DMA_DEST_LAST(x) (cpu_is_omap15xx() \ | 586 | #define DMA_DEST_LAST(x) (cpu_is_omap15xx() \ |
562 | ? OMAP_DMA_CSAC(x) /* really: CPC */ \ | 587 | ? omap_readw(OMAP_DMA_CSAC(x)) /* really: CPC */ \ |
563 | : OMAP_DMA_CDAC(x)) | 588 | : dma_cdac(x)) |
564 | 589 | ||
565 | static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start) | 590 | static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start) |
566 | { | 591 | { |
567 | dma_addr_t end; | 592 | dma_addr_t end; |
568 | 593 | ||
569 | end = omap_readw(DMA_DEST_LAST(ep->lch)); | 594 | end = DMA_DEST_LAST(ep->lch); |
570 | if (end == ep->dma_counter) | 595 | if (end == ep->dma_counter) |
571 | return 0; | 596 | return 0; |
572 | 597 | ||
@@ -593,7 +618,7 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) | |||
593 | : OMAP_DMA_SYNC_ELEMENT; | 618 | : OMAP_DMA_SYNC_ELEMENT; |
594 | 619 | ||
595 | /* measure length in either bytes or packets */ | 620 | /* measure length in either bytes or packets */ |
596 | if ((cpu_is_omap16xx() && length <= (UDC_TXN_TSC + 1)) | 621 | if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC) |
597 | || (cpu_is_omap15xx() && length < ep->maxpacket)) { | 622 | || (cpu_is_omap15xx() && length < ep->maxpacket)) { |
598 | txdma_ctrl = UDC_TXN_EOT | length; | 623 | txdma_ctrl = UDC_TXN_EOT | length; |
599 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, | 624 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, |
@@ -602,15 +627,15 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) | |||
602 | length = min(length / ep->maxpacket, | 627 | length = min(length / ep->maxpacket, |
603 | (unsigned) UDC_TXN_TSC + 1); | 628 | (unsigned) UDC_TXN_TSC + 1); |
604 | txdma_ctrl = length; | 629 | txdma_ctrl = length; |
605 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, | 630 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, |
606 | ep->ep.maxpacket, length, sync_mode); | 631 | ep->ep.maxpacket >> 1, length, sync_mode); |
607 | length *= ep->maxpacket; | 632 | length *= ep->maxpacket; |
608 | } | 633 | } |
609 | omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF, | 634 | omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF, |
610 | OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); | 635 | OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); |
611 | 636 | ||
612 | omap_start_dma(ep->lch); | 637 | omap_start_dma(ep->lch); |
613 | ep->dma_counter = omap_readw(OMAP_DMA_CSAC(ep->lch)); | 638 | ep->dma_counter = dma_csac(ep->lch); |
614 | UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel); | 639 | UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel); |
615 | UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl; | 640 | UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl; |
616 | req->dma_bytes = length; | 641 | req->dma_bytes = length; |
@@ -650,12 +675,12 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) | |||
650 | packets = (req->req.length - req->req.actual) / ep->ep.maxpacket; | 675 | packets = (req->req.length - req->req.actual) / ep->ep.maxpacket; |
651 | packets = min(packets, (unsigned)UDC_RXN_TC + 1); | 676 | packets = min(packets, (unsigned)UDC_RXN_TC + 1); |
652 | req->dma_bytes = packets * ep->ep.maxpacket; | 677 | req->dma_bytes = packets * ep->ep.maxpacket; |
653 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, | 678 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, |
654 | ep->ep.maxpacket, packets, | 679 | ep->ep.maxpacket >> 1, packets, |
655 | OMAP_DMA_SYNC_ELEMENT); | 680 | OMAP_DMA_SYNC_ELEMENT); |
656 | omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, | 681 | omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, |
657 | OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); | 682 | OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); |
658 | ep->dma_counter = omap_readw(DMA_DEST_LAST(ep->lch)); | 683 | ep->dma_counter = DMA_DEST_LAST(ep->lch); |
659 | 684 | ||
660 | UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1); | 685 | UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1); |
661 | UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel); | 686 | UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel); |
@@ -763,7 +788,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) | |||
763 | reg = UDC_TXDMA_CFG_REG; | 788 | reg = UDC_TXDMA_CFG_REG; |
764 | else | 789 | else |
765 | reg = UDC_RXDMA_CFG_REG; | 790 | reg = UDC_RXDMA_CFG_REG; |
766 | reg |= 1 << 12; /* "pulse" activated */ | 791 | reg |= UDC_DMA_REQ; /* "pulse" activated */ |
767 | 792 | ||
768 | ep->dma_channel = 0; | 793 | ep->dma_channel = 0; |
769 | ep->lch = -1; | 794 | ep->lch = -1; |
@@ -787,6 +812,11 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) | |||
787 | ep->ep.name, dma_error, ep, &ep->lch); | 812 | ep->ep.name, dma_error, ep, &ep->lch); |
788 | if (status == 0) { | 813 | if (status == 0) { |
789 | UDC_TXDMA_CFG_REG = reg; | 814 | UDC_TXDMA_CFG_REG = reg; |
815 | /* EMIFF */ | ||
816 | omap_set_dma_src_burst_mode(ep->lch, | ||
817 | OMAP_DMA_DATA_BURST_4); | ||
818 | omap_set_dma_src_data_pack(ep->lch, 1); | ||
819 | /* TIPB */ | ||
790 | omap_set_dma_dest_params(ep->lch, | 820 | omap_set_dma_dest_params(ep->lch, |
791 | OMAP_DMA_PORT_TIPB, | 821 | OMAP_DMA_PORT_TIPB, |
792 | OMAP_DMA_AMODE_CONSTANT, | 822 | OMAP_DMA_AMODE_CONSTANT, |
@@ -797,10 +827,15 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) | |||
797 | ep->ep.name, dma_error, ep, &ep->lch); | 827 | ep->ep.name, dma_error, ep, &ep->lch); |
798 | if (status == 0) { | 828 | if (status == 0) { |
799 | UDC_RXDMA_CFG_REG = reg; | 829 | UDC_RXDMA_CFG_REG = reg; |
830 | /* TIPB */ | ||
800 | omap_set_dma_src_params(ep->lch, | 831 | omap_set_dma_src_params(ep->lch, |
801 | OMAP_DMA_PORT_TIPB, | 832 | OMAP_DMA_PORT_TIPB, |
802 | OMAP_DMA_AMODE_CONSTANT, | 833 | OMAP_DMA_AMODE_CONSTANT, |
803 | (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG)); | 834 | (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG)); |
835 | /* EMIFF */ | ||
836 | omap_set_dma_dest_burst_mode(ep->lch, | ||
837 | OMAP_DMA_DATA_BURST_4); | ||
838 | omap_set_dma_dest_data_pack(ep->lch, 1); | ||
804 | } | 839 | } |
805 | } | 840 | } |
806 | if (status) | 841 | if (status) |
@@ -856,7 +891,7 @@ static void dma_channel_release(struct omap_ep *ep) | |||
856 | if (!list_empty(&ep->queue)) | 891 | if (!list_empty(&ep->queue)) |
857 | req = container_of(ep->queue.next, struct omap_req, queue); | 892 | req = container_of(ep->queue.next, struct omap_req, queue); |
858 | else | 893 | else |
859 | req = 0; | 894 | req = NULL; |
860 | 895 | ||
861 | active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0; | 896 | active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0; |
862 | 897 | ||
@@ -865,9 +900,13 @@ static void dma_channel_release(struct omap_ep *ep) | |||
865 | (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r', | 900 | (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r', |
866 | ep->dma_channel - 1, req); | 901 | ep->dma_channel - 1, req); |
867 | 902 | ||
903 | /* NOTE: re-setting RX_REQ/TX_REQ because of a chip bug (before | ||
904 | * OMAP 1710 ES2.0) where reading the DMA_CFG can clear them. | ||
905 | */ | ||
906 | |||
868 | /* wait till current packet DMA finishes, and fifo empties */ | 907 | /* wait till current packet DMA finishes, and fifo empties */ |
869 | if (ep->bEndpointAddress & USB_DIR_IN) { | 908 | if (ep->bEndpointAddress & USB_DIR_IN) { |
870 | UDC_TXDMA_CFG_REG &= ~mask; | 909 | UDC_TXDMA_CFG_REG = (UDC_TXDMA_CFG_REG & ~mask) | UDC_DMA_REQ; |
871 | 910 | ||
872 | if (req) { | 911 | if (req) { |
873 | finish_in_dma(ep, req, -ECONNRESET); | 912 | finish_in_dma(ep, req, -ECONNRESET); |
@@ -880,7 +919,7 @@ static void dma_channel_release(struct omap_ep *ep) | |||
880 | while (UDC_TXDMA_CFG_REG & mask) | 919 | while (UDC_TXDMA_CFG_REG & mask) |
881 | udelay(10); | 920 | udelay(10); |
882 | } else { | 921 | } else { |
883 | UDC_RXDMA_CFG_REG &= ~mask; | 922 | UDC_RXDMA_CFG_REG = (UDC_RXDMA_CFG_REG & ~mask) | UDC_DMA_REQ; |
884 | 923 | ||
885 | /* dma empties the fifo */ | 924 | /* dma empties the fifo */ |
886 | while (UDC_RXDMA_CFG_REG & mask) | 925 | while (UDC_RXDMA_CFG_REG & mask) |
@@ -997,18 +1036,19 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) | |||
997 | UDC_IRQ_EN_REG = irq_en; | 1036 | UDC_IRQ_EN_REG = irq_en; |
998 | } | 1037 | } |
999 | 1038 | ||
1000 | /* STATUS is reverse direction */ | 1039 | /* STATUS for zero length DATA stages is |
1001 | UDC_EP_NUM_REG = is_in | 1040 | * always an IN ... even for IN transfers, |
1002 | ? UDC_EP_SEL | 1041 | * a wierd case which seem to stall OMAP. |
1003 | : (UDC_EP_SEL|UDC_EP_DIR); | 1042 | */ |
1043 | UDC_EP_NUM_REG = (UDC_EP_SEL|UDC_EP_DIR); | ||
1004 | UDC_CTRL_REG = UDC_CLR_EP; | 1044 | UDC_CTRL_REG = UDC_CLR_EP; |
1005 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1045 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
1006 | UDC_EP_NUM_REG = udc->ep0_in ? 0 : UDC_EP_DIR; | 1046 | UDC_EP_NUM_REG = UDC_EP_DIR; |
1007 | 1047 | ||
1008 | /* cleanup */ | 1048 | /* cleanup */ |
1009 | udc->ep0_pending = 0; | 1049 | udc->ep0_pending = 0; |
1010 | done(ep, req, 0); | 1050 | done(ep, req, 0); |
1011 | req = 0; | 1051 | req = NULL; |
1012 | 1052 | ||
1013 | /* non-empty DATA stage */ | 1053 | /* non-empty DATA stage */ |
1014 | } else if (is_in) { | 1054 | } else if (is_in) { |
@@ -1029,7 +1069,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) | |||
1029 | (is_in ? next_in_dma : next_out_dma)(ep, req); | 1069 | (is_in ? next_in_dma : next_out_dma)(ep, req); |
1030 | else if (req) { | 1070 | else if (req) { |
1031 | if ((is_in ? write_fifo : read_fifo)(ep, req) == 1) | 1071 | if ((is_in ? write_fifo : read_fifo)(ep, req) == 1) |
1032 | req = 0; | 1072 | req = NULL; |
1033 | deselect_ep(); | 1073 | deselect_ep(); |
1034 | if (!is_in) { | 1074 | if (!is_in) { |
1035 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1075 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
@@ -1041,7 +1081,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) | |||
1041 | 1081 | ||
1042 | irq_wait: | 1082 | irq_wait: |
1043 | /* irq handler advances the queue */ | 1083 | /* irq handler advances the queue */ |
1044 | if (req != 0) | 1084 | if (req != NULL) |
1045 | list_add_tail(&req->queue, &ep->queue); | 1085 | list_add_tail(&req->queue, &ep->queue); |
1046 | spin_unlock_irqrestore(&udc->lock, flags); | 1086 | spin_unlock_irqrestore(&udc->lock, flags); |
1047 | 1087 | ||
@@ -1140,7 +1180,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) | |||
1140 | dma_channel_claim(ep, channel); | 1180 | dma_channel_claim(ep, channel); |
1141 | } else { | 1181 | } else { |
1142 | use_ep(ep, 0); | 1182 | use_ep(ep, 0); |
1143 | UDC_CTRL_REG = UDC_RESET_EP; | 1183 | UDC_CTRL_REG = ep->udc->clr_halt; |
1144 | ep->ackwait = 0; | 1184 | ep->ackwait = 0; |
1145 | if (!(ep->bEndpointAddress & USB_DIR_IN)) { | 1185 | if (!(ep->bEndpointAddress & USB_DIR_IN)) { |
1146 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1186 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
@@ -1238,6 +1278,8 @@ static int can_pullup(struct omap_udc *udc) | |||
1238 | 1278 | ||
1239 | static void pullup_enable(struct omap_udc *udc) | 1279 | static void pullup_enable(struct omap_udc *udc) |
1240 | { | 1280 | { |
1281 | udc->gadget.dev.parent->power.power_state = PMSG_ON; | ||
1282 | udc->gadget.dev.power.power_state = PMSG_ON; | ||
1241 | UDC_SYSCON1_REG |= UDC_PULLUP_EN; | 1283 | UDC_SYSCON1_REG |= UDC_PULLUP_EN; |
1242 | #ifndef CONFIG_USB_OTG | 1284 | #ifndef CONFIG_USB_OTG |
1243 | if (!cpu_is_omap15xx()) | 1285 | if (!cpu_is_omap15xx()) |
@@ -1382,7 +1424,7 @@ static void update_otg(struct omap_udc *udc) | |||
1382 | static void ep0_irq(struct omap_udc *udc, u16 irq_src) | 1424 | static void ep0_irq(struct omap_udc *udc, u16 irq_src) |
1383 | { | 1425 | { |
1384 | struct omap_ep *ep0 = &udc->ep[0]; | 1426 | struct omap_ep *ep0 = &udc->ep[0]; |
1385 | struct omap_req *req = 0; | 1427 | struct omap_req *req = NULL; |
1386 | 1428 | ||
1387 | ep0->irqs++; | 1429 | ep0->irqs++; |
1388 | 1430 | ||
@@ -1438,7 +1480,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1438 | if (req) | 1480 | if (req) |
1439 | done(ep0, req, 0); | 1481 | done(ep0, req, 0); |
1440 | } | 1482 | } |
1441 | req = 0; | 1483 | req = NULL; |
1442 | } else if (stat & UDC_STALL) { | 1484 | } else if (stat & UDC_STALL) { |
1443 | UDC_CTRL_REG = UDC_CLR_HALT; | 1485 | UDC_CTRL_REG = UDC_CLR_HALT; |
1444 | UDC_EP_NUM_REG = UDC_EP_DIR; | 1486 | UDC_EP_NUM_REG = UDC_EP_DIR; |
@@ -1511,9 +1553,10 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1511 | u.word[3] = UDC_DATA_REG; | 1553 | u.word[3] = UDC_DATA_REG; |
1512 | UDC_EP_NUM_REG = 0; | 1554 | UDC_EP_NUM_REG = 0; |
1513 | } while (UDC_IRQ_SRC_REG & UDC_SETUP); | 1555 | } while (UDC_IRQ_SRC_REG & UDC_SETUP); |
1514 | le16_to_cpus (&u.r.wValue); | 1556 | |
1515 | le16_to_cpus (&u.r.wIndex); | 1557 | #define w_value le16_to_cpup (&u.r.wValue) |
1516 | le16_to_cpus (&u.r.wLength); | 1558 | #define w_index le16_to_cpup (&u.r.wIndex) |
1559 | #define w_length le16_to_cpup (&u.r.wLength) | ||
1517 | 1560 | ||
1518 | /* Delegate almost all control requests to the gadget driver, | 1561 | /* Delegate almost all control requests to the gadget driver, |
1519 | * except for a handful of ch9 status/feature requests that | 1562 | * except for a handful of ch9 status/feature requests that |
@@ -1529,11 +1572,11 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1529 | /* udc needs to know when ep != 0 is valid */ | 1572 | /* udc needs to know when ep != 0 is valid */ |
1530 | if (u.r.bRequestType != USB_RECIP_DEVICE) | 1573 | if (u.r.bRequestType != USB_RECIP_DEVICE) |
1531 | goto delegate; | 1574 | goto delegate; |
1532 | if (u.r.wLength != 0) | 1575 | if (w_length != 0) |
1533 | goto do_stall; | 1576 | goto do_stall; |
1534 | udc->ep0_set_config = 1; | 1577 | udc->ep0_set_config = 1; |
1535 | udc->ep0_reset_config = (u.r.wValue == 0); | 1578 | udc->ep0_reset_config = (w_value == 0); |
1536 | VDBG("set config %d\n", u.r.wValue); | 1579 | VDBG("set config %d\n", w_value); |
1537 | 1580 | ||
1538 | /* update udc NOW since gadget driver may start | 1581 | /* update udc NOW since gadget driver may start |
1539 | * queueing requests immediately; clear config | 1582 | * queueing requests immediately; clear config |
@@ -1549,23 +1592,28 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1549 | /* clear endpoint halt */ | 1592 | /* clear endpoint halt */ |
1550 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) | 1593 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) |
1551 | goto delegate; | 1594 | goto delegate; |
1552 | if (u.r.wValue != USB_ENDPOINT_HALT | 1595 | if (w_value != USB_ENDPOINT_HALT |
1553 | || u.r.wLength != 0) | 1596 | || w_length != 0) |
1554 | goto do_stall; | 1597 | goto do_stall; |
1555 | ep = &udc->ep[u.r.wIndex & 0xf]; | 1598 | ep = &udc->ep[w_index & 0xf]; |
1556 | if (ep != ep0) { | 1599 | if (ep != ep0) { |
1557 | if (u.r.wIndex & USB_DIR_IN) | 1600 | if (w_index & USB_DIR_IN) |
1558 | ep += 16; | 1601 | ep += 16; |
1559 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC | 1602 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC |
1560 | || !ep->desc) | 1603 | || !ep->desc) |
1561 | goto do_stall; | 1604 | goto do_stall; |
1562 | use_ep(ep, 0); | 1605 | use_ep(ep, 0); |
1563 | UDC_CTRL_REG = UDC_RESET_EP; | 1606 | UDC_CTRL_REG = udc->clr_halt; |
1564 | ep->ackwait = 0; | 1607 | ep->ackwait = 0; |
1565 | if (!(ep->bEndpointAddress & USB_DIR_IN)) { | 1608 | if (!(ep->bEndpointAddress & USB_DIR_IN)) { |
1566 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1609 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
1567 | ep->ackwait = 1 + ep->double_buf; | 1610 | ep->ackwait = 1 + ep->double_buf; |
1568 | } | 1611 | } |
1612 | /* NOTE: assumes the host behaves sanely, | ||
1613 | * only clearing real halts. Else we may | ||
1614 | * need to kill pending transfers and then | ||
1615 | * restart the queue... very messy for DMA! | ||
1616 | */ | ||
1569 | } | 1617 | } |
1570 | VDBG("%s halt cleared by host\n", ep->name); | 1618 | VDBG("%s halt cleared by host\n", ep->name); |
1571 | goto ep0out_status_stage; | 1619 | goto ep0out_status_stage; |
@@ -1573,11 +1621,11 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1573 | /* set endpoint halt */ | 1621 | /* set endpoint halt */ |
1574 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) | 1622 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) |
1575 | goto delegate; | 1623 | goto delegate; |
1576 | if (u.r.wValue != USB_ENDPOINT_HALT | 1624 | if (w_value != USB_ENDPOINT_HALT |
1577 | || u.r.wLength != 0) | 1625 | || w_length != 0) |
1578 | goto do_stall; | 1626 | goto do_stall; |
1579 | ep = &udc->ep[u.r.wIndex & 0xf]; | 1627 | ep = &udc->ep[w_index & 0xf]; |
1580 | if (u.r.wIndex & USB_DIR_IN) | 1628 | if (w_index & USB_DIR_IN) |
1581 | ep += 16; | 1629 | ep += 16; |
1582 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC | 1630 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC |
1583 | || ep == ep0 || !ep->desc) | 1631 | || ep == ep0 || !ep->desc) |
@@ -1615,13 +1663,13 @@ ep0out_status_stage: | |||
1615 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1663 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
1616 | UDC_EP_NUM_REG = UDC_EP_DIR; | 1664 | UDC_EP_NUM_REG = UDC_EP_DIR; |
1617 | status = 0; | 1665 | status = 0; |
1618 | VDBG("GET_STATUS, interface %d\n", u.r.wIndex); | 1666 | VDBG("GET_STATUS, interface %d\n", w_index); |
1619 | /* next, status stage */ | 1667 | /* next, status stage */ |
1620 | break; | 1668 | break; |
1621 | default: | 1669 | default: |
1622 | delegate: | 1670 | delegate: |
1623 | /* activate the ep0out fifo right away */ | 1671 | /* activate the ep0out fifo right away */ |
1624 | if (!udc->ep0_in && u.r.wLength) { | 1672 | if (!udc->ep0_in && w_length) { |
1625 | UDC_EP_NUM_REG = 0; | 1673 | UDC_EP_NUM_REG = 0; |
1626 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1674 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
1627 | } | 1675 | } |
@@ -1632,7 +1680,11 @@ delegate: | |||
1632 | */ | 1680 | */ |
1633 | VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n", | 1681 | VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n", |
1634 | u.r.bRequestType, u.r.bRequest, | 1682 | u.r.bRequestType, u.r.bRequest, |
1635 | u.r.wValue, u.r.wIndex, u.r.wLength); | 1683 | w_value, w_index, w_length); |
1684 | |||
1685 | #undef w_value | ||
1686 | #undef w_index | ||
1687 | #undef w_length | ||
1636 | 1688 | ||
1637 | /* The gadget driver may return an error here, | 1689 | /* The gadget driver may return an error here, |
1638 | * causing an immediate protocol stall. | 1690 | * causing an immediate protocol stall. |
@@ -2013,7 +2065,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
2013 | udc->softconnect = 1; | 2065 | udc->softconnect = 1; |
2014 | 2066 | ||
2015 | /* hook up the driver */ | 2067 | /* hook up the driver */ |
2016 | driver->driver.bus = 0; | 2068 | driver->driver.bus = NULL; |
2017 | udc->driver = driver; | 2069 | udc->driver = driver; |
2018 | udc->gadget.dev.driver = &driver->driver; | 2070 | udc->gadget.dev.driver = &driver->driver; |
2019 | spin_unlock_irqrestore(&udc->lock, flags); | 2071 | spin_unlock_irqrestore(&udc->lock, flags); |
@@ -2021,8 +2073,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
2021 | status = driver->bind (&udc->gadget); | 2073 | status = driver->bind (&udc->gadget); |
2022 | if (status) { | 2074 | if (status) { |
2023 | DBG("bind to %s --> %d\n", driver->driver.name, status); | 2075 | DBG("bind to %s --> %d\n", driver->driver.name, status); |
2024 | udc->gadget.dev.driver = 0; | 2076 | udc->gadget.dev.driver = NULL; |
2025 | udc->driver = 0; | 2077 | udc->driver = NULL; |
2026 | goto done; | 2078 | goto done; |
2027 | } | 2079 | } |
2028 | DBG("bound to driver %s\n", driver->driver.name); | 2080 | DBG("bound to driver %s\n", driver->driver.name); |
@@ -2035,8 +2087,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
2035 | if (status < 0) { | 2087 | if (status < 0) { |
2036 | ERR("can't bind to transceiver\n"); | 2088 | ERR("can't bind to transceiver\n"); |
2037 | driver->unbind (&udc->gadget); | 2089 | driver->unbind (&udc->gadget); |
2038 | udc->gadget.dev.driver = 0; | 2090 | udc->gadget.dev.driver = NULL; |
2039 | udc->driver = 0; | 2091 | udc->driver = NULL; |
2040 | goto done; | 2092 | goto done; |
2041 | } | 2093 | } |
2042 | } else { | 2094 | } else { |
@@ -2071,7 +2123,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
2071 | omap_vbus_session(&udc->gadget, 0); | 2123 | omap_vbus_session(&udc->gadget, 0); |
2072 | 2124 | ||
2073 | if (udc->transceiver) | 2125 | if (udc->transceiver) |
2074 | (void) otg_set_peripheral(udc->transceiver, 0); | 2126 | (void) otg_set_peripheral(udc->transceiver, NULL); |
2075 | else | 2127 | else |
2076 | pullup_disable(udc); | 2128 | pullup_disable(udc); |
2077 | 2129 | ||
@@ -2080,9 +2132,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
2080 | spin_unlock_irqrestore(&udc->lock, flags); | 2132 | spin_unlock_irqrestore(&udc->lock, flags); |
2081 | 2133 | ||
2082 | driver->unbind(&udc->gadget); | 2134 | driver->unbind(&udc->gadget); |
2083 | udc->gadget.dev.driver = 0; | 2135 | udc->gadget.dev.driver = NULL; |
2084 | udc->driver = 0; | 2136 | udc->driver = NULL; |
2085 | |||
2086 | 2137 | ||
2087 | DBG("unregistered driver '%s'\n", driver->driver.name); | 2138 | DBG("unregistered driver '%s'\n", driver->driver.name); |
2088 | return status; | 2139 | return status; |
@@ -2178,14 +2229,14 @@ static int proc_otg_show(struct seq_file *s) | |||
2178 | 2229 | ||
2179 | tmp = OTG_REV_REG; | 2230 | tmp = OTG_REV_REG; |
2180 | trans = USB_TRANSCEIVER_CTRL_REG; | 2231 | trans = USB_TRANSCEIVER_CTRL_REG; |
2181 | seq_printf(s, "OTG rev %d.%d, transceiver_ctrl %03x\n", | 2232 | seq_printf(s, "\nOTG rev %d.%d, transceiver_ctrl %05x\n", |
2182 | tmp >> 4, tmp & 0xf, trans); | 2233 | tmp >> 4, tmp & 0xf, trans); |
2183 | tmp = OTG_SYSCON_1_REG; | 2234 | tmp = OTG_SYSCON_1_REG; |
2184 | seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s," | 2235 | seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s," |
2185 | FOURBITS "\n", tmp, | 2236 | FOURBITS "\n", tmp, |
2186 | trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R), | 2237 | trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R), |
2187 | trx_mode(USB1_TRX_MODE(tmp), trans & CONF_USB1_UNI_R), | 2238 | trx_mode(USB1_TRX_MODE(tmp), trans & CONF_USB1_UNI_R), |
2188 | (USB0_TRX_MODE(tmp) == 0) | 2239 | (USB0_TRX_MODE(tmp) == 0 && !cpu_is_omap1710()) |
2189 | ? "internal" | 2240 | ? "internal" |
2190 | : trx_mode(USB0_TRX_MODE(tmp), 1), | 2241 | : trx_mode(USB0_TRX_MODE(tmp), 1), |
2191 | (tmp & OTG_IDLE_EN) ? " !otg" : "", | 2242 | (tmp & OTG_IDLE_EN) ? " !otg" : "", |
@@ -2235,6 +2286,7 @@ static int proc_otg_show(struct seq_file *s) | |||
2235 | seq_printf(s, "otg_outctrl %04x" "\n", tmp); | 2286 | seq_printf(s, "otg_outctrl %04x" "\n", tmp); |
2236 | tmp = OTG_TEST_REG; | 2287 | tmp = OTG_TEST_REG; |
2237 | seq_printf(s, "otg_test %04x" "\n", tmp); | 2288 | seq_printf(s, "otg_test %04x" "\n", tmp); |
2289 | return 0; | ||
2238 | } | 2290 | } |
2239 | 2291 | ||
2240 | static int proc_udc_show(struct seq_file *s, void *_) | 2292 | static int proc_udc_show(struct seq_file *s, void *_) |
@@ -2378,7 +2430,7 @@ static int proc_udc_show(struct seq_file *s, void *_) | |||
2378 | 2430 | ||
2379 | static int proc_udc_open(struct inode *inode, struct file *file) | 2431 | static int proc_udc_open(struct inode *inode, struct file *file) |
2380 | { | 2432 | { |
2381 | return single_open(file, proc_udc_show, 0); | 2433 | return single_open(file, proc_udc_show, NULL); |
2382 | } | 2434 | } |
2383 | 2435 | ||
2384 | static struct file_operations proc_ops = { | 2436 | static struct file_operations proc_ops = { |
@@ -2399,7 +2451,7 @@ static void create_proc_file(void) | |||
2399 | 2451 | ||
2400 | static void remove_proc_file(void) | 2452 | static void remove_proc_file(void) |
2401 | { | 2453 | { |
2402 | remove_proc_entry(proc_filename, 0); | 2454 | remove_proc_entry(proc_filename, NULL); |
2403 | } | 2455 | } |
2404 | 2456 | ||
2405 | #else | 2457 | #else |
@@ -2414,6 +2466,10 @@ static inline void remove_proc_file(void) {} | |||
2414 | /* Before this controller can enumerate, we need to pick an endpoint | 2466 | /* Before this controller can enumerate, we need to pick an endpoint |
2415 | * configuration, or "fifo_mode" That involves allocating 2KB of packet | 2467 | * configuration, or "fifo_mode" That involves allocating 2KB of packet |
2416 | * buffer space among the endpoints we'll be operating. | 2468 | * buffer space among the endpoints we'll be operating. |
2469 | * | ||
2470 | * NOTE: as of OMAP 1710 ES2.0, writing a new endpoint config when | ||
2471 | * UDC_SYSCON_1_REG.CFG_LOCK is set can now work. We won't use that | ||
2472 | * capability yet though. | ||
2417 | */ | 2473 | */ |
2418 | static unsigned __init | 2474 | static unsigned __init |
2419 | omap_ep_setup(char *name, u8 addr, u8 type, | 2475 | omap_ep_setup(char *name, u8 addr, u8 type, |
@@ -2505,7 +2561,7 @@ static void omap_udc_release(struct device *dev) | |||
2505 | { | 2561 | { |
2506 | complete(udc->done); | 2562 | complete(udc->done); |
2507 | kfree (udc); | 2563 | kfree (udc); |
2508 | udc = 0; | 2564 | udc = NULL; |
2509 | } | 2565 | } |
2510 | 2566 | ||
2511 | static int __init | 2567 | static int __init |
@@ -2577,23 +2633,33 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) | |||
2577 | case 1: | 2633 | case 1: |
2578 | OMAP_BULK_EP("ep1in", USB_DIR_IN | 1); | 2634 | OMAP_BULK_EP("ep1in", USB_DIR_IN | 1); |
2579 | OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2); | 2635 | OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2); |
2636 | OMAP_INT_EP("ep9in", USB_DIR_IN | 9, 16); | ||
2637 | |||
2580 | OMAP_BULK_EP("ep3in", USB_DIR_IN | 3); | 2638 | OMAP_BULK_EP("ep3in", USB_DIR_IN | 3); |
2581 | OMAP_BULK_EP("ep4out", USB_DIR_OUT | 4); | 2639 | OMAP_BULK_EP("ep4out", USB_DIR_OUT | 4); |
2640 | OMAP_INT_EP("ep10in", USB_DIR_IN | 10, 16); | ||
2582 | 2641 | ||
2583 | OMAP_BULK_EP("ep5in", USB_DIR_IN | 5); | 2642 | OMAP_BULK_EP("ep5in", USB_DIR_IN | 5); |
2584 | OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5); | 2643 | OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5); |
2644 | OMAP_INT_EP("ep11in", USB_DIR_IN | 11, 16); | ||
2645 | |||
2585 | OMAP_BULK_EP("ep6in", USB_DIR_IN | 6); | 2646 | OMAP_BULK_EP("ep6in", USB_DIR_IN | 6); |
2586 | OMAP_BULK_EP("ep6out", USB_DIR_OUT | 6); | 2647 | OMAP_BULK_EP("ep6out", USB_DIR_OUT | 6); |
2648 | OMAP_INT_EP("ep12in", USB_DIR_IN | 12, 16); | ||
2587 | 2649 | ||
2588 | OMAP_BULK_EP("ep7in", USB_DIR_IN | 7); | 2650 | OMAP_BULK_EP("ep7in", USB_DIR_IN | 7); |
2589 | OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7); | 2651 | OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7); |
2652 | OMAP_INT_EP("ep13in", USB_DIR_IN | 13, 16); | ||
2653 | OMAP_INT_EP("ep13out", USB_DIR_OUT | 13, 16); | ||
2654 | |||
2590 | OMAP_BULK_EP("ep8in", USB_DIR_IN | 8); | 2655 | OMAP_BULK_EP("ep8in", USB_DIR_IN | 8); |
2591 | OMAP_BULK_EP("ep8out", USB_DIR_OUT | 8); | 2656 | OMAP_BULK_EP("ep8out", USB_DIR_OUT | 8); |
2657 | OMAP_INT_EP("ep14in", USB_DIR_IN | 14, 16); | ||
2658 | OMAP_INT_EP("ep14out", USB_DIR_OUT | 14, 16); | ||
2659 | |||
2660 | OMAP_BULK_EP("ep15in", USB_DIR_IN | 15); | ||
2661 | OMAP_BULK_EP("ep15out", USB_DIR_OUT | 15); | ||
2592 | 2662 | ||
2593 | OMAP_INT_EP("ep9in", USB_DIR_IN | 9, 16); | ||
2594 | OMAP_INT_EP("ep10out", USB_DIR_IN | 10, 16); | ||
2595 | OMAP_INT_EP("ep11in", USB_DIR_IN | 9, 16); | ||
2596 | OMAP_INT_EP("ep12out", USB_DIR_IN | 10, 16); | ||
2597 | break; | 2663 | break; |
2598 | 2664 | ||
2599 | #ifdef USE_ISO | 2665 | #ifdef USE_ISO |
@@ -2640,8 +2706,8 @@ static int __init omap_udc_probe(struct device *dev) | |||
2640 | struct platform_device *odev = to_platform_device(dev); | 2706 | struct platform_device *odev = to_platform_device(dev); |
2641 | int status = -ENODEV; | 2707 | int status = -ENODEV; |
2642 | int hmc; | 2708 | int hmc; |
2643 | struct otg_transceiver *xceiv = 0; | 2709 | struct otg_transceiver *xceiv = NULL; |
2644 | const char *type = 0; | 2710 | const char *type = NULL; |
2645 | struct omap_usb_config *config = dev->platform_data; | 2711 | struct omap_usb_config *config = dev->platform_data; |
2646 | 2712 | ||
2647 | /* NOTE: "knows" the order of the resources! */ | 2713 | /* NOTE: "knows" the order of the resources! */ |
@@ -2676,54 +2742,78 @@ static int __init omap_udc_probe(struct device *dev) | |||
2676 | FUNC_MUX_CTRL_0_REG = tmp; | 2742 | FUNC_MUX_CTRL_0_REG = tmp; |
2677 | } | 2743 | } |
2678 | } else { | 2744 | } else { |
2745 | /* The transceiver may package some GPIO logic or handle | ||
2746 | * loopback and/or transceiverless setup; if we find one, | ||
2747 | * use it. Except for OTG, we don't _need_ to talk to one; | ||
2748 | * but not having one probably means no VBUS detection. | ||
2749 | */ | ||
2750 | xceiv = otg_get_transceiver(); | ||
2751 | if (xceiv) | ||
2752 | type = xceiv->label; | ||
2753 | else if (config->otg) { | ||
2754 | DBG("OTG requires external transceiver!\n"); | ||
2755 | goto cleanup0; | ||
2756 | } | ||
2757 | |||
2679 | hmc = HMC_1610; | 2758 | hmc = HMC_1610; |
2680 | switch (hmc) { | 2759 | switch (hmc) { |
2760 | case 0: /* POWERUP DEFAULT == 0 */ | ||
2761 | case 4: | ||
2762 | case 12: | ||
2763 | case 20: | ||
2764 | if (!cpu_is_omap1710()) { | ||
2765 | type = "integrated"; | ||
2766 | break; | ||
2767 | } | ||
2768 | /* FALL THROUGH */ | ||
2681 | case 3: | 2769 | case 3: |
2682 | case 11: | 2770 | case 11: |
2683 | case 16: | 2771 | case 16: |
2684 | case 19: | 2772 | case 19: |
2685 | case 25: | 2773 | case 25: |
2686 | xceiv = otg_get_transceiver(); | ||
2687 | if (!xceiv) { | 2774 | if (!xceiv) { |
2688 | DBG("external transceiver not registered!\n"); | 2775 | DBG("external transceiver not registered!\n"); |
2689 | if (config->otg) | 2776 | type = "unknown"; |
2690 | goto cleanup0; | 2777 | } |
2691 | type = "(unknown external)"; | ||
2692 | } else | ||
2693 | type = xceiv->label; | ||
2694 | break; | ||
2695 | case 0: /* POWERUP DEFAULT == 0 */ | ||
2696 | case 4: | ||
2697 | case 12: | ||
2698 | case 20: | ||
2699 | type = "INTEGRATED"; | ||
2700 | break; | 2778 | break; |
2701 | case 21: /* internal loopback */ | 2779 | case 21: /* internal loopback */ |
2702 | type = "(loopback)"; | 2780 | type = "loopback"; |
2703 | break; | 2781 | break; |
2704 | case 14: /* transceiverless */ | 2782 | case 14: /* transceiverless */ |
2705 | type = "(none)"; | 2783 | if (cpu_is_omap1710()) |
2784 | goto bad_on_1710; | ||
2785 | /* FALL THROUGH */ | ||
2786 | case 13: | ||
2787 | case 15: | ||
2788 | type = "no"; | ||
2706 | break; | 2789 | break; |
2707 | 2790 | ||
2708 | default: | 2791 | default: |
2792 | bad_on_1710: | ||
2709 | ERR("unrecognized UDC HMC mode %d\n", hmc); | 2793 | ERR("unrecognized UDC HMC mode %d\n", hmc); |
2710 | return -ENODEV; | 2794 | goto cleanup0; |
2711 | } | 2795 | } |
2712 | } | 2796 | } |
2713 | INFO("hmc mode %d, transceiver %s\n", hmc, type); | 2797 | INFO("hmc mode %d, %s transceiver\n", hmc, type); |
2714 | 2798 | ||
2715 | /* a "gadget" abstracts/virtualizes the controller */ | 2799 | /* a "gadget" abstracts/virtualizes the controller */ |
2716 | status = omap_udc_setup(odev, xceiv); | 2800 | status = omap_udc_setup(odev, xceiv); |
2717 | if (status) { | 2801 | if (status) { |
2718 | goto cleanup0; | 2802 | goto cleanup0; |
2719 | } | 2803 | } |
2720 | xceiv = 0; | 2804 | xceiv = NULL; |
2721 | // "udc" is now valid | 2805 | // "udc" is now valid |
2722 | pullup_disable(udc); | 2806 | pullup_disable(udc); |
2723 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) | 2807 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
2724 | udc->gadget.is_otg = (config->otg != 0); | 2808 | udc->gadget.is_otg = (config->otg != 0); |
2725 | #endif | 2809 | #endif |
2726 | 2810 | ||
2811 | /* starting with omap1710 es2.0, clear toggle is a separate bit */ | ||
2812 | if (UDC_REV_REG >= 0x61) | ||
2813 | udc->clr_halt = UDC_RESET_EP | UDC_CLRDATA_TOGGLE; | ||
2814 | else | ||
2815 | udc->clr_halt = UDC_RESET_EP; | ||
2816 | |||
2727 | /* USB general purpose IRQ: ep0, state changes, dma, etc */ | 2817 | /* USB general purpose IRQ: ep0, state changes, dma, etc */ |
2728 | status = request_irq(odev->resource[1].start, omap_udc_irq, | 2818 | status = request_irq(odev->resource[1].start, omap_udc_irq, |
2729 | SA_SAMPLE_RANDOM, driver_name, udc); | 2819 | SA_SAMPLE_RANDOM, driver_name, udc); |
@@ -2765,7 +2855,7 @@ cleanup2: | |||
2765 | 2855 | ||
2766 | cleanup1: | 2856 | cleanup1: |
2767 | kfree (udc); | 2857 | kfree (udc); |
2768 | udc = 0; | 2858 | udc = NULL; |
2769 | 2859 | ||
2770 | cleanup0: | 2860 | cleanup0: |
2771 | if (xceiv) | 2861 | if (xceiv) |
@@ -2788,7 +2878,7 @@ static int __exit omap_udc_remove(struct device *dev) | |||
2788 | pullup_disable(udc); | 2878 | pullup_disable(udc); |
2789 | if (udc->transceiver) { | 2879 | if (udc->transceiver) { |
2790 | put_device(udc->transceiver->dev); | 2880 | put_device(udc->transceiver->dev); |
2791 | udc->transceiver = 0; | 2881 | udc->transceiver = NULL; |
2792 | } | 2882 | } |
2793 | UDC_SYSCON1_REG = 0; | 2883 | UDC_SYSCON1_REG = 0; |
2794 | 2884 | ||
@@ -2809,13 +2899,32 @@ static int __exit omap_udc_remove(struct device *dev) | |||
2809 | return 0; | 2899 | return 0; |
2810 | } | 2900 | } |
2811 | 2901 | ||
2812 | static int omap_udc_suspend(struct device *dev, pm_message_t state, u32 level) | 2902 | /* suspend/resume/wakeup from sysfs (echo > power/state) or when the |
2903 | * system is forced into deep sleep | ||
2904 | * | ||
2905 | * REVISIT we should probably reject suspend requests when there's a host | ||
2906 | * session active, rather than disconnecting, at least on boards that can | ||
2907 | * report VBUS irqs (UDC_DEVSTAT_REG.UDC_ATT). And in any case, we need to | ||
2908 | * make host resumes and VBUS detection trigger OMAP wakeup events; that | ||
2909 | * may involve talking to an external transceiver (e.g. isp1301). | ||
2910 | */ | ||
2911 | static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level) | ||
2813 | { | 2912 | { |
2814 | if (level != 0) | 2913 | u32 devstat; |
2914 | |||
2915 | if (level != SUSPEND_POWER_DOWN) | ||
2815 | return 0; | 2916 | return 0; |
2917 | devstat = UDC_DEVSTAT_REG; | ||
2918 | |||
2919 | /* we're requesting 48 MHz clock if the pullup is enabled | ||
2920 | * (== we're attached to the host) and we're not suspended, | ||
2921 | * which would prevent entry to deep sleep... | ||
2922 | */ | ||
2923 | if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) { | ||
2924 | WARN("session active; suspend requires disconnect\n"); | ||
2925 | omap_pullup(&udc->gadget, 0); | ||
2926 | } | ||
2816 | 2927 | ||
2817 | DBG("suspend, state %d\n", state); | ||
2818 | omap_pullup(&udc->gadget, 0); | ||
2819 | udc->gadget.dev.power.power_state = PMSG_SUSPEND; | 2928 | udc->gadget.dev.power.power_state = PMSG_SUSPEND; |
2820 | udc->gadget.dev.parent->power.power_state = PMSG_SUSPEND; | 2929 | udc->gadget.dev.parent->power.power_state = PMSG_SUSPEND; |
2821 | return 0; | 2930 | return 0; |
@@ -2823,7 +2932,7 @@ static int omap_udc_suspend(struct device *dev, pm_message_t state, u32 level) | |||
2823 | 2932 | ||
2824 | static int omap_udc_resume(struct device *dev, u32 level) | 2933 | static int omap_udc_resume(struct device *dev, u32 level) |
2825 | { | 2934 | { |
2826 | if (level != 0) | 2935 | if (level != RESUME_POWER_ON) |
2827 | return 0; | 2936 | return 0; |
2828 | 2937 | ||
2829 | DBG("resume + wakeup/SRP\n"); | 2938 | DBG("resume + wakeup/SRP\n"); |
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index c9e68541622c..652ee4627344 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #define UDC_CTRL_REG UDC_REG(0x0C) /* Endpoint control */ | 20 | #define UDC_CTRL_REG UDC_REG(0x0C) /* Endpoint control */ |
21 | # define UDC_CLR_HALT (1 << 7) | 21 | # define UDC_CLR_HALT (1 << 7) |
22 | # define UDC_SET_HALT (1 << 6) | 22 | # define UDC_SET_HALT (1 << 6) |
23 | # define UDC_CLRDATA_TOGGLE (1 << 3) | ||
23 | # define UDC_SET_FIFO_EN (1 << 2) | 24 | # define UDC_SET_FIFO_EN (1 << 2) |
24 | # define UDC_CLR_EP (1 << 1) | 25 | # define UDC_CLR_EP (1 << 1) |
25 | # define UDC_RESET_EP (1 << 0) | 26 | # define UDC_RESET_EP (1 << 0) |
@@ -99,6 +100,7 @@ | |||
99 | 100 | ||
100 | /* DMA configuration registers: up to three channels in each direction. */ | 101 | /* DMA configuration registers: up to three channels in each direction. */ |
101 | #define UDC_RXDMA_CFG_REG UDC_REG(0x40) /* 3 eps for RX DMA */ | 102 | #define UDC_RXDMA_CFG_REG UDC_REG(0x40) /* 3 eps for RX DMA */ |
103 | # define UDC_DMA_REQ (1 << 12) | ||
102 | #define UDC_TXDMA_CFG_REG UDC_REG(0x44) /* 3 eps for TX DMA */ | 104 | #define UDC_TXDMA_CFG_REG UDC_REG(0x44) /* 3 eps for TX DMA */ |
103 | #define UDC_DATA_DMA_REG UDC_REG(0x48) /* rx/tx fifo addr */ | 105 | #define UDC_DATA_DMA_REG UDC_REG(0x48) /* rx/tx fifo addr */ |
104 | 106 | ||
@@ -162,6 +164,7 @@ struct omap_udc { | |||
162 | spinlock_t lock; | 164 | spinlock_t lock; |
163 | struct omap_ep ep[32]; | 165 | struct omap_ep ep[32]; |
164 | u16 devstat; | 166 | u16 devstat; |
167 | u16 clr_halt; | ||
165 | struct otg_transceiver *transceiver; | 168 | struct otg_transceiver *transceiver; |
166 | struct list_head iso; | 169 | struct list_head iso; |
167 | unsigned softconnect:1; | 170 | unsigned softconnect:1; |
@@ -171,7 +174,6 @@ struct omap_udc { | |||
171 | unsigned ep0_set_config:1; | 174 | unsigned ep0_set_config:1; |
172 | unsigned ep0_reset_config:1; | 175 | unsigned ep0_reset_config:1; |
173 | unsigned ep0_setup:1; | 176 | unsigned ep0_setup:1; |
174 | |||
175 | struct completion *done; | 177 | struct completion *done; |
176 | }; | 178 | }; |
177 | 179 | ||
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index b8b4524ed746..6a0b957af335 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/usb/gadget/pxa2xx_udc.c | 2 | * linux/drivers/usb/gadget/pxa2xx_udc.c |
3 | * Intel PXA2xx and IXP4xx on-chip full speed USB device controllers | 3 | * Intel PXA25x and IXP4xx on-chip full speed USB device controllers |
4 | * | 4 | * |
5 | * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker) | 5 | * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker) |
6 | * Copyright (C) 2003 Robert Schwebel, Pengutronix | 6 | * Copyright (C) 2003 Robert Schwebel, Pengutronix |
@@ -63,7 +63,7 @@ | |||
63 | 63 | ||
64 | 64 | ||
65 | /* | 65 | /* |
66 | * This driver handles the USB Device Controller (UDC) in Intel's PXA 2xx | 66 | * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x |
67 | * series processors. The UDC for the IXP 4xx series is very similar. | 67 | * series processors. The UDC for the IXP 4xx series is very similar. |
68 | * There are fifteen endpoints, in addition to ep0. | 68 | * There are fifteen endpoints, in addition to ep0. |
69 | * | 69 | * |
@@ -79,8 +79,8 @@ | |||
79 | * pxa250 a0/a1 b0/b1/b2 sure act like they're still there. | 79 | * pxa250 a0/a1 b0/b1/b2 sure act like they're still there. |
80 | */ | 80 | */ |
81 | 81 | ||
82 | #define DRIVER_VERSION "14-Dec-2003" | 82 | #define DRIVER_VERSION "4-May-2005" |
83 | #define DRIVER_DESC "PXA 2xx USB Device Controller driver" | 83 | #define DRIVER_DESC "PXA 25x USB Device Controller driver" |
84 | 84 | ||
85 | 85 | ||
86 | static const char driver_name [] = "pxa2xx_udc"; | 86 | static const char driver_name [] = "pxa2xx_udc"; |
@@ -290,6 +290,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep, | |||
290 | static int pxa2xx_ep_disable (struct usb_ep *_ep) | 290 | static int pxa2xx_ep_disable (struct usb_ep *_ep) |
291 | { | 291 | { |
292 | struct pxa2xx_ep *ep; | 292 | struct pxa2xx_ep *ep; |
293 | unsigned long flags; | ||
293 | 294 | ||
294 | ep = container_of (_ep, struct pxa2xx_ep, ep); | 295 | ep = container_of (_ep, struct pxa2xx_ep, ep); |
295 | if (!_ep || !ep->desc) { | 296 | if (!_ep || !ep->desc) { |
@@ -297,6 +298,8 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep) | |||
297 | _ep ? ep->ep.name : NULL); | 298 | _ep ? ep->ep.name : NULL); |
298 | return -EINVAL; | 299 | return -EINVAL; |
299 | } | 300 | } |
301 | local_irq_save(flags); | ||
302 | |||
300 | nuke (ep, -ESHUTDOWN); | 303 | nuke (ep, -ESHUTDOWN); |
301 | 304 | ||
302 | #ifdef USE_DMA | 305 | #ifdef USE_DMA |
@@ -313,6 +316,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep) | |||
313 | ep->desc = NULL; | 316 | ep->desc = NULL; |
314 | ep->stopped = 1; | 317 | ep->stopped = 1; |
315 | 318 | ||
319 | local_irq_restore(flags); | ||
316 | DBG(DBG_VERBOSE, "%s disabled\n", _ep->name); | 320 | DBG(DBG_VERBOSE, "%s disabled\n", _ep->name); |
317 | return 0; | 321 | return 0; |
318 | } | 322 | } |
@@ -971,10 +975,10 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) | |||
971 | kick_dma(ep, req); | 975 | kick_dma(ep, req); |
972 | #endif | 976 | #endif |
973 | /* can the FIFO can satisfy the request immediately? */ | 977 | /* can the FIFO can satisfy the request immediately? */ |
974 | } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0 | 978 | } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) { |
975 | && (*ep->reg_udccs & UDCCS_BI_TFS) != 0 | 979 | if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0 |
976 | && write_fifo(ep, req)) { | 980 | && write_fifo(ep, req)) |
977 | req = NULL; | 981 | req = NULL; |
978 | } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0 | 982 | } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0 |
979 | && read_fifo(ep, req)) { | 983 | && read_fifo(ep, req)) { |
980 | req = NULL; | 984 | req = NULL; |
@@ -1290,7 +1294,7 @@ udc_proc_read(char *page, char **start, off_t off, int count, | |||
1290 | "%s version: %s\nGadget driver: %s\nHost %s\n\n", | 1294 | "%s version: %s\nGadget driver: %s\nHost %s\n\n", |
1291 | driver_name, DRIVER_VERSION SIZE_STR DMASTR, | 1295 | driver_name, DRIVER_VERSION SIZE_STR DMASTR, |
1292 | dev->driver ? dev->driver->driver.name : "(none)", | 1296 | dev->driver ? dev->driver->driver.name : "(none)", |
1293 | is_usb_connected() ? "full speed" : "disconnected"); | 1297 | is_vbus_present() ? "full speed" : "disconnected"); |
1294 | size -= t; | 1298 | size -= t; |
1295 | next += t; | 1299 | next += t; |
1296 | 1300 | ||
@@ -1339,7 +1343,7 @@ udc_proc_read(char *page, char **start, off_t off, int count, | |||
1339 | next += t; | 1343 | next += t; |
1340 | } | 1344 | } |
1341 | 1345 | ||
1342 | if (!is_usb_connected() || !dev->driver) | 1346 | if (!is_vbus_present() || !dev->driver) |
1343 | goto done; | 1347 | goto done; |
1344 | 1348 | ||
1345 | t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n", | 1349 | t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n", |
@@ -1454,7 +1458,7 @@ static void udc_disable(struct pxa2xx_udc *dev) | |||
1454 | UFNRH = UFNRH_SIM; | 1458 | UFNRH = UFNRH_SIM; |
1455 | 1459 | ||
1456 | /* if hardware supports it, disconnect from usb */ | 1460 | /* if hardware supports it, disconnect from usb */ |
1457 | make_usb_disappear(); | 1461 | pullup_off(); |
1458 | 1462 | ||
1459 | udc_clear_mask_UDCCR(UDCCR_UDE); | 1463 | udc_clear_mask_UDCCR(UDCCR_UDE); |
1460 | 1464 | ||
@@ -1567,7 +1571,7 @@ static void udc_enable (struct pxa2xx_udc *dev) | |||
1567 | UICR0 &= ~UICR0_IM0; | 1571 | UICR0 &= ~UICR0_IM0; |
1568 | 1572 | ||
1569 | /* if hardware supports it, pullup D+ and wait for reset */ | 1573 | /* if hardware supports it, pullup D+ and wait for reset */ |
1570 | let_usb_appear(); | 1574 | pullup_on(); |
1571 | } | 1575 | } |
1572 | 1576 | ||
1573 | 1577 | ||
@@ -2052,10 +2056,10 @@ pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r) | |||
2052 | if (unlikely(udccr & UDCCR_SUSIR)) { | 2056 | if (unlikely(udccr & UDCCR_SUSIR)) { |
2053 | udc_ack_int_UDCCR(UDCCR_SUSIR); | 2057 | udc_ack_int_UDCCR(UDCCR_SUSIR); |
2054 | handled = 1; | 2058 | handled = 1; |
2055 | DBG(DBG_VERBOSE, "USB suspend%s\n", is_usb_connected() | 2059 | DBG(DBG_VERBOSE, "USB suspend%s\n", is_vbus_present() |
2056 | ? "" : "+disconnect"); | 2060 | ? "" : "+disconnect"); |
2057 | 2061 | ||
2058 | if (!is_usb_connected()) | 2062 | if (!is_vbus_present()) |
2059 | stop_activity(dev, dev->driver); | 2063 | stop_activity(dev, dev->driver); |
2060 | else if (dev->gadget.speed != USB_SPEED_UNKNOWN | 2064 | else if (dev->gadget.speed != USB_SPEED_UNKNOWN |
2061 | && dev->driver | 2065 | && dev->driver |
@@ -2073,7 +2077,7 @@ pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r) | |||
2073 | if (dev->gadget.speed != USB_SPEED_UNKNOWN | 2077 | if (dev->gadget.speed != USB_SPEED_UNKNOWN |
2074 | && dev->driver | 2078 | && dev->driver |
2075 | && dev->driver->resume | 2079 | && dev->driver->resume |
2076 | && is_usb_connected()) | 2080 | && is_vbus_present()) |
2077 | dev->driver->resume(&dev->gadget); | 2081 | dev->driver->resume(&dev->gadget); |
2078 | } | 2082 | } |
2079 | 2083 | ||
@@ -2509,7 +2513,7 @@ static int __init pxa2xx_udc_probe(struct device *_dev) | |||
2509 | udc_disable(dev); | 2513 | udc_disable(dev); |
2510 | udc_reinit(dev); | 2514 | udc_reinit(dev); |
2511 | 2515 | ||
2512 | dev->vbus = is_usb_connected(); | 2516 | dev->vbus = is_vbus_present(); |
2513 | 2517 | ||
2514 | /* irq setup after old hardware state is cleaned up */ | 2518 | /* irq setup after old hardware state is cleaned up */ |
2515 | retval = request_irq(IRQ_USB, pxa2xx_udc_irq, | 2519 | retval = request_irq(IRQ_USB, pxa2xx_udc_irq, |
@@ -2555,6 +2559,12 @@ lubbock_fail0: | |||
2555 | 2559 | ||
2556 | return 0; | 2560 | return 0; |
2557 | } | 2561 | } |
2562 | |||
2563 | static void pxa2xx_udc_shutdown(struct device *_dev) | ||
2564 | { | ||
2565 | pullup_off(); | ||
2566 | } | ||
2567 | |||
2558 | static int __exit pxa2xx_udc_remove(struct device *_dev) | 2568 | static int __exit pxa2xx_udc_remove(struct device *_dev) |
2559 | { | 2569 | { |
2560 | struct pxa2xx_udc *dev = dev_get_drvdata(_dev); | 2570 | struct pxa2xx_udc *dev = dev_get_drvdata(_dev); |
@@ -2624,6 +2634,7 @@ static struct device_driver udc_driver = { | |||
2624 | .name = "pxa2xx-udc", | 2634 | .name = "pxa2xx-udc", |
2625 | .bus = &platform_bus_type, | 2635 | .bus = &platform_bus_type, |
2626 | .probe = pxa2xx_udc_probe, | 2636 | .probe = pxa2xx_udc_probe, |
2637 | .shutdown = pxa2xx_udc_shutdown, | ||
2627 | .remove = __exit_p(pxa2xx_udc_remove), | 2638 | .remove = __exit_p(pxa2xx_udc_remove), |
2628 | .suspend = pxa2xx_udc_suspend, | 2639 | .suspend = pxa2xx_udc_suspend, |
2629 | .resume = pxa2xx_udc_resume, | 2640 | .resume = pxa2xx_udc_resume, |
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h index 1f3a7d999da7..d0bc396a85d5 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa2xx_udc.h | |||
@@ -177,23 +177,23 @@ struct pxa2xx_udc { | |||
177 | 177 | ||
178 | static struct pxa2xx_udc *the_controller; | 178 | static struct pxa2xx_udc *the_controller; |
179 | 179 | ||
180 | /* one GPIO should be used to detect host disconnect */ | 180 | /* one GPIO should be used to detect VBUS from the host */ |
181 | static inline int is_usb_connected(void) | 181 | static inline int is_vbus_present(void) |
182 | { | 182 | { |
183 | if (!the_controller->mach->udc_is_connected) | 183 | if (!the_controller->mach->udc_is_connected) |
184 | return 1; | 184 | return 1; |
185 | return the_controller->mach->udc_is_connected(); | 185 | return the_controller->mach->udc_is_connected(); |
186 | } | 186 | } |
187 | 187 | ||
188 | /* one GPIO should force the host to see this device (or not) */ | 188 | /* one GPIO should control a D+ pullup, so host sees this device (or not) */ |
189 | static inline void make_usb_disappear(void) | 189 | static inline void pullup_off(void) |
190 | { | 190 | { |
191 | if (!the_controller->mach->udc_command) | 191 | if (!the_controller->mach->udc_command) |
192 | return; | 192 | return; |
193 | the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); | 193 | the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); |
194 | } | 194 | } |
195 | 195 | ||
196 | static inline void let_usb_appear(void) | 196 | static inline void pullup_on(void) |
197 | { | 197 | { |
198 | if (!the_controller->mach->udc_command) | 198 | if (!the_controller->mach->udc_command) |
199 | return; | 199 | return; |
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 7457268d5f28..06b6eba925b5 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | 42 | ||
43 | #undef RNDIS_PM | 43 | #undef RNDIS_PM |
44 | #undef RNDIS_WAKEUP | ||
44 | #undef VERBOSE | 45 | #undef VERBOSE |
45 | 46 | ||
46 | #include "rndis.h" | 47 | #include "rndis.h" |
@@ -60,7 +61,7 @@ | |||
60 | } while (0) | 61 | } while (0) |
61 | static int rndis_debug = 0; | 62 | static int rndis_debug = 0; |
62 | 63 | ||
63 | module_param (rndis_debug, bool, 0); | 64 | module_param (rndis_debug, int, 0); |
64 | MODULE_PARM_DESC (rndis_debug, "enable debugging"); | 65 | MODULE_PARM_DESC (rndis_debug, "enable debugging"); |
65 | 66 | ||
66 | #else | 67 | #else |
@@ -78,22 +79,103 @@ static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS]; | |||
78 | static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1); | 79 | static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1); |
79 | 80 | ||
80 | /* Function Prototypes */ | 81 | /* Function Prototypes */ |
81 | static int rndis_init_response (int configNr, rndis_init_msg_type *buf); | ||
82 | static int rndis_query_response (int configNr, rndis_query_msg_type *buf); | ||
83 | static int rndis_set_response (int configNr, rndis_set_msg_type *buf); | ||
84 | static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf); | ||
85 | static int rndis_keepalive_response (int configNr, | ||
86 | rndis_keepalive_msg_type *buf); | ||
87 | |||
88 | static rndis_resp_t *rndis_add_response (int configNr, u32 length); | 82 | static rndis_resp_t *rndis_add_response (int configNr, u32 length); |
89 | 83 | ||
90 | 84 | ||
85 | /* supported OIDs */ | ||
86 | static const u32 oid_supported_list [] = | ||
87 | { | ||
88 | /* the general stuff */ | ||
89 | OID_GEN_SUPPORTED_LIST, | ||
90 | OID_GEN_HARDWARE_STATUS, | ||
91 | OID_GEN_MEDIA_SUPPORTED, | ||
92 | OID_GEN_MEDIA_IN_USE, | ||
93 | OID_GEN_MAXIMUM_FRAME_SIZE, | ||
94 | OID_GEN_LINK_SPEED, | ||
95 | OID_GEN_TRANSMIT_BLOCK_SIZE, | ||
96 | OID_GEN_RECEIVE_BLOCK_SIZE, | ||
97 | OID_GEN_VENDOR_ID, | ||
98 | OID_GEN_VENDOR_DESCRIPTION, | ||
99 | OID_GEN_VENDOR_DRIVER_VERSION, | ||
100 | OID_GEN_CURRENT_PACKET_FILTER, | ||
101 | OID_GEN_MAXIMUM_TOTAL_SIZE, | ||
102 | OID_GEN_MEDIA_CONNECT_STATUS, | ||
103 | OID_GEN_PHYSICAL_MEDIUM, | ||
104 | #if 0 | ||
105 | OID_GEN_RNDIS_CONFIG_PARAMETER, | ||
106 | #endif | ||
107 | |||
108 | /* the statistical stuff */ | ||
109 | OID_GEN_XMIT_OK, | ||
110 | OID_GEN_RCV_OK, | ||
111 | OID_GEN_XMIT_ERROR, | ||
112 | OID_GEN_RCV_ERROR, | ||
113 | OID_GEN_RCV_NO_BUFFER, | ||
114 | #ifdef RNDIS_OPTIONAL_STATS | ||
115 | OID_GEN_DIRECTED_BYTES_XMIT, | ||
116 | OID_GEN_DIRECTED_FRAMES_XMIT, | ||
117 | OID_GEN_MULTICAST_BYTES_XMIT, | ||
118 | OID_GEN_MULTICAST_FRAMES_XMIT, | ||
119 | OID_GEN_BROADCAST_BYTES_XMIT, | ||
120 | OID_GEN_BROADCAST_FRAMES_XMIT, | ||
121 | OID_GEN_DIRECTED_BYTES_RCV, | ||
122 | OID_GEN_DIRECTED_FRAMES_RCV, | ||
123 | OID_GEN_MULTICAST_BYTES_RCV, | ||
124 | OID_GEN_MULTICAST_FRAMES_RCV, | ||
125 | OID_GEN_BROADCAST_BYTES_RCV, | ||
126 | OID_GEN_BROADCAST_FRAMES_RCV, | ||
127 | OID_GEN_RCV_CRC_ERROR, | ||
128 | OID_GEN_TRANSMIT_QUEUE_LENGTH, | ||
129 | #endif /* RNDIS_OPTIONAL_STATS */ | ||
130 | |||
131 | /* mandatory 802.3 */ | ||
132 | /* the general stuff */ | ||
133 | OID_802_3_PERMANENT_ADDRESS, | ||
134 | OID_802_3_CURRENT_ADDRESS, | ||
135 | OID_802_3_MULTICAST_LIST, | ||
136 | OID_802_3_MAC_OPTIONS, | ||
137 | OID_802_3_MAXIMUM_LIST_SIZE, | ||
138 | |||
139 | /* the statistical stuff */ | ||
140 | OID_802_3_RCV_ERROR_ALIGNMENT, | ||
141 | OID_802_3_XMIT_ONE_COLLISION, | ||
142 | OID_802_3_XMIT_MORE_COLLISIONS, | ||
143 | #ifdef RNDIS_OPTIONAL_STATS | ||
144 | OID_802_3_XMIT_DEFERRED, | ||
145 | OID_802_3_XMIT_MAX_COLLISIONS, | ||
146 | OID_802_3_RCV_OVERRUN, | ||
147 | OID_802_3_XMIT_UNDERRUN, | ||
148 | OID_802_3_XMIT_HEARTBEAT_FAILURE, | ||
149 | OID_802_3_XMIT_TIMES_CRS_LOST, | ||
150 | OID_802_3_XMIT_LATE_COLLISIONS, | ||
151 | #endif /* RNDIS_OPTIONAL_STATS */ | ||
152 | |||
153 | #ifdef RNDIS_PM | ||
154 | /* PM and wakeup are mandatory for USB: */ | ||
155 | |||
156 | /* power management */ | ||
157 | OID_PNP_CAPABILITIES, | ||
158 | OID_PNP_QUERY_POWER, | ||
159 | OID_PNP_SET_POWER, | ||
160 | |||
161 | #ifdef RNDIS_WAKEUP | ||
162 | /* wake up host */ | ||
163 | OID_PNP_ENABLE_WAKE_UP, | ||
164 | OID_PNP_ADD_WAKE_UP_PATTERN, | ||
165 | OID_PNP_REMOVE_WAKE_UP_PATTERN, | ||
166 | #endif /* RNDIS_WAKEUP */ | ||
167 | #endif /* RNDIS_PM */ | ||
168 | }; | ||
169 | |||
170 | |||
91 | /* NDIS Functions */ | 171 | /* NDIS Functions */ |
92 | static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | 172 | static int |
173 | gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | ||
174 | rndis_resp_t *r) | ||
93 | { | 175 | { |
94 | int retval = -ENOTSUPP; | 176 | int retval = -ENOTSUPP; |
95 | u32 length = 0; | 177 | u32 length = 4; /* usually */ |
96 | __le32 *tmp; | 178 | __le32 *outbuf; |
97 | int i, count; | 179 | int i, count; |
98 | rndis_query_cmplt_type *resp; | 180 | rndis_query_cmplt_type *resp; |
99 | 181 | ||
@@ -101,7 +183,22 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
101 | resp = (rndis_query_cmplt_type *) r->buf; | 183 | resp = (rndis_query_cmplt_type *) r->buf; |
102 | 184 | ||
103 | if (!resp) return -ENOMEM; | 185 | if (!resp) return -ENOMEM; |
104 | 186 | ||
187 | if (buf_len && rndis_debug > 1) { | ||
188 | DEBUG("query OID %08x value, len %d:\n", OID, buf_len); | ||
189 | for (i = 0; i < buf_len; i += 16) { | ||
190 | DEBUG ("%03d: %08x %08x %08x %08x\n", i, | ||
191 | le32_to_cpup((__le32 *)&buf[i]), | ||
192 | le32_to_cpup((__le32 *)&buf[i + 4]), | ||
193 | le32_to_cpup((__le32 *)&buf[i + 8]), | ||
194 | le32_to_cpup((__le32 *)&buf[i + 12])); | ||
195 | } | ||
196 | } | ||
197 | |||
198 | /* response goes here, right after the header */ | ||
199 | outbuf = (__le32 *) &resp[1]; | ||
200 | resp->InformationBufferOffset = __constant_cpu_to_le32 (16); | ||
201 | |||
105 | switch (OID) { | 202 | switch (OID) { |
106 | 203 | ||
107 | /* general oids (table 4-1) */ | 204 | /* general oids (table 4-1) */ |
@@ -111,42 +208,36 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
111 | DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__); | 208 | DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__); |
112 | length = sizeof (oid_supported_list); | 209 | length = sizeof (oid_supported_list); |
113 | count = length / sizeof (u32); | 210 | count = length / sizeof (u32); |
114 | tmp = (__le32 *) ((u8 *)resp + 24); | ||
115 | for (i = 0; i < count; i++) | 211 | for (i = 0; i < count; i++) |
116 | tmp[i] = cpu_to_le32 (oid_supported_list[i]); | 212 | outbuf[i] = cpu_to_le32 (oid_supported_list[i]); |
117 | retval = 0; | 213 | retval = 0; |
118 | break; | 214 | break; |
119 | 215 | ||
120 | /* mandatory */ | 216 | /* mandatory */ |
121 | case OID_GEN_HARDWARE_STATUS: | 217 | case OID_GEN_HARDWARE_STATUS: |
122 | DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); | 218 | DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); |
123 | length = 4; | ||
124 | /* Bogus question! | 219 | /* Bogus question! |
125 | * Hardware must be ready to receive high level protocols. | 220 | * Hardware must be ready to receive high level protocols. |
126 | * BTW: | 221 | * BTW: |
127 | * reddite ergo quae sunt Caesaris Caesari | 222 | * reddite ergo quae sunt Caesaris Caesari |
128 | * et quae sunt Dei Deo! | 223 | * et quae sunt Dei Deo! |
129 | */ | 224 | */ |
130 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 225 | *outbuf = __constant_cpu_to_le32 (0); |
131 | retval = 0; | 226 | retval = 0; |
132 | break; | 227 | break; |
133 | 228 | ||
134 | /* mandatory */ | 229 | /* mandatory */ |
135 | case OID_GEN_MEDIA_SUPPORTED: | 230 | case OID_GEN_MEDIA_SUPPORTED: |
136 | DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); | 231 | DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); |
137 | length = 4; | 232 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); |
138 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
139 | rndis_per_dev_params [configNr].medium); | ||
140 | retval = 0; | 233 | retval = 0; |
141 | break; | 234 | break; |
142 | 235 | ||
143 | /* mandatory */ | 236 | /* mandatory */ |
144 | case OID_GEN_MEDIA_IN_USE: | 237 | case OID_GEN_MEDIA_IN_USE: |
145 | DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); | 238 | DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); |
146 | length = 4; | ||
147 | /* one medium, one transport... (maybe you do it better) */ | 239 | /* one medium, one transport... (maybe you do it better) */ |
148 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 240 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); |
149 | rndis_per_dev_params [configNr].medium); | ||
150 | retval = 0; | 241 | retval = 0; |
151 | break; | 242 | break; |
152 | 243 | ||
@@ -154,25 +245,21 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
154 | case OID_GEN_MAXIMUM_FRAME_SIZE: | 245 | case OID_GEN_MAXIMUM_FRAME_SIZE: |
155 | DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); | 246 | DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); |
156 | if (rndis_per_dev_params [configNr].dev) { | 247 | if (rndis_per_dev_params [configNr].dev) { |
157 | length = 4; | 248 | *outbuf = cpu_to_le32 ( |
158 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
159 | rndis_per_dev_params [configNr].dev->mtu); | 249 | rndis_per_dev_params [configNr].dev->mtu); |
160 | retval = 0; | 250 | retval = 0; |
161 | } else { | ||
162 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
163 | retval = 0; | ||
164 | } | 251 | } |
165 | break; | 252 | break; |
166 | 253 | ||
167 | /* mandatory */ | 254 | /* mandatory */ |
168 | case OID_GEN_LINK_SPEED: | 255 | case OID_GEN_LINK_SPEED: |
169 | // DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__); | 256 | if (rndis_debug > 1) |
170 | length = 4; | 257 | DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__); |
171 | if (rndis_per_dev_params [configNr].media_state | 258 | if (rndis_per_dev_params [configNr].media_state |
172 | == NDIS_MEDIA_STATE_DISCONNECTED) | 259 | == NDIS_MEDIA_STATE_DISCONNECTED) |
173 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 260 | *outbuf = __constant_cpu_to_le32 (0); |
174 | else | 261 | else |
175 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 262 | *outbuf = cpu_to_le32 ( |
176 | rndis_per_dev_params [configNr].speed); | 263 | rndis_per_dev_params [configNr].speed); |
177 | retval = 0; | 264 | retval = 0; |
178 | break; | 265 | break; |
@@ -181,8 +268,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
181 | case OID_GEN_TRANSMIT_BLOCK_SIZE: | 268 | case OID_GEN_TRANSMIT_BLOCK_SIZE: |
182 | DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__); | 269 | DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__); |
183 | if (rndis_per_dev_params [configNr].dev) { | 270 | if (rndis_per_dev_params [configNr].dev) { |
184 | length = 4; | 271 | *outbuf = cpu_to_le32 ( |
185 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
186 | rndis_per_dev_params [configNr].dev->mtu); | 272 | rndis_per_dev_params [configNr].dev->mtu); |
187 | retval = 0; | 273 | retval = 0; |
188 | } | 274 | } |
@@ -192,8 +278,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
192 | case OID_GEN_RECEIVE_BLOCK_SIZE: | 278 | case OID_GEN_RECEIVE_BLOCK_SIZE: |
193 | DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); | 279 | DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); |
194 | if (rndis_per_dev_params [configNr].dev) { | 280 | if (rndis_per_dev_params [configNr].dev) { |
195 | length = 4; | 281 | *outbuf = cpu_to_le32 ( |
196 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
197 | rndis_per_dev_params [configNr].dev->mtu); | 282 | rndis_per_dev_params [configNr].dev->mtu); |
198 | retval = 0; | 283 | retval = 0; |
199 | } | 284 | } |
@@ -202,8 +287,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
202 | /* mandatory */ | 287 | /* mandatory */ |
203 | case OID_GEN_VENDOR_ID: | 288 | case OID_GEN_VENDOR_ID: |
204 | DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); | 289 | DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); |
205 | length = 4; | 290 | *outbuf = cpu_to_le32 ( |
206 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
207 | rndis_per_dev_params [configNr].vendorID); | 291 | rndis_per_dev_params [configNr].vendorID); |
208 | retval = 0; | 292 | retval = 0; |
209 | break; | 293 | break; |
@@ -212,51 +296,44 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
212 | case OID_GEN_VENDOR_DESCRIPTION: | 296 | case OID_GEN_VENDOR_DESCRIPTION: |
213 | DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); | 297 | DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); |
214 | length = strlen (rndis_per_dev_params [configNr].vendorDescr); | 298 | length = strlen (rndis_per_dev_params [configNr].vendorDescr); |
215 | memcpy ((u8 *) resp + 24, | 299 | memcpy (outbuf, |
216 | rndis_per_dev_params [configNr].vendorDescr, length); | 300 | rndis_per_dev_params [configNr].vendorDescr, length); |
217 | retval = 0; | 301 | retval = 0; |
218 | break; | 302 | break; |
219 | 303 | ||
220 | case OID_GEN_VENDOR_DRIVER_VERSION: | 304 | case OID_GEN_VENDOR_DRIVER_VERSION: |
221 | DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); | 305 | DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); |
222 | length = 4; | ||
223 | /* Created as LE */ | 306 | /* Created as LE */ |
224 | *((__le32 *) resp + 6) = rndis_driver_version; | 307 | *outbuf = rndis_driver_version; |
225 | retval = 0; | 308 | retval = 0; |
226 | break; | 309 | break; |
227 | 310 | ||
228 | /* mandatory */ | 311 | /* mandatory */ |
229 | case OID_GEN_CURRENT_PACKET_FILTER: | 312 | case OID_GEN_CURRENT_PACKET_FILTER: |
230 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__); | 313 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__); |
231 | length = 4; | 314 | *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter); |
232 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
233 | rndis_per_dev_params[configNr].filter); | ||
234 | retval = 0; | 315 | retval = 0; |
235 | break; | 316 | break; |
236 | 317 | ||
237 | /* mandatory */ | 318 | /* mandatory */ |
238 | case OID_GEN_MAXIMUM_TOTAL_SIZE: | 319 | case OID_GEN_MAXIMUM_TOTAL_SIZE: |
239 | DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__); | 320 | DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__); |
240 | length = 4; | 321 | *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE); |
241 | *((__le32 *) resp + 6) = __constant_cpu_to_le32( | ||
242 | RNDIS_MAX_TOTAL_SIZE); | ||
243 | retval = 0; | 322 | retval = 0; |
244 | break; | 323 | break; |
245 | 324 | ||
246 | /* mandatory */ | 325 | /* mandatory */ |
247 | case OID_GEN_MEDIA_CONNECT_STATUS: | 326 | case OID_GEN_MEDIA_CONNECT_STATUS: |
248 | DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__); | 327 | if (rndis_debug > 1) |
249 | length = 4; | 328 | DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__); |
250 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 329 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
251 | rndis_per_dev_params [configNr] | ||
252 | .media_state); | 330 | .media_state); |
253 | retval = 0; | 331 | retval = 0; |
254 | break; | 332 | break; |
255 | 333 | ||
256 | case OID_GEN_PHYSICAL_MEDIUM: | 334 | case OID_GEN_PHYSICAL_MEDIUM: |
257 | DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); | 335 | DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); |
258 | length = 4; | 336 | *outbuf = __constant_cpu_to_le32 (0); |
259 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
260 | retval = 0; | 337 | retval = 0; |
261 | break; | 338 | break; |
262 | 339 | ||
@@ -266,8 +343,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
266 | */ | 343 | */ |
267 | case OID_GEN_MAC_OPTIONS: /* from WinME */ | 344 | case OID_GEN_MAC_OPTIONS: /* from WinME */ |
268 | DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); | 345 | DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); |
269 | length = 4; | 346 | *outbuf = __constant_cpu_to_le32( |
270 | *((__le32 *) resp + 6) = __constant_cpu_to_le32( | ||
271 | NDIS_MAC_OPTION_RECEIVE_SERIALIZED | 347 | NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
272 | | NDIS_MAC_OPTION_FULL_DUPLEX); | 348 | | NDIS_MAC_OPTION_FULL_DUPLEX); |
273 | retval = 0; | 349 | retval = 0; |
@@ -277,62 +353,49 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
277 | 353 | ||
278 | /* mandatory */ | 354 | /* mandatory */ |
279 | case OID_GEN_XMIT_OK: | 355 | case OID_GEN_XMIT_OK: |
280 | DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); | 356 | if (rndis_debug > 1) |
357 | DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); | ||
281 | if (rndis_per_dev_params [configNr].stats) { | 358 | if (rndis_per_dev_params [configNr].stats) { |
282 | length = 4; | 359 | *outbuf = cpu_to_le32 ( |
283 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
284 | rndis_per_dev_params [configNr].stats->tx_packets - | 360 | rndis_per_dev_params [configNr].stats->tx_packets - |
285 | rndis_per_dev_params [configNr].stats->tx_errors - | 361 | rndis_per_dev_params [configNr].stats->tx_errors - |
286 | rndis_per_dev_params [configNr].stats->tx_dropped); | 362 | rndis_per_dev_params [configNr].stats->tx_dropped); |
287 | retval = 0; | 363 | retval = 0; |
288 | } else { | ||
289 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
290 | retval = 0; | ||
291 | } | 364 | } |
292 | break; | 365 | break; |
293 | 366 | ||
294 | /* mandatory */ | 367 | /* mandatory */ |
295 | case OID_GEN_RCV_OK: | 368 | case OID_GEN_RCV_OK: |
296 | DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); | 369 | if (rndis_debug > 1) |
370 | DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); | ||
297 | if (rndis_per_dev_params [configNr].stats) { | 371 | if (rndis_per_dev_params [configNr].stats) { |
298 | length = 4; | 372 | *outbuf = cpu_to_le32 ( |
299 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
300 | rndis_per_dev_params [configNr].stats->rx_packets - | 373 | rndis_per_dev_params [configNr].stats->rx_packets - |
301 | rndis_per_dev_params [configNr].stats->rx_errors - | 374 | rndis_per_dev_params [configNr].stats->rx_errors - |
302 | rndis_per_dev_params [configNr].stats->rx_dropped); | 375 | rndis_per_dev_params [configNr].stats->rx_dropped); |
303 | retval = 0; | 376 | retval = 0; |
304 | } else { | ||
305 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
306 | retval = 0; | ||
307 | } | 377 | } |
308 | break; | 378 | break; |
309 | 379 | ||
310 | /* mandatory */ | 380 | /* mandatory */ |
311 | case OID_GEN_XMIT_ERROR: | 381 | case OID_GEN_XMIT_ERROR: |
312 | DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__); | 382 | if (rndis_debug > 1) |
383 | DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__); | ||
313 | if (rndis_per_dev_params [configNr].stats) { | 384 | if (rndis_per_dev_params [configNr].stats) { |
314 | length = 4; | 385 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
315 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
316 | rndis_per_dev_params [configNr] | ||
317 | .stats->tx_errors); | 386 | .stats->tx_errors); |
318 | retval = 0; | 387 | retval = 0; |
319 | } else { | ||
320 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
321 | retval = 0; | ||
322 | } | 388 | } |
323 | break; | 389 | break; |
324 | 390 | ||
325 | /* mandatory */ | 391 | /* mandatory */ |
326 | case OID_GEN_RCV_ERROR: | 392 | case OID_GEN_RCV_ERROR: |
327 | DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__); | 393 | if (rndis_debug > 1) |
394 | DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__); | ||
328 | if (rndis_per_dev_params [configNr].stats) { | 395 | if (rndis_per_dev_params [configNr].stats) { |
329 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 396 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
330 | rndis_per_dev_params [configNr] | ||
331 | .stats->rx_errors); | 397 | .stats->rx_errors); |
332 | retval = 0; | 398 | retval = 0; |
333 | } else { | ||
334 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
335 | retval = 0; | ||
336 | } | 399 | } |
337 | break; | 400 | break; |
338 | 401 | ||
@@ -340,13 +403,9 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
340 | case OID_GEN_RCV_NO_BUFFER: | 403 | case OID_GEN_RCV_NO_BUFFER: |
341 | DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); | 404 | DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); |
342 | if (rndis_per_dev_params [configNr].stats) { | 405 | if (rndis_per_dev_params [configNr].stats) { |
343 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 406 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
344 | rndis_per_dev_params [configNr] | ||
345 | .stats->rx_dropped); | 407 | .stats->rx_dropped); |
346 | retval = 0; | 408 | retval = 0; |
347 | } else { | ||
348 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
349 | retval = 0; | ||
350 | } | 409 | } |
351 | break; | 410 | break; |
352 | 411 | ||
@@ -359,8 +418,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
359 | * divided by weight of Alpha Centauri | 418 | * divided by weight of Alpha Centauri |
360 | */ | 419 | */ |
361 | if (rndis_per_dev_params [configNr].stats) { | 420 | if (rndis_per_dev_params [configNr].stats) { |
362 | length = 4; | 421 | *outbuf = cpu_to_le32 ( |
363 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
364 | (rndis_per_dev_params [configNr] | 422 | (rndis_per_dev_params [configNr] |
365 | .stats->tx_packets - | 423 | .stats->tx_packets - |
366 | rndis_per_dev_params [configNr] | 424 | rndis_per_dev_params [configNr] |
@@ -369,9 +427,6 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
369 | .stats->tx_dropped) | 427 | .stats->tx_dropped) |
370 | * 123); | 428 | * 123); |
371 | retval = 0; | 429 | retval = 0; |
372 | } else { | ||
373 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
374 | retval = 0; | ||
375 | } | 430 | } |
376 | break; | 431 | break; |
377 | 432 | ||
@@ -379,8 +434,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
379 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); | 434 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); |
380 | /* dito */ | 435 | /* dito */ |
381 | if (rndis_per_dev_params [configNr].stats) { | 436 | if (rndis_per_dev_params [configNr].stats) { |
382 | length = 4; | 437 | *outbuf = cpu_to_le32 ( |
383 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
384 | (rndis_per_dev_params [configNr] | 438 | (rndis_per_dev_params [configNr] |
385 | .stats->tx_packets - | 439 | .stats->tx_packets - |
386 | rndis_per_dev_params [configNr] | 440 | rndis_per_dev_params [configNr] |
@@ -389,144 +443,105 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
389 | .stats->tx_dropped) | 443 | .stats->tx_dropped) |
390 | / 123); | 444 | / 123); |
391 | retval = 0; | 445 | retval = 0; |
392 | } else { | ||
393 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
394 | retval = 0; | ||
395 | } | 446 | } |
396 | break; | 447 | break; |
397 | 448 | ||
398 | case OID_GEN_MULTICAST_BYTES_XMIT: | 449 | case OID_GEN_MULTICAST_BYTES_XMIT: |
399 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); | 450 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); |
400 | if (rndis_per_dev_params [configNr].stats) { | 451 | if (rndis_per_dev_params [configNr].stats) { |
401 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 452 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
402 | rndis_per_dev_params [configNr] | ||
403 | .stats->multicast*1234); | 453 | .stats->multicast*1234); |
404 | retval = 0; | 454 | retval = 0; |
405 | } else { | ||
406 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
407 | retval = 0; | ||
408 | } | 455 | } |
409 | break; | 456 | break; |
410 | 457 | ||
411 | case OID_GEN_MULTICAST_FRAMES_XMIT: | 458 | case OID_GEN_MULTICAST_FRAMES_XMIT: |
412 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); | 459 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); |
413 | if (rndis_per_dev_params [configNr].stats) { | 460 | if (rndis_per_dev_params [configNr].stats) { |
414 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 461 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
415 | rndis_per_dev_params [configNr] | ||
416 | .stats->multicast); | 462 | .stats->multicast); |
417 | retval = 0; | 463 | retval = 0; |
418 | } else { | ||
419 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
420 | retval = 0; | ||
421 | } | 464 | } |
422 | break; | 465 | break; |
423 | 466 | ||
424 | case OID_GEN_BROADCAST_BYTES_XMIT: | 467 | case OID_GEN_BROADCAST_BYTES_XMIT: |
425 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); | 468 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); |
426 | if (rndis_per_dev_params [configNr].stats) { | 469 | if (rndis_per_dev_params [configNr].stats) { |
427 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 470 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
428 | rndis_per_dev_params [configNr] | ||
429 | .stats->tx_packets/42*255); | 471 | .stats->tx_packets/42*255); |
430 | retval = 0; | 472 | retval = 0; |
431 | } else { | ||
432 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
433 | retval = 0; | ||
434 | } | 473 | } |
435 | break; | 474 | break; |
436 | 475 | ||
437 | case OID_GEN_BROADCAST_FRAMES_XMIT: | 476 | case OID_GEN_BROADCAST_FRAMES_XMIT: |
438 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); | 477 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); |
439 | if (rndis_per_dev_params [configNr].stats) { | 478 | if (rndis_per_dev_params [configNr].stats) { |
440 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 479 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
441 | rndis_per_dev_params [configNr] | ||
442 | .stats->tx_packets/42); | 480 | .stats->tx_packets/42); |
443 | retval = 0; | 481 | retval = 0; |
444 | } else { | ||
445 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
446 | retval = 0; | ||
447 | } | 482 | } |
448 | break; | 483 | break; |
449 | 484 | ||
450 | case OID_GEN_DIRECTED_BYTES_RCV: | 485 | case OID_GEN_DIRECTED_BYTES_RCV: |
451 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); | 486 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); |
452 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 487 | *outbuf = __constant_cpu_to_le32 (0); |
453 | retval = 0; | 488 | retval = 0; |
454 | break; | 489 | break; |
455 | 490 | ||
456 | case OID_GEN_DIRECTED_FRAMES_RCV: | 491 | case OID_GEN_DIRECTED_FRAMES_RCV: |
457 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); | 492 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); |
458 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 493 | *outbuf = __constant_cpu_to_le32 (0); |
459 | retval = 0; | 494 | retval = 0; |
460 | break; | 495 | break; |
461 | 496 | ||
462 | case OID_GEN_MULTICAST_BYTES_RCV: | 497 | case OID_GEN_MULTICAST_BYTES_RCV: |
463 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); | 498 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); |
464 | if (rndis_per_dev_params [configNr].stats) { | 499 | if (rndis_per_dev_params [configNr].stats) { |
465 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 500 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
466 | rndis_per_dev_params [configNr] | ||
467 | .stats->multicast * 1111); | 501 | .stats->multicast * 1111); |
468 | retval = 0; | 502 | retval = 0; |
469 | } else { | ||
470 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
471 | retval = 0; | ||
472 | } | 503 | } |
473 | break; | 504 | break; |
474 | 505 | ||
475 | case OID_GEN_MULTICAST_FRAMES_RCV: | 506 | case OID_GEN_MULTICAST_FRAMES_RCV: |
476 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); | 507 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); |
477 | if (rndis_per_dev_params [configNr].stats) { | 508 | if (rndis_per_dev_params [configNr].stats) { |
478 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 509 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
479 | rndis_per_dev_params [configNr] | ||
480 | .stats->multicast); | 510 | .stats->multicast); |
481 | retval = 0; | 511 | retval = 0; |
482 | } else { | ||
483 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
484 | retval = 0; | ||
485 | } | 512 | } |
486 | break; | 513 | break; |
487 | 514 | ||
488 | case OID_GEN_BROADCAST_BYTES_RCV: | 515 | case OID_GEN_BROADCAST_BYTES_RCV: |
489 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); | 516 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); |
490 | if (rndis_per_dev_params [configNr].stats) { | 517 | if (rndis_per_dev_params [configNr].stats) { |
491 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 518 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
492 | rndis_per_dev_params [configNr] | ||
493 | .stats->rx_packets/42*255); | 519 | .stats->rx_packets/42*255); |
494 | retval = 0; | 520 | retval = 0; |
495 | } else { | ||
496 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
497 | retval = 0; | ||
498 | } | 521 | } |
499 | break; | 522 | break; |
500 | 523 | ||
501 | case OID_GEN_BROADCAST_FRAMES_RCV: | 524 | case OID_GEN_BROADCAST_FRAMES_RCV: |
502 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); | 525 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); |
503 | if (rndis_per_dev_params [configNr].stats) { | 526 | if (rndis_per_dev_params [configNr].stats) { |
504 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 527 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
505 | rndis_per_dev_params [configNr] | ||
506 | .stats->rx_packets/42); | 528 | .stats->rx_packets/42); |
507 | retval = 0; | 529 | retval = 0; |
508 | } else { | ||
509 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
510 | retval = 0; | ||
511 | } | 530 | } |
512 | break; | 531 | break; |
513 | 532 | ||
514 | case OID_GEN_RCV_CRC_ERROR: | 533 | case OID_GEN_RCV_CRC_ERROR: |
515 | DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); | 534 | DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); |
516 | if (rndis_per_dev_params [configNr].stats) { | 535 | if (rndis_per_dev_params [configNr].stats) { |
517 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 536 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
518 | rndis_per_dev_params [configNr] | ||
519 | .stats->rx_crc_errors); | 537 | .stats->rx_crc_errors); |
520 | retval = 0; | 538 | retval = 0; |
521 | } else { | ||
522 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
523 | retval = 0; | ||
524 | } | 539 | } |
525 | break; | 540 | break; |
526 | 541 | ||
527 | case OID_GEN_TRANSMIT_QUEUE_LENGTH: | 542 | case OID_GEN_TRANSMIT_QUEUE_LENGTH: |
528 | DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); | 543 | DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); |
529 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 544 | *outbuf = __constant_cpu_to_le32 (0); |
530 | retval = 0; | 545 | retval = 0; |
531 | break; | 546 | break; |
532 | #endif /* RNDIS_OPTIONAL_STATS */ | 547 | #endif /* RNDIS_OPTIONAL_STATS */ |
@@ -538,13 +553,10 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
538 | DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__); | 553 | DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__); |
539 | if (rndis_per_dev_params [configNr].dev) { | 554 | if (rndis_per_dev_params [configNr].dev) { |
540 | length = ETH_ALEN; | 555 | length = ETH_ALEN; |
541 | memcpy ((u8 *) resp + 24, | 556 | memcpy (outbuf, |
542 | rndis_per_dev_params [configNr].host_mac, | 557 | rndis_per_dev_params [configNr].host_mac, |
543 | length); | 558 | length); |
544 | retval = 0; | 559 | retval = 0; |
545 | } else { | ||
546 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
547 | retval = 0; | ||
548 | } | 560 | } |
549 | break; | 561 | break; |
550 | 562 | ||
@@ -553,7 +565,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
553 | DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); | 565 | DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); |
554 | if (rndis_per_dev_params [configNr].dev) { | 566 | if (rndis_per_dev_params [configNr].dev) { |
555 | length = ETH_ALEN; | 567 | length = ETH_ALEN; |
556 | memcpy ((u8 *) resp + 24, | 568 | memcpy (outbuf, |
557 | rndis_per_dev_params [configNr].host_mac, | 569 | rndis_per_dev_params [configNr].host_mac, |
558 | length); | 570 | length); |
559 | retval = 0; | 571 | retval = 0; |
@@ -563,18 +575,16 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
563 | /* mandatory */ | 575 | /* mandatory */ |
564 | case OID_802_3_MULTICAST_LIST: | 576 | case OID_802_3_MULTICAST_LIST: |
565 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); | 577 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); |
566 | length = 4; | ||
567 | /* Multicast base address only */ | 578 | /* Multicast base address only */ |
568 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000); | 579 | *outbuf = __constant_cpu_to_le32 (0xE0000000); |
569 | retval = 0; | 580 | retval = 0; |
570 | break; | 581 | break; |
571 | 582 | ||
572 | /* mandatory */ | 583 | /* mandatory */ |
573 | case OID_802_3_MAXIMUM_LIST_SIZE: | 584 | case OID_802_3_MAXIMUM_LIST_SIZE: |
574 | DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); | 585 | DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); |
575 | length = 4; | ||
576 | /* Multicast base address only */ | 586 | /* Multicast base address only */ |
577 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (1); | 587 | *outbuf = __constant_cpu_to_le32 (1); |
578 | retval = 0; | 588 | retval = 0; |
579 | break; | 589 | break; |
580 | 590 | ||
@@ -587,11 +597,8 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
587 | /* mandatory */ | 597 | /* mandatory */ |
588 | case OID_802_3_RCV_ERROR_ALIGNMENT: | 598 | case OID_802_3_RCV_ERROR_ALIGNMENT: |
589 | DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__); | 599 | DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__); |
590 | if (rndis_per_dev_params [configNr].stats) | 600 | if (rndis_per_dev_params [configNr].stats) { |
591 | { | 601 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
592 | length = 4; | ||
593 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
594 | rndis_per_dev_params [configNr] | ||
595 | .stats->rx_frame_errors); | 602 | .stats->rx_frame_errors); |
596 | retval = 0; | 603 | retval = 0; |
597 | } | 604 | } |
@@ -600,16 +607,14 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
600 | /* mandatory */ | 607 | /* mandatory */ |
601 | case OID_802_3_XMIT_ONE_COLLISION: | 608 | case OID_802_3_XMIT_ONE_COLLISION: |
602 | DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); | 609 | DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); |
603 | length = 4; | 610 | *outbuf = __constant_cpu_to_le32 (0); |
604 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
605 | retval = 0; | 611 | retval = 0; |
606 | break; | 612 | break; |
607 | 613 | ||
608 | /* mandatory */ | 614 | /* mandatory */ |
609 | case OID_802_3_XMIT_MORE_COLLISIONS: | 615 | case OID_802_3_XMIT_MORE_COLLISIONS: |
610 | DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); | 616 | DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); |
611 | length = 4; | 617 | *outbuf = __constant_cpu_to_le32 (0); |
612 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
613 | retval = 0; | 618 | retval = 0; |
614 | break; | 619 | break; |
615 | 620 | ||
@@ -655,27 +660,18 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
655 | case OID_PNP_CAPABILITIES: | 660 | case OID_PNP_CAPABILITIES: |
656 | DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__); | 661 | DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__); |
657 | 662 | ||
658 | /* just PM, and remote wakeup on link status change | 663 | /* for now, no wakeup capabilities */ |
659 | * (not magic packet or pattern match) | ||
660 | */ | ||
661 | length = sizeof (struct NDIS_PNP_CAPABILITIES); | 664 | length = sizeof (struct NDIS_PNP_CAPABILITIES); |
662 | memset (resp, 0, length); | 665 | memset(outbuf, 0, length); |
663 | { | ||
664 | struct NDIS_PNP_CAPABILITIES *caps = (void *) resp; | ||
665 | |||
666 | caps->Flags = NDIS_DEVICE_WAKE_UP_ENABLE; | ||
667 | caps->WakeUpCapabilities.MinLinkChangeWakeUp | ||
668 | = NdisDeviceStateD3; | ||
669 | |||
670 | /* FIXME then use usb_gadget_wakeup(), and | ||
671 | * set USB_CONFIG_ATT_WAKEUP in config desc | ||
672 | */ | ||
673 | } | ||
674 | retval = 0; | 666 | retval = 0; |
675 | break; | 667 | break; |
676 | case OID_PNP_QUERY_POWER: | 668 | case OID_PNP_QUERY_POWER: |
677 | DEBUG("%s: OID_PNP_QUERY_POWER\n", __FUNCTION__); | 669 | DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__, |
678 | /* sure, handle any power state that maps to USB suspend */ | 670 | le32_to_cpup((__le32 *) buf) - 1); |
671 | /* only suspend is a real power state, and | ||
672 | * it can't be entered by OID_PNP_SET_POWER... | ||
673 | */ | ||
674 | length = 0; | ||
679 | retval = 0; | 675 | retval = 0; |
680 | break; | 676 | break; |
681 | #endif | 677 | #endif |
@@ -684,11 +680,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
684 | printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", | 680 | printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", |
685 | __FUNCTION__, OID); | 681 | __FUNCTION__, OID); |
686 | } | 682 | } |
683 | if (retval < 0) | ||
684 | length = 0; | ||
687 | 685 | ||
688 | resp->InformationBufferOffset = __constant_cpu_to_le32 (16); | ||
689 | resp->InformationBufferLength = cpu_to_le32 (length); | 686 | resp->InformationBufferLength = cpu_to_le32 (length); |
690 | resp->MessageLength = cpu_to_le32 (24 + length); | 687 | r->length = length + sizeof *resp; |
691 | r->length = 24 + length; | 688 | resp->MessageLength = cpu_to_le32 (r->length); |
692 | return retval; | 689 | return retval; |
693 | } | 690 | } |
694 | 691 | ||
@@ -705,45 +702,40 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, | |||
705 | if (!resp) | 702 | if (!resp) |
706 | return -ENOMEM; | 703 | return -ENOMEM; |
707 | 704 | ||
708 | DEBUG("set OID %08x value, len %d:\n", OID, buf_len); | 705 | if (buf_len && rndis_debug > 1) { |
709 | for (i = 0; i < buf_len; i += 16) { | 706 | DEBUG("set OID %08x value, len %d:\n", OID, buf_len); |
710 | DEBUG ("%03d: " | 707 | for (i = 0; i < buf_len; i += 16) { |
711 | " %02x %02x %02x %02x" | 708 | DEBUG ("%03d: %08x %08x %08x %08x\n", i, |
712 | " %02x %02x %02x %02x" | 709 | le32_to_cpup((__le32 *)&buf[i]), |
713 | " %02x %02x %02x %02x" | 710 | le32_to_cpup((__le32 *)&buf[i + 4]), |
714 | " %02x %02x %02x %02x" | 711 | le32_to_cpup((__le32 *)&buf[i + 8]), |
715 | "\n", | 712 | le32_to_cpup((__le32 *)&buf[i + 12])); |
716 | i, | 713 | } |
717 | buf[i], buf [i+1], | ||
718 | buf[i+2], buf[i+3], | ||
719 | buf[i+4], buf [i+5], | ||
720 | buf[i+6], buf[i+7], | ||
721 | buf[i+8], buf [i+9], | ||
722 | buf[i+10], buf[i+11], | ||
723 | buf[i+12], buf [i+13], | ||
724 | buf[i+14], buf[i+15]); | ||
725 | } | 714 | } |
726 | 715 | ||
716 | params = &rndis_per_dev_params [configNr]; | ||
727 | switch (OID) { | 717 | switch (OID) { |
728 | case OID_GEN_CURRENT_PACKET_FILTER: | 718 | case OID_GEN_CURRENT_PACKET_FILTER: |
729 | params = &rndis_per_dev_params [configNr]; | ||
730 | retval = 0; | ||
731 | 719 | ||
732 | /* FIXME use these NDIS_PACKET_TYPE_* bitflags to | 720 | /* these NDIS_PACKET_TYPE_* bitflags are shared with |
733 | * set the cdc_filter; it's not RNDIS-specific | 721 | * cdc_filter; it's not RNDIS-specific |
734 | * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: | 722 | * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: |
735 | * PROMISCUOUS, DIRECTED, | 723 | * PROMISCUOUS, DIRECTED, |
736 | * MULTICAST, ALL_MULTICAST, BROADCAST | 724 | * MULTICAST, ALL_MULTICAST, BROADCAST |
737 | */ | 725 | */ |
738 | params->filter = le32_to_cpup((__le32 *)buf); | 726 | *params->filter = (u16) le32_to_cpup((__le32 *)buf); |
739 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", | 727 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", |
740 | __FUNCTION__, params->filter); | 728 | __FUNCTION__, *params->filter); |
741 | 729 | ||
742 | /* this call has a significant side effect: it's | 730 | /* this call has a significant side effect: it's |
743 | * what makes the packet flow start and stop, like | 731 | * what makes the packet flow start and stop, like |
744 | * activating the CDC Ethernet altsetting. | 732 | * activating the CDC Ethernet altsetting. |
745 | */ | 733 | */ |
746 | if (params->filter) { | 734 | #ifdef RNDIS_PM |
735 | update_linkstate: | ||
736 | #endif | ||
737 | retval = 0; | ||
738 | if (*params->filter) { | ||
747 | params->state = RNDIS_DATA_INITIALIZED; | 739 | params->state = RNDIS_DATA_INITIALIZED; |
748 | netif_carrier_on(params->dev); | 740 | netif_carrier_on(params->dev); |
749 | if (netif_running(params->dev)) | 741 | if (netif_running(params->dev)) |
@@ -776,21 +768,34 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, | |||
776 | 768 | ||
777 | #ifdef RNDIS_PM | 769 | #ifdef RNDIS_PM |
778 | case OID_PNP_SET_POWER: | 770 | case OID_PNP_SET_POWER: |
779 | DEBUG ("OID_PNP_SET_POWER\n"); | 771 | /* The only real power state is USB suspend, and RNDIS requests |
780 | /* sure, handle any power state that maps to USB suspend */ | 772 | * can't enter it; this one isn't really about power. After |
781 | retval = 0; | 773 | * resuming, Windows forces a reset, and then SET_POWER D0. |
782 | break; | 774 | * FIXME ... then things go batty; Windows wedges itself. |
783 | 775 | */ | |
784 | case OID_PNP_ENABLE_WAKE_UP: | 776 | i = le32_to_cpup((__force __le32 *)buf); |
785 | /* always-connected ... */ | 777 | DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1); |
786 | DEBUG ("OID_PNP_ENABLE_WAKE_UP\n"); | 778 | switch (i) { |
787 | retval = 0; | 779 | case NdisDeviceStateD0: |
780 | *params->filter = params->saved_filter; | ||
781 | goto update_linkstate; | ||
782 | case NdisDeviceStateD3: | ||
783 | case NdisDeviceStateD2: | ||
784 | case NdisDeviceStateD1: | ||
785 | params->saved_filter = *params->filter; | ||
786 | retval = 0; | ||
787 | break; | ||
788 | } | ||
788 | break; | 789 | break; |
789 | 790 | ||
790 | // no PM resume patterns supported (specified where?) | 791 | #ifdef RNDIS_WAKEUP |
791 | // so OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN always fails | 792 | // no wakeup support advertised, so wakeup OIDs always fail: |
793 | // - OID_PNP_ENABLE_WAKE_UP | ||
794 | // - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN | ||
792 | #endif | 795 | #endif |
793 | 796 | ||
797 | #endif /* RNDIS_PM */ | ||
798 | |||
794 | default: | 799 | default: |
795 | printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", | 800 | printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", |
796 | __FUNCTION__, OID, buf_len); | 801 | __FUNCTION__, OID, buf_len); |
@@ -811,13 +816,10 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf) | |||
811 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; | 816 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; |
812 | 817 | ||
813 | r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); | 818 | r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); |
814 | 819 | if (!r) | |
815 | if (!r) return -ENOMEM; | 820 | return -ENOMEM; |
816 | |||
817 | resp = (rndis_init_cmplt_type *) r->buf; | 821 | resp = (rndis_init_cmplt_type *) r->buf; |
818 | 822 | ||
819 | if (!resp) return -ENOMEM; | ||
820 | |||
821 | resp->MessageType = __constant_cpu_to_le32 ( | 823 | resp->MessageType = __constant_cpu_to_le32 ( |
822 | REMOTE_NDIS_INITIALIZE_CMPLT); | 824 | REMOTE_NDIS_INITIALIZE_CMPLT); |
823 | resp->MessageLength = __constant_cpu_to_le32 (52); | 825 | resp->MessageLength = __constant_cpu_to_le32 (52); |
@@ -857,20 +859,22 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) | |||
857 | * oid_supported_list is the largest answer | 859 | * oid_supported_list is the largest answer |
858 | */ | 860 | */ |
859 | r = rndis_add_response (configNr, sizeof (oid_supported_list)); | 861 | r = rndis_add_response (configNr, sizeof (oid_supported_list)); |
860 | 862 | if (!r) | |
861 | if (!r) return -ENOMEM; | 863 | return -ENOMEM; |
862 | resp = (rndis_query_cmplt_type *) r->buf; | 864 | resp = (rndis_query_cmplt_type *) r->buf; |
863 | 865 | ||
864 | if (!resp) return -ENOMEM; | ||
865 | |||
866 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); | 866 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); |
867 | resp->MessageLength = __constant_cpu_to_le32 (24); | ||
868 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ | 867 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ |
869 | 868 | ||
870 | if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), r)) { | 869 | if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), |
870 | le32_to_cpu(buf->InformationBufferOffset) | ||
871 | + 8 + (u8 *) buf, | ||
872 | le32_to_cpu(buf->InformationBufferLength), | ||
873 | r)) { | ||
871 | /* OID not supported */ | 874 | /* OID not supported */ |
872 | resp->Status = __constant_cpu_to_le32 ( | 875 | resp->Status = __constant_cpu_to_le32 ( |
873 | RNDIS_STATUS_NOT_SUPPORTED); | 876 | RNDIS_STATUS_NOT_SUPPORTED); |
877 | resp->MessageLength = __constant_cpu_to_le32 (sizeof *resp); | ||
874 | resp->InformationBufferLength = __constant_cpu_to_le32 (0); | 878 | resp->InformationBufferLength = __constant_cpu_to_le32 (0); |
875 | resp->InformationBufferOffset = __constant_cpu_to_le32 (0); | 879 | resp->InformationBufferOffset = __constant_cpu_to_le32 (0); |
876 | } else | 880 | } else |
@@ -889,10 +893,9 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) | |||
889 | rndis_resp_t *r; | 893 | rndis_resp_t *r; |
890 | 894 | ||
891 | r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); | 895 | r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); |
892 | 896 | if (!r) | |
893 | if (!r) return -ENOMEM; | 897 | return -ENOMEM; |
894 | resp = (rndis_set_cmplt_type *) r->buf; | 898 | resp = (rndis_set_cmplt_type *) r->buf; |
895 | if (!resp) return -ENOMEM; | ||
896 | 899 | ||
897 | BufLength = le32_to_cpu (buf->InformationBufferLength); | 900 | BufLength = le32_to_cpu (buf->InformationBufferLength); |
898 | BufOffset = le32_to_cpu (buf->InformationBufferOffset); | 901 | BufOffset = le32_to_cpu (buf->InformationBufferOffset); |
@@ -930,10 +933,9 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf) | |||
930 | rndis_resp_t *r; | 933 | rndis_resp_t *r; |
931 | 934 | ||
932 | r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); | 935 | r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); |
933 | 936 | if (!r) | |
934 | if (!r) return -ENOMEM; | 937 | return -ENOMEM; |
935 | resp = (rndis_reset_cmplt_type *) r->buf; | 938 | resp = (rndis_reset_cmplt_type *) r->buf; |
936 | if (!resp) return -ENOMEM; | ||
937 | 939 | ||
938 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); | 940 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); |
939 | resp->MessageLength = __constant_cpu_to_le32 (16); | 941 | resp->MessageLength = __constant_cpu_to_le32 (16); |
@@ -957,8 +959,9 @@ static int rndis_keepalive_response (int configNr, | |||
957 | /* host "should" check only in RNDIS_DATA_INITIALIZED state */ | 959 | /* host "should" check only in RNDIS_DATA_INITIALIZED state */ |
958 | 960 | ||
959 | r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type)); | 961 | r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type)); |
962 | if (!r) | ||
963 | return -ENOMEM; | ||
960 | resp = (rndis_keepalive_cmplt_type *) r->buf; | 964 | resp = (rndis_keepalive_cmplt_type *) r->buf; |
961 | if (!resp) return -ENOMEM; | ||
962 | 965 | ||
963 | resp->MessageType = __constant_cpu_to_le32 ( | 966 | resp->MessageType = __constant_cpu_to_le32 ( |
964 | REMOTE_NDIS_KEEPALIVE_CMPLT); | 967 | REMOTE_NDIS_KEEPALIVE_CMPLT); |
@@ -987,10 +990,9 @@ static int rndis_indicate_status_msg (int configNr, u32 status) | |||
987 | 990 | ||
988 | r = rndis_add_response (configNr, | 991 | r = rndis_add_response (configNr, |
989 | sizeof (rndis_indicate_status_msg_type)); | 992 | sizeof (rndis_indicate_status_msg_type)); |
990 | if (!r) return -ENOMEM; | 993 | if (!r) |
991 | 994 | return -ENOMEM; | |
992 | resp = (rndis_indicate_status_msg_type *) r->buf; | 995 | resp = (rndis_indicate_status_msg_type *) r->buf; |
993 | if (!resp) return -ENOMEM; | ||
994 | 996 | ||
995 | resp->MessageType = __constant_cpu_to_le32 ( | 997 | resp->MessageType = __constant_cpu_to_le32 ( |
996 | REMOTE_NDIS_INDICATE_STATUS_MSG); | 998 | REMOTE_NDIS_INDICATE_STATUS_MSG); |
@@ -1021,6 +1023,21 @@ int rndis_signal_disconnect (int configNr) | |||
1021 | RNDIS_STATUS_MEDIA_DISCONNECT); | 1023 | RNDIS_STATUS_MEDIA_DISCONNECT); |
1022 | } | 1024 | } |
1023 | 1025 | ||
1026 | void rndis_uninit (int configNr) | ||
1027 | { | ||
1028 | u8 *buf; | ||
1029 | u32 length; | ||
1030 | |||
1031 | if (configNr >= RNDIS_MAX_CONFIGS) | ||
1032 | return; | ||
1033 | rndis_per_dev_params [configNr].used = 0; | ||
1034 | rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED; | ||
1035 | |||
1036 | /* drain the response queue */ | ||
1037 | while ((buf = rndis_get_next_response(configNr, &length))) | ||
1038 | rndis_free_response(configNr, buf); | ||
1039 | } | ||
1040 | |||
1024 | void rndis_set_host_mac (int configNr, const u8 *addr) | 1041 | void rndis_set_host_mac (int configNr, const u8 *addr) |
1025 | { | 1042 | { |
1026 | rndis_per_dev_params [configNr].host_mac = addr; | 1043 | rndis_per_dev_params [configNr].host_mac = addr; |
@@ -1046,9 +1063,13 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1046 | return -ENOTSUPP; | 1063 | return -ENOTSUPP; |
1047 | params = &rndis_per_dev_params [configNr]; | 1064 | params = &rndis_per_dev_params [configNr]; |
1048 | 1065 | ||
1066 | /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for | ||
1067 | * rx/tx statistics and link status, in addition to KEEPALIVE traffic | ||
1068 | * and normal HC level polling to see if there's any IN traffic. | ||
1069 | */ | ||
1070 | |||
1049 | /* For USB: responses may take up to 10 seconds */ | 1071 | /* For USB: responses may take up to 10 seconds */ |
1050 | switch (MsgType) | 1072 | switch (MsgType) { |
1051 | { | ||
1052 | case REMOTE_NDIS_INITIALIZE_MSG: | 1073 | case REMOTE_NDIS_INITIALIZE_MSG: |
1053 | DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", | 1074 | DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", |
1054 | __FUNCTION__ ); | 1075 | __FUNCTION__ ); |
@@ -1082,10 +1103,9 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1082 | 1103 | ||
1083 | case REMOTE_NDIS_KEEPALIVE_MSG: | 1104 | case REMOTE_NDIS_KEEPALIVE_MSG: |
1084 | /* For USB: host does this every 5 seconds */ | 1105 | /* For USB: host does this every 5 seconds */ |
1085 | #ifdef VERBOSE | 1106 | if (rndis_debug > 1) |
1086 | DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", | 1107 | DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", |
1087 | __FUNCTION__ ); | 1108 | __FUNCTION__ ); |
1088 | #endif | ||
1089 | return rndis_keepalive_response (configNr, | 1109 | return rndis_keepalive_response (configNr, |
1090 | (rndis_keepalive_msg_type *) | 1110 | (rndis_keepalive_msg_type *) |
1091 | buf); | 1111 | buf); |
@@ -1152,7 +1172,8 @@ void rndis_deregister (int configNr) | |||
1152 | } | 1172 | } |
1153 | 1173 | ||
1154 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, | 1174 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, |
1155 | struct net_device_stats *stats) | 1175 | struct net_device_stats *stats, |
1176 | u16 *cdc_filter) | ||
1156 | { | 1177 | { |
1157 | DEBUG("%s:\n", __FUNCTION__ ); | 1178 | DEBUG("%s:\n", __FUNCTION__ ); |
1158 | if (!dev || !stats) return -1; | 1179 | if (!dev || !stats) return -1; |
@@ -1160,6 +1181,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev, | |||
1160 | 1181 | ||
1161 | rndis_per_dev_params [configNr].dev = dev; | 1182 | rndis_per_dev_params [configNr].dev = dev; |
1162 | rndis_per_dev_params [configNr].stats = stats; | 1183 | rndis_per_dev_params [configNr].stats = stats; |
1184 | rndis_per_dev_params [configNr].filter = cdc_filter; | ||
1163 | 1185 | ||
1164 | return 0; | 1186 | return 0; |
1165 | } | 1187 | } |
@@ -1178,7 +1200,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) | |||
1178 | 1200 | ||
1179 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) | 1201 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) |
1180 | { | 1202 | { |
1181 | DEBUG("%s:\n", __FUNCTION__ ); | 1203 | DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed); |
1182 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; | 1204 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; |
1183 | 1205 | ||
1184 | rndis_per_dev_params [configNr].medium = medium; | 1206 | rndis_per_dev_params [configNr].medium = medium; |
@@ -1242,6 +1264,7 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length) | |||
1242 | { | 1264 | { |
1243 | rndis_resp_t *r; | 1265 | rndis_resp_t *r; |
1244 | 1266 | ||
1267 | /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ | ||
1245 | r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); | 1268 | r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); |
1246 | if (!r) return NULL; | 1269 | if (!r) return NULL; |
1247 | 1270 | ||
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index 2b5b55df3cfd..95b4c6326100 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h | |||
@@ -69,90 +69,6 @@ | |||
69 | #define OID_PNP_ENABLE_WAKE_UP 0xFD010106 | 69 | #define OID_PNP_ENABLE_WAKE_UP 0xFD010106 |
70 | 70 | ||
71 | 71 | ||
72 | /* supported OIDs */ | ||
73 | static const u32 oid_supported_list [] = | ||
74 | { | ||
75 | /* the general stuff */ | ||
76 | OID_GEN_SUPPORTED_LIST, | ||
77 | OID_GEN_HARDWARE_STATUS, | ||
78 | OID_GEN_MEDIA_SUPPORTED, | ||
79 | OID_GEN_MEDIA_IN_USE, | ||
80 | OID_GEN_MAXIMUM_FRAME_SIZE, | ||
81 | OID_GEN_LINK_SPEED, | ||
82 | OID_GEN_TRANSMIT_BLOCK_SIZE, | ||
83 | OID_GEN_RECEIVE_BLOCK_SIZE, | ||
84 | OID_GEN_VENDOR_ID, | ||
85 | OID_GEN_VENDOR_DESCRIPTION, | ||
86 | OID_GEN_VENDOR_DRIVER_VERSION, | ||
87 | OID_GEN_CURRENT_PACKET_FILTER, | ||
88 | OID_GEN_MAXIMUM_TOTAL_SIZE, | ||
89 | OID_GEN_MEDIA_CONNECT_STATUS, | ||
90 | OID_GEN_PHYSICAL_MEDIUM, | ||
91 | #if 0 | ||
92 | OID_GEN_RNDIS_CONFIG_PARAMETER, | ||
93 | #endif | ||
94 | |||
95 | /* the statistical stuff */ | ||
96 | OID_GEN_XMIT_OK, | ||
97 | OID_GEN_RCV_OK, | ||
98 | OID_GEN_XMIT_ERROR, | ||
99 | OID_GEN_RCV_ERROR, | ||
100 | OID_GEN_RCV_NO_BUFFER, | ||
101 | #ifdef RNDIS_OPTIONAL_STATS | ||
102 | OID_GEN_DIRECTED_BYTES_XMIT, | ||
103 | OID_GEN_DIRECTED_FRAMES_XMIT, | ||
104 | OID_GEN_MULTICAST_BYTES_XMIT, | ||
105 | OID_GEN_MULTICAST_FRAMES_XMIT, | ||
106 | OID_GEN_BROADCAST_BYTES_XMIT, | ||
107 | OID_GEN_BROADCAST_FRAMES_XMIT, | ||
108 | OID_GEN_DIRECTED_BYTES_RCV, | ||
109 | OID_GEN_DIRECTED_FRAMES_RCV, | ||
110 | OID_GEN_MULTICAST_BYTES_RCV, | ||
111 | OID_GEN_MULTICAST_FRAMES_RCV, | ||
112 | OID_GEN_BROADCAST_BYTES_RCV, | ||
113 | OID_GEN_BROADCAST_FRAMES_RCV, | ||
114 | OID_GEN_RCV_CRC_ERROR, | ||
115 | OID_GEN_TRANSMIT_QUEUE_LENGTH, | ||
116 | #endif /* RNDIS_OPTIONAL_STATS */ | ||
117 | |||
118 | /* mandatory 802.3 */ | ||
119 | /* the general stuff */ | ||
120 | OID_802_3_PERMANENT_ADDRESS, | ||
121 | OID_802_3_CURRENT_ADDRESS, | ||
122 | OID_802_3_MULTICAST_LIST, | ||
123 | OID_802_3_MAC_OPTIONS, | ||
124 | OID_802_3_MAXIMUM_LIST_SIZE, | ||
125 | |||
126 | /* the statistical stuff */ | ||
127 | OID_802_3_RCV_ERROR_ALIGNMENT, | ||
128 | OID_802_3_XMIT_ONE_COLLISION, | ||
129 | OID_802_3_XMIT_MORE_COLLISIONS, | ||
130 | #ifdef RNDIS_OPTIONAL_STATS | ||
131 | OID_802_3_XMIT_DEFERRED, | ||
132 | OID_802_3_XMIT_MAX_COLLISIONS, | ||
133 | OID_802_3_RCV_OVERRUN, | ||
134 | OID_802_3_XMIT_UNDERRUN, | ||
135 | OID_802_3_XMIT_HEARTBEAT_FAILURE, | ||
136 | OID_802_3_XMIT_TIMES_CRS_LOST, | ||
137 | OID_802_3_XMIT_LATE_COLLISIONS, | ||
138 | #endif /* RNDIS_OPTIONAL_STATS */ | ||
139 | |||
140 | #ifdef RNDIS_PM | ||
141 | /* PM and wakeup are mandatory for USB: */ | ||
142 | |||
143 | /* power management */ | ||
144 | OID_PNP_CAPABILITIES, | ||
145 | OID_PNP_QUERY_POWER, | ||
146 | OID_PNP_SET_POWER, | ||
147 | |||
148 | /* wake up host */ | ||
149 | OID_PNP_ENABLE_WAKE_UP, | ||
150 | OID_PNP_ADD_WAKE_UP_PATTERN, | ||
151 | OID_PNP_REMOVE_WAKE_UP_PATTERN, | ||
152 | #endif | ||
153 | }; | ||
154 | |||
155 | |||
156 | typedef struct rndis_init_msg_type | 72 | typedef struct rndis_init_msg_type |
157 | { | 73 | { |
158 | __le32 MessageType; | 74 | __le32 MessageType; |
@@ -309,15 +225,18 @@ typedef struct rndis_resp_t | |||
309 | typedef struct rndis_params | 225 | typedef struct rndis_params |
310 | { | 226 | { |
311 | u8 confignr; | 227 | u8 confignr; |
312 | int used; | 228 | u8 used; |
229 | u16 saved_filter; | ||
313 | enum rndis_state state; | 230 | enum rndis_state state; |
314 | u32 filter; | ||
315 | u32 medium; | 231 | u32 medium; |
316 | u32 speed; | 232 | u32 speed; |
317 | u32 media_state; | 233 | u32 media_state; |
234 | |||
318 | const u8 *host_mac; | 235 | const u8 *host_mac; |
236 | u16 *filter; | ||
319 | struct net_device *dev; | 237 | struct net_device *dev; |
320 | struct net_device_stats *stats; | 238 | struct net_device_stats *stats; |
239 | |||
321 | u32 vendorID; | 240 | u32 vendorID; |
322 | const char *vendorDescr; | 241 | const char *vendorDescr; |
323 | int (*ack) (struct net_device *); | 242 | int (*ack) (struct net_device *); |
@@ -329,7 +248,8 @@ int rndis_msg_parser (u8 configNr, u8 *buf); | |||
329 | int rndis_register (int (*rndis_control_ack) (struct net_device *)); | 248 | int rndis_register (int (*rndis_control_ack) (struct net_device *)); |
330 | void rndis_deregister (int configNr); | 249 | void rndis_deregister (int configNr); |
331 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, | 250 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, |
332 | struct net_device_stats *stats); | 251 | struct net_device_stats *stats, |
252 | u16 *cdc_filter); | ||
333 | int rndis_set_param_vendor (u8 configNr, u32 vendorID, | 253 | int rndis_set_param_vendor (u8 configNr, u32 vendorID, |
334 | const char *vendorDescr); | 254 | const char *vendorDescr); |
335 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); | 255 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); |
@@ -338,6 +258,7 @@ int rndis_rm_hdr (struct sk_buff *skb); | |||
338 | u8 *rndis_get_next_response (int configNr, u32 *length); | 258 | u8 *rndis_get_next_response (int configNr, u32 *length); |
339 | void rndis_free_response (int configNr, u8 *buf); | 259 | void rndis_free_response (int configNr, u8 *buf); |
340 | 260 | ||
261 | void rndis_uninit (int configNr); | ||
341 | int rndis_signal_connect (int configNr); | 262 | int rndis_signal_connect (int configNr); |
342 | int rndis_signal_disconnect (int configNr); | 263 | int rndis_signal_disconnect (int configNr); |
343 | int rndis_state (int configNr); | 264 | int rndis_state (int configNr); |
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 4d591c764e38..9e4f1c6935a5 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -300,18 +300,18 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, | |||
300 | u8 type, unsigned int index, int is_otg); | 300 | u8 type, unsigned int index, int is_otg); |
301 | 301 | ||
302 | static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, | 302 | static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, |
303 | int kmalloc_flags); | 303 | unsigned kmalloc_flags); |
304 | static void gs_free_req(struct usb_ep *ep, struct usb_request *req); | 304 | static void gs_free_req(struct usb_ep *ep, struct usb_request *req); |
305 | 305 | ||
306 | static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, | 306 | static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, |
307 | int kmalloc_flags); | 307 | unsigned kmalloc_flags); |
308 | static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req); | 308 | static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req); |
309 | 309 | ||
310 | static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags); | 310 | static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags); |
311 | static void gs_free_ports(struct gs_dev *dev); | 311 | static void gs_free_ports(struct gs_dev *dev); |
312 | 312 | ||
313 | /* circular buffer */ | 313 | /* circular buffer */ |
314 | static struct gs_buf *gs_buf_alloc(unsigned int size, int kmalloc_flags); | 314 | static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags); |
315 | static void gs_buf_free(struct gs_buf *gb); | 315 | static void gs_buf_free(struct gs_buf *gb); |
316 | static void gs_buf_clear(struct gs_buf *gb); | 316 | static void gs_buf_clear(struct gs_buf *gb); |
317 | static unsigned int gs_buf_data_avail(struct gs_buf *gb); | 317 | static unsigned int gs_buf_data_avail(struct gs_buf *gb); |
@@ -1607,9 +1607,9 @@ static int gs_setup(struct usb_gadget *gadget, | |||
1607 | int ret = -EOPNOTSUPP; | 1607 | int ret = -EOPNOTSUPP; |
1608 | struct gs_dev *dev = get_gadget_data(gadget); | 1608 | struct gs_dev *dev = get_gadget_data(gadget); |
1609 | struct usb_request *req = dev->dev_ctrl_req; | 1609 | struct usb_request *req = dev->dev_ctrl_req; |
1610 | u16 wIndex = ctrl->wIndex; | 1610 | u16 wIndex = le16_to_cpu(ctrl->wIndex); |
1611 | u16 wValue = ctrl->wValue; | 1611 | u16 wValue = le16_to_cpu(ctrl->wValue); |
1612 | u16 wLength = ctrl->wLength; | 1612 | u16 wLength = le16_to_cpu(ctrl->wLength); |
1613 | 1613 | ||
1614 | switch (ctrl->bRequestType & USB_TYPE_MASK) { | 1614 | switch (ctrl->bRequestType & USB_TYPE_MASK) { |
1615 | case USB_TYPE_STANDARD: | 1615 | case USB_TYPE_STANDARD: |
@@ -1651,9 +1651,9 @@ static int gs_setup_standard(struct usb_gadget *gadget, | |||
1651 | int ret = -EOPNOTSUPP; | 1651 | int ret = -EOPNOTSUPP; |
1652 | struct gs_dev *dev = get_gadget_data(gadget); | 1652 | struct gs_dev *dev = get_gadget_data(gadget); |
1653 | struct usb_request *req = dev->dev_ctrl_req; | 1653 | struct usb_request *req = dev->dev_ctrl_req; |
1654 | u16 wIndex = ctrl->wIndex; | 1654 | u16 wIndex = le16_to_cpu(ctrl->wIndex); |
1655 | u16 wValue = ctrl->wValue; | 1655 | u16 wValue = le16_to_cpu(ctrl->wValue); |
1656 | u16 wLength = ctrl->wLength; | 1656 | u16 wLength = le16_to_cpu(ctrl->wLength); |
1657 | 1657 | ||
1658 | switch (ctrl->bRequest) { | 1658 | switch (ctrl->bRequest) { |
1659 | case USB_REQ_GET_DESCRIPTOR: | 1659 | case USB_REQ_GET_DESCRIPTOR: |
@@ -1782,9 +1782,9 @@ static int gs_setup_class(struct usb_gadget *gadget, | |||
1782 | struct gs_dev *dev = get_gadget_data(gadget); | 1782 | struct gs_dev *dev = get_gadget_data(gadget); |
1783 | struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ | 1783 | struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ |
1784 | struct usb_request *req = dev->dev_ctrl_req; | 1784 | struct usb_request *req = dev->dev_ctrl_req; |
1785 | u16 wIndex = ctrl->wIndex; | 1785 | u16 wIndex = le16_to_cpu(ctrl->wIndex); |
1786 | u16 wValue = ctrl->wValue; | 1786 | u16 wValue = le16_to_cpu(ctrl->wValue); |
1787 | u16 wLength = ctrl->wLength; | 1787 | u16 wLength = le16_to_cpu(ctrl->wLength); |
1788 | 1788 | ||
1789 | switch (ctrl->bRequest) { | 1789 | switch (ctrl->bRequest) { |
1790 | case USB_CDC_REQ_SET_LINE_CODING: | 1790 | case USB_CDC_REQ_SET_LINE_CODING: |
@@ -2119,7 +2119,8 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, | |||
2119 | * Allocate a usb_request and its buffer. Returns a pointer to the | 2119 | * Allocate a usb_request and its buffer. Returns a pointer to the |
2120 | * usb_request or NULL if there is an error. | 2120 | * usb_request or NULL if there is an error. |
2121 | */ | 2121 | */ |
2122 | static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, int kmalloc_flags) | 2122 | static struct usb_request * |
2123 | gs_alloc_req(struct usb_ep *ep, unsigned int len, unsigned kmalloc_flags) | ||
2123 | { | 2124 | { |
2124 | struct usb_request *req; | 2125 | struct usb_request *req; |
2125 | 2126 | ||
@@ -2159,7 +2160,8 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req) | |||
2159 | * Allocates a request and its buffer, using the given | 2160 | * Allocates a request and its buffer, using the given |
2160 | * endpoint, buffer len, and kmalloc flags. | 2161 | * endpoint, buffer len, and kmalloc flags. |
2161 | */ | 2162 | */ |
2162 | static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, int kmalloc_flags) | 2163 | static struct gs_req_entry * |
2164 | gs_alloc_req_entry(struct usb_ep *ep, unsigned len, unsigned kmalloc_flags) | ||
2163 | { | 2165 | { |
2164 | struct gs_req_entry *req; | 2166 | struct gs_req_entry *req; |
2165 | 2167 | ||
@@ -2200,7 +2202,7 @@ static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req) | |||
2200 | * | 2202 | * |
2201 | * The device lock is normally held when calling this function. | 2203 | * The device lock is normally held when calling this function. |
2202 | */ | 2204 | */ |
2203 | static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags) | 2205 | static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags) |
2204 | { | 2206 | { |
2205 | int i; | 2207 | int i; |
2206 | struct gs_port *port; | 2208 | struct gs_port *port; |
@@ -2282,7 +2284,7 @@ static void gs_free_ports(struct gs_dev *dev) | |||
2282 | * | 2284 | * |
2283 | * Allocate a circular buffer and all associated memory. | 2285 | * Allocate a circular buffer and all associated memory. |
2284 | */ | 2286 | */ |
2285 | static struct gs_buf *gs_buf_alloc(unsigned int size, int kmalloc_flags) | 2287 | static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags) |
2286 | { | 2288 | { |
2287 | struct gs_buf *gb; | 2289 | struct gs_buf *gb; |
2288 | 2290 | ||
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 6e49432071a1..a6e035e24479 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c | |||
@@ -919,9 +919,9 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
919 | struct zero_dev *dev = get_gadget_data (gadget); | 919 | struct zero_dev *dev = get_gadget_data (gadget); |
920 | struct usb_request *req = dev->req; | 920 | struct usb_request *req = dev->req; |
921 | int value = -EOPNOTSUPP; | 921 | int value = -EOPNOTSUPP; |
922 | u16 w_index = ctrl->wIndex; | 922 | u16 w_index = le16_to_cpu(ctrl->wIndex); |
923 | u16 w_value = ctrl->wValue; | 923 | u16 w_value = le16_to_cpu(ctrl->wValue); |
924 | u16 w_length = ctrl->wLength; | 924 | u16 w_length = le16_to_cpu(ctrl->wLength); |
925 | 925 | ||
926 | /* usually this stores reply data in the pre-allocated ep0 buffer, | 926 | /* usually this stores reply data in the pre-allocated ep0 buffer, |
927 | * but config change events will reconfigure hardware. | 927 | * but config change events will reconfigure hardware. |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 19e598c9641f..ed1899d307db 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -49,6 +49,19 @@ config USB_EHCI_ROOT_HUB_TT | |||
49 | 49 | ||
50 | This supports the EHCI implementation from TransDimension Inc. | 50 | This supports the EHCI implementation from TransDimension Inc. |
51 | 51 | ||
52 | config USB_ISP116X_HCD | ||
53 | tristate "ISP116X HCD support" | ||
54 | depends on USB | ||
55 | default N | ||
56 | ---help--- | ||
57 | The ISP1160 and ISP1161 chips are USB host controllers. Enable this | ||
58 | option if your board has this chip. If unsure, say N. | ||
59 | |||
60 | This driver does not support isochronous transfers. | ||
61 | |||
62 | To compile this driver as a module, choose M here: the | ||
63 | module will be called isp116x-hcd. | ||
64 | |||
52 | config USB_OHCI_HCD | 65 | config USB_OHCI_HCD |
53 | tristate "OHCI HCD support" | 66 | tristate "OHCI HCD support" |
54 | depends on USB && USB_ARCH_HAS_OHCI | 67 | depends on USB && USB_ARCH_HAS_OHCI |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 5dbd3e7a27c7..350d14fc1cc9 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o | 6 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o |
7 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | ||
7 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o | 8 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o |
8 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o | 9 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o |
9 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o | 10 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 2ff11d53567b..50cb01831075 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -254,7 +254,7 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) | |||
254 | } | 254 | } |
255 | 255 | ||
256 | return scnprintf (buf, len, | 256 | return scnprintf (buf, len, |
257 | "%s%sport %d status %06x%s%s sig=%s %s%s%s%s%s%s%s%s%s", | 257 | "%s%sport %d status %06x%s%s sig=%s%s%s%s%s%s%s%s%s%s", |
258 | label, label [0] ? " " : "", port, status, | 258 | label, label [0] ? " " : "", port, status, |
259 | (status & PORT_POWER) ? " POWER" : "", | 259 | (status & PORT_POWER) ? " POWER" : "", |
260 | (status & PORT_OWNER) ? " OWNER" : "", | 260 | (status & PORT_OWNER) ? " OWNER" : "", |
@@ -644,9 +644,11 @@ show_registers (struct class_device *class_dev, char *buf) | |||
644 | if (bus->controller->power.power_state) { | 644 | if (bus->controller->power.power_state) { |
645 | size = scnprintf (next, size, | 645 | size = scnprintf (next, size, |
646 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" | 646 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" |
647 | "%s\n" | ||
647 | "SUSPENDED (no register access)\n", | 648 | "SUSPENDED (no register access)\n", |
648 | hcd->self.controller->bus->name, | 649 | hcd->self.controller->bus->name, |
649 | hcd->self.controller->bus_id); | 650 | hcd->self.controller->bus_id, |
651 | hcd->product_desc); | ||
650 | goto done; | 652 | goto done; |
651 | } | 653 | } |
652 | 654 | ||
@@ -654,13 +656,53 @@ show_registers (struct class_device *class_dev, char *buf) | |||
654 | i = HC_VERSION(readl (&ehci->caps->hc_capbase)); | 656 | i = HC_VERSION(readl (&ehci->caps->hc_capbase)); |
655 | temp = scnprintf (next, size, | 657 | temp = scnprintf (next, size, |
656 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" | 658 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" |
659 | "%s\n" | ||
657 | "EHCI %x.%02x, hcd state %d\n", | 660 | "EHCI %x.%02x, hcd state %d\n", |
658 | hcd->self.controller->bus->name, | 661 | hcd->self.controller->bus->name, |
659 | hcd->self.controller->bus_id, | 662 | hcd->self.controller->bus_id, |
663 | hcd->product_desc, | ||
660 | i >> 8, i & 0x0ff, hcd->state); | 664 | i >> 8, i & 0x0ff, hcd->state); |
661 | size -= temp; | 665 | size -= temp; |
662 | next += temp; | 666 | next += temp; |
663 | 667 | ||
668 | #ifdef CONFIG_PCI | ||
669 | /* EHCI 0.96 and later may have "extended capabilities" */ | ||
670 | if (hcd->self.controller->bus == &pci_bus_type) { | ||
671 | struct pci_dev *pdev; | ||
672 | u32 offset, cap, cap2; | ||
673 | unsigned count = 256/4; | ||
674 | |||
675 | pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
676 | offset = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); | ||
677 | while (offset && count--) { | ||
678 | pci_read_config_dword (pdev, offset, &cap); | ||
679 | switch (cap & 0xff) { | ||
680 | case 1: | ||
681 | temp = scnprintf (next, size, | ||
682 | "ownership %08x%s%s\n", cap, | ||
683 | (cap & (1 << 24)) ? " linux" : "", | ||
684 | (cap & (1 << 16)) ? " firmware" : ""); | ||
685 | size -= temp; | ||
686 | next += temp; | ||
687 | |||
688 | offset += 4; | ||
689 | pci_read_config_dword (pdev, offset, &cap2); | ||
690 | temp = scnprintf (next, size, | ||
691 | "SMI sts/enable 0x%08x\n", cap2); | ||
692 | size -= temp; | ||
693 | next += temp; | ||
694 | break; | ||
695 | case 0: /* illegal reserved capability */ | ||
696 | cap = 0; | ||
697 | /* FALLTHROUGH */ | ||
698 | default: /* unknown */ | ||
699 | break; | ||
700 | } | ||
701 | temp = (cap >> 8) & 0xff; | ||
702 | } | ||
703 | } | ||
704 | #endif | ||
705 | |||
664 | // FIXME interpret both types of params | 706 | // FIXME interpret both types of params |
665 | i = readl (&ehci->caps->hcs_params); | 707 | i = readl (&ehci->caps->hcs_params); |
666 | temp = scnprintf (next, size, "structural params 0x%08x\n", i); | 708 | temp = scnprintf (next, size, "structural params 0x%08x\n", i); |
@@ -696,12 +738,19 @@ show_registers (struct class_device *class_dev, char *buf) | |||
696 | size -= temp; | 738 | size -= temp; |
697 | next += temp; | 739 | next += temp; |
698 | 740 | ||
699 | for (i = 0; i < HCS_N_PORTS (ehci->hcs_params); i++) { | 741 | for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { |
700 | temp = dbg_port_buf (scratch, sizeof scratch, label, i + 1, | 742 | temp = dbg_port_buf (scratch, sizeof scratch, label, i, |
701 | readl (&ehci->regs->port_status [i])); | 743 | readl (&ehci->regs->port_status [i - 1])); |
702 | temp = scnprintf (next, size, fmt, temp, scratch); | 744 | temp = scnprintf (next, size, fmt, temp, scratch); |
703 | size -= temp; | 745 | size -= temp; |
704 | next += temp; | 746 | next += temp; |
747 | if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { | ||
748 | temp = scnprintf (next, size, | ||
749 | " debug control %08x\n", | ||
750 | readl (&ehci->debug->control)); | ||
751 | size -= temp; | ||
752 | next += temp; | ||
753 | } | ||
705 | } | 754 | } |
706 | 755 | ||
707 | if (ehci->reclaim) { | 756 | if (ehci->reclaim) { |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index bc69bd7acebe..35248a37b717 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -304,30 +304,31 @@ static void ehci_watchdog (unsigned long param) | |||
304 | */ | 304 | */ |
305 | static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) | 305 | static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) |
306 | { | 306 | { |
307 | struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
308 | |||
309 | /* always say Linux will own the hardware */ | ||
310 | pci_write_config_byte(pdev, where + 3, 1); | ||
311 | |||
312 | /* maybe wait a while for BIOS to respond */ | ||
307 | if (cap & (1 << 16)) { | 313 | if (cap & (1 << 16)) { |
308 | int msec = 5000; | 314 | int msec = 5000; |
309 | struct pci_dev *pdev = | ||
310 | to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
311 | 315 | ||
312 | /* request handoff to OS */ | ||
313 | cap |= 1 << 24; | ||
314 | pci_write_config_dword(pdev, where, cap); | ||
315 | |||
316 | /* and wait a while for it to happen */ | ||
317 | do { | 316 | do { |
318 | msleep(10); | 317 | msleep(10); |
319 | msec -= 10; | 318 | msec -= 10; |
320 | pci_read_config_dword(pdev, where, &cap); | 319 | pci_read_config_dword(pdev, where, &cap); |
321 | } while ((cap & (1 << 16)) && msec); | 320 | } while ((cap & (1 << 16)) && msec); |
322 | if (cap & (1 << 16)) { | 321 | if (cap & (1 << 16)) { |
323 | ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n", | 322 | ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n", |
324 | where, cap); | 323 | where, cap); |
325 | // some BIOS versions seem buggy... | 324 | // some BIOS versions seem buggy... |
326 | // return 1; | 325 | // return 1; |
327 | ehci_warn (ehci, "continuing after BIOS bug...\n"); | 326 | ehci_warn (ehci, "continuing after BIOS bug...\n"); |
328 | return 0; | 327 | /* disable all SMIs, and clear "BIOS owns" flag */ |
329 | } | 328 | pci_write_config_dword(pdev, where + 4, 0); |
330 | ehci_dbg (ehci, "BIOS handoff succeeded\n"); | 329 | pci_write_config_byte(pdev, where + 2, 0); |
330 | } else | ||
331 | ehci_dbg(ehci, "BIOS handoff succeeded\n"); | ||
331 | } | 332 | } |
332 | return 0; | 333 | return 0; |
333 | } | 334 | } |
@@ -492,8 +493,6 @@ static int ehci_start (struct usb_hcd *hcd) | |||
492 | { | 493 | { |
493 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 494 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
494 | u32 temp; | 495 | u32 temp; |
495 | struct usb_device *udev; | ||
496 | struct usb_bus *bus; | ||
497 | int retval; | 496 | int retval; |
498 | u32 hcc_params; | 497 | u32 hcc_params; |
499 | u8 sbrn = 0; | 498 | u8 sbrn = 0; |
@@ -588,8 +587,8 @@ static int ehci_start (struct usb_hcd *hcd) | |||
588 | writel (0, &ehci->regs->segment); | 587 | writel (0, &ehci->regs->segment); |
589 | #if 0 | 588 | #if 0 |
590 | // this is deeply broken on almost all architectures | 589 | // this is deeply broken on almost all architectures |
591 | if (!pci_set_dma_mask (to_pci_dev(hcd->self.controller), 0xffffffffffffffffULL)) | 590 | if (!dma_set_mask (hcd->self.controller, DMA_64BIT_MASK)) |
592 | ehci_info (ehci, "enabled 64bit PCI DMA\n"); | 591 | ehci_info (ehci, "enabled 64bit DMA\n"); |
593 | #endif | 592 | #endif |
594 | } | 593 | } |
595 | 594 | ||
@@ -631,17 +630,6 @@ static int ehci_start (struct usb_hcd *hcd) | |||
631 | 630 | ||
632 | /* set async sleep time = 10 us ... ? */ | 631 | /* set async sleep time = 10 us ... ? */ |
633 | 632 | ||
634 | /* wire up the root hub */ | ||
635 | bus = hcd_to_bus (hcd); | ||
636 | udev = first ? usb_alloc_dev (NULL, bus, 0) : bus->root_hub; | ||
637 | if (!udev) { | ||
638 | done2: | ||
639 | ehci_mem_cleanup (ehci); | ||
640 | return -ENOMEM; | ||
641 | } | ||
642 | udev->speed = USB_SPEED_HIGH; | ||
643 | udev->state = first ? USB_STATE_ATTACHED : USB_STATE_CONFIGURED; | ||
644 | |||
645 | /* | 633 | /* |
646 | * Start, enabling full USB 2.0 functionality ... usb 1.1 devices | 634 | * Start, enabling full USB 2.0 functionality ... usb 1.1 devices |
647 | * are explicitly handed to companion controller(s), so no TT is | 635 | * are explicitly handed to companion controller(s), so no TT is |
@@ -664,24 +652,6 @@ done2: | |||
664 | first ? "initialized" : "restarted", | 652 | first ? "initialized" : "restarted", |
665 | temp >> 8, temp & 0xff, DRIVER_VERSION); | 653 | temp >> 8, temp & 0xff, DRIVER_VERSION); |
666 | 654 | ||
667 | /* | ||
668 | * From here on, khubd concurrently accesses the root | ||
669 | * hub; drivers will be talking to enumerated devices. | ||
670 | * (On restart paths, khubd already knows about the root | ||
671 | * hub and could find work as soon as we wrote FLAG_CF.) | ||
672 | * | ||
673 | * Before this point the HC was idle/ready. After, khubd | ||
674 | * and device drivers may start it running. | ||
675 | */ | ||
676 | if (first && usb_hcd_register_root_hub (udev, hcd) != 0) { | ||
677 | if (hcd->state == HC_STATE_RUNNING) | ||
678 | ehci_quiesce (ehci); | ||
679 | ehci_reset (ehci); | ||
680 | usb_put_dev (udev); | ||
681 | retval = -ENODEV; | ||
682 | goto done2; | ||
683 | } | ||
684 | |||
685 | writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ | 655 | writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ |
686 | 656 | ||
687 | if (first) | 657 | if (first) |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index d7b4f7939ded..36cc1f2218d5 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001-2002 by David Brownell | 2 | * Copyright (C) 2001-2004 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 7df9b9af54f6..45d89a7083b1 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001-2002 by David Brownell | 2 | * Copyright (C) 2001-2004 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 2fa1ffee5ff3..c2104cad4033 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -637,9 +637,8 @@ iso_stream_alloc (int mem_flags) | |||
637 | { | 637 | { |
638 | struct ehci_iso_stream *stream; | 638 | struct ehci_iso_stream *stream; |
639 | 639 | ||
640 | stream = kmalloc(sizeof *stream, mem_flags); | 640 | stream = kcalloc(1, sizeof *stream, mem_flags); |
641 | if (likely (stream != NULL)) { | 641 | if (likely (stream != NULL)) { |
642 | memset (stream, 0, sizeof(*stream)); | ||
643 | INIT_LIST_HEAD(&stream->td_list); | 642 | INIT_LIST_HEAD(&stream->td_list); |
644 | INIT_LIST_HEAD(&stream->free_list); | 643 | INIT_LIST_HEAD(&stream->free_list); |
645 | stream->next_uframe = -1; | 644 | stream->next_uframe = -1; |
@@ -894,7 +893,7 @@ itd_sched_init ( | |||
894 | trans |= length << 16; | 893 | trans |= length << 16; |
895 | uframe->transaction = cpu_to_le32 (trans); | 894 | uframe->transaction = cpu_to_le32 (trans); |
896 | 895 | ||
897 | /* might need to cross a buffer page within a td */ | 896 | /* might need to cross a buffer page within a uframe */ |
898 | uframe->bufp = (buf & ~(u64)0x0fff); | 897 | uframe->bufp = (buf & ~(u64)0x0fff); |
899 | buf += length; | 898 | buf += length; |
900 | if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) | 899 | if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) |
@@ -1194,6 +1193,7 @@ itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd) | |||
1194 | { | 1193 | { |
1195 | int i; | 1194 | int i; |
1196 | 1195 | ||
1196 | /* it's been recently zeroed */ | ||
1197 | itd->hw_next = EHCI_LIST_END; | 1197 | itd->hw_next = EHCI_LIST_END; |
1198 | itd->hw_bufp [0] = stream->buf0; | 1198 | itd->hw_bufp [0] = stream->buf0; |
1199 | itd->hw_bufp [1] = stream->buf1; | 1199 | itd->hw_bufp [1] = stream->buf1; |
@@ -1210,8 +1210,7 @@ itd_patch ( | |||
1210 | struct ehci_itd *itd, | 1210 | struct ehci_itd *itd, |
1211 | struct ehci_iso_sched *iso_sched, | 1211 | struct ehci_iso_sched *iso_sched, |
1212 | unsigned index, | 1212 | unsigned index, |
1213 | u16 uframe, | 1213 | u16 uframe |
1214 | int first | ||
1215 | ) | 1214 | ) |
1216 | { | 1215 | { |
1217 | struct ehci_iso_packet *uf = &iso_sched->packet [index]; | 1216 | struct ehci_iso_packet *uf = &iso_sched->packet [index]; |
@@ -1228,7 +1227,7 @@ itd_patch ( | |||
1228 | itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32)); | 1227 | itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32)); |
1229 | 1228 | ||
1230 | /* iso_frame_desc[].offset must be strictly increasing */ | 1229 | /* iso_frame_desc[].offset must be strictly increasing */ |
1231 | if (unlikely (!first && uf->cross)) { | 1230 | if (unlikely (uf->cross)) { |
1232 | u64 bufp = uf->bufp + 4096; | 1231 | u64 bufp = uf->bufp + 4096; |
1233 | itd->pg = ++pg; | 1232 | itd->pg = ++pg; |
1234 | itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0); | 1233 | itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0); |
@@ -1257,7 +1256,7 @@ itd_link_urb ( | |||
1257 | struct ehci_iso_stream *stream | 1256 | struct ehci_iso_stream *stream |
1258 | ) | 1257 | ) |
1259 | { | 1258 | { |
1260 | int packet, first = 1; | 1259 | int packet; |
1261 | unsigned next_uframe, uframe, frame; | 1260 | unsigned next_uframe, uframe, frame; |
1262 | struct ehci_iso_sched *iso_sched = urb->hcpriv; | 1261 | struct ehci_iso_sched *iso_sched = urb->hcpriv; |
1263 | struct ehci_itd *itd; | 1262 | struct ehci_itd *itd; |
@@ -1290,7 +1289,6 @@ itd_link_urb ( | |||
1290 | list_move_tail (&itd->itd_list, &stream->td_list); | 1289 | list_move_tail (&itd->itd_list, &stream->td_list); |
1291 | itd->stream = iso_stream_get (stream); | 1290 | itd->stream = iso_stream_get (stream); |
1292 | itd->urb = usb_get_urb (urb); | 1291 | itd->urb = usb_get_urb (urb); |
1293 | first = 1; | ||
1294 | itd_init (stream, itd); | 1292 | itd_init (stream, itd); |
1295 | } | 1293 | } |
1296 | 1294 | ||
@@ -1298,8 +1296,7 @@ itd_link_urb ( | |||
1298 | frame = next_uframe >> 3; | 1296 | frame = next_uframe >> 3; |
1299 | 1297 | ||
1300 | itd->usecs [uframe] = stream->usecs; | 1298 | itd->usecs [uframe] = stream->usecs; |
1301 | itd_patch (itd, iso_sched, packet, uframe, first); | 1299 | itd_patch (itd, iso_sched, packet, uframe); |
1302 | first = 0; | ||
1303 | 1300 | ||
1304 | next_uframe += stream->interval; | 1301 | next_uframe += stream->interval; |
1305 | stream->depth += stream->interval; | 1302 | stream->depth += stream->interval; |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c new file mode 100644 index 000000000000..ff0a168e8eed --- /dev/null +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -0,0 +1,1875 @@ | |||
1 | /* | ||
2 | * ISP116x HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * Derived from the SL811 HCD, rewritten for ISP116x. | ||
5 | * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee> | ||
6 | * | ||
7 | * Portions: | ||
8 | * Copyright (C) 2004 Psion Teklogix (for NetBook PRO) | ||
9 | * Copyright (C) 2004 David Brownell | ||
10 | * | ||
11 | * Periodic scheduling is based on Roman's OHCI code | ||
12 | * Copyright (C) 1999 Roman Weissgaerber | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | /* | ||
17 | * The driver basically works. A number of people have used it with a range | ||
18 | * of devices. | ||
19 | * | ||
20 | *The driver passes all usbtests 1-14. | ||
21 | * | ||
22 | * Suspending/resuming of root hub via sysfs works. Remote wakeup works too. | ||
23 | * And suspending/resuming of platform device works too. Suspend/resume | ||
24 | * via HCD operations vector is not implemented. | ||
25 | * | ||
26 | * Iso transfer support is not implemented. Adding this would include | ||
27 | * implementing recovery from the failure to service the processed ITL | ||
28 | * fifo ram in time, which will involve chip reset. | ||
29 | * | ||
30 | * TODO: | ||
31 | + More testing of suspend/resume. | ||
32 | */ | ||
33 | |||
34 | /* | ||
35 | ISP116x chips require certain delays between accesses to its | ||
36 | registers. The following timing options exist. | ||
37 | |||
38 | 1. Configure your memory controller (the best) | ||
39 | 2. Implement platform-specific delay function possibly | ||
40 | combined with configuring the memory controller; see | ||
41 | include/linux/usb-isp116x.h for more info. Some broken | ||
42 | memory controllers line LH7A400 SMC need this. Also, | ||
43 | uncomment for that to work the following | ||
44 | USE_PLATFORM_DELAY macro. | ||
45 | 3. Use ndelay (easiest, poorest). For that, uncomment | ||
46 | the following USE_NDELAY macro. | ||
47 | */ | ||
48 | #define USE_PLATFORM_DELAY | ||
49 | //#define USE_NDELAY | ||
50 | |||
51 | //#define DEBUG | ||
52 | //#define VERBOSE | ||
53 | /* Transfer descriptors. See dump_ptd() for printout format */ | ||
54 | //#define PTD_TRACE | ||
55 | /* enqueuing/finishing log of urbs */ | ||
56 | //#define URB_TRACE | ||
57 | |||
58 | #include <linux/config.h> | ||
59 | #include <linux/module.h> | ||
60 | #include <linux/moduleparam.h> | ||
61 | #include <linux/kernel.h> | ||
62 | #include <linux/delay.h> | ||
63 | #include <linux/ioport.h> | ||
64 | #include <linux/sched.h> | ||
65 | #include <linux/slab.h> | ||
66 | #include <linux/smp_lock.h> | ||
67 | #include <linux/errno.h> | ||
68 | #include <linux/init.h> | ||
69 | #include <linux/list.h> | ||
70 | #include <linux/interrupt.h> | ||
71 | #include <linux/usb.h> | ||
72 | #include <linux/usb_isp116x.h> | ||
73 | |||
74 | #include <asm/io.h> | ||
75 | #include <asm/irq.h> | ||
76 | #include <asm/system.h> | ||
77 | #include <asm/byteorder.h> | ||
78 | |||
79 | #ifndef DEBUG | ||
80 | # define STUB_DEBUG_FILE | ||
81 | #endif | ||
82 | |||
83 | #include "../core/hcd.h" | ||
84 | #include "isp116x.h" | ||
85 | |||
86 | #define DRIVER_VERSION "08 Apr 2005" | ||
87 | #define DRIVER_DESC "ISP116x USB Host Controller Driver" | ||
88 | |||
89 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
90 | MODULE_LICENSE("GPL"); | ||
91 | |||
92 | static const char hcd_name[] = "isp116x-hcd"; | ||
93 | |||
94 | /*-----------------------------------------------------------------*/ | ||
95 | |||
96 | /* | ||
97 | Write len bytes to fifo, pad till 32-bit boundary | ||
98 | */ | ||
99 | static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len) | ||
100 | { | ||
101 | u8 *dp = (u8 *) buf; | ||
102 | u16 *dp2 = (u16 *) buf; | ||
103 | u16 w; | ||
104 | int quot = len % 4; | ||
105 | |||
106 | if ((unsigned long)dp2 & 1) { | ||
107 | /* not aligned */ | ||
108 | for (; len > 1; len -= 2) { | ||
109 | w = *dp++; | ||
110 | w |= *dp++ << 8; | ||
111 | isp116x_raw_write_data16(isp116x, w); | ||
112 | } | ||
113 | if (len) | ||
114 | isp116x_write_data16(isp116x, (u16) * dp); | ||
115 | } else { | ||
116 | /* aligned */ | ||
117 | for (; len > 1; len -= 2) | ||
118 | isp116x_raw_write_data16(isp116x, *dp2++); | ||
119 | if (len) | ||
120 | isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2)); | ||
121 | } | ||
122 | if (quot == 1 || quot == 2) | ||
123 | isp116x_raw_write_data16(isp116x, 0); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | Read len bytes from fifo and then read till 32-bit boundary. | ||
128 | */ | ||
129 | static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len) | ||
130 | { | ||
131 | u8 *dp = (u8 *) buf; | ||
132 | u16 *dp2 = (u16 *) buf; | ||
133 | u16 w; | ||
134 | int quot = len % 4; | ||
135 | |||
136 | if ((unsigned long)dp2 & 1) { | ||
137 | /* not aligned */ | ||
138 | for (; len > 1; len -= 2) { | ||
139 | w = isp116x_raw_read_data16(isp116x); | ||
140 | *dp++ = w & 0xff; | ||
141 | *dp++ = (w >> 8) & 0xff; | ||
142 | } | ||
143 | if (len) | ||
144 | *dp = 0xff & isp116x_read_data16(isp116x); | ||
145 | } else { | ||
146 | /* aligned */ | ||
147 | for (; len > 1; len -= 2) | ||
148 | *dp2++ = isp116x_raw_read_data16(isp116x); | ||
149 | if (len) | ||
150 | *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x); | ||
151 | } | ||
152 | if (quot == 1 || quot == 2) | ||
153 | isp116x_raw_read_data16(isp116x); | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | Write ptd's and data for scheduled transfers into | ||
158 | the fifo ram. Fifo must be empty and ready. | ||
159 | */ | ||
160 | static void pack_fifo(struct isp116x *isp116x) | ||
161 | { | ||
162 | struct isp116x_ep *ep; | ||
163 | struct ptd *ptd; | ||
164 | int buflen = isp116x->atl_last_dir == PTD_DIR_IN | ||
165 | ? isp116x->atl_bufshrt : isp116x->atl_buflen; | ||
166 | int ptd_count = 0; | ||
167 | |||
168 | isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); | ||
169 | isp116x_write_reg16(isp116x, HCXFERCTR, buflen); | ||
170 | isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET); | ||
171 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
172 | ++ptd_count; | ||
173 | ptd = &ep->ptd; | ||
174 | dump_ptd(ptd); | ||
175 | dump_ptd_out_data(ptd, ep->data); | ||
176 | isp116x_write_data16(isp116x, ptd->count); | ||
177 | isp116x_write_data16(isp116x, ptd->mps); | ||
178 | isp116x_write_data16(isp116x, ptd->len); | ||
179 | isp116x_write_data16(isp116x, ptd->faddr); | ||
180 | buflen -= sizeof(struct ptd); | ||
181 | /* Skip writing data for last IN PTD */ | ||
182 | if (ep->active || (isp116x->atl_last_dir != PTD_DIR_IN)) { | ||
183 | write_ptddata_to_fifo(isp116x, ep->data, ep->length); | ||
184 | buflen -= ALIGN(ep->length, 4); | ||
185 | } | ||
186 | } | ||
187 | BUG_ON(buflen); | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | Read the processed ptd's and data from fifo ram back to | ||
192 | URBs' buffers. Fifo must be full and done | ||
193 | */ | ||
194 | static void unpack_fifo(struct isp116x *isp116x) | ||
195 | { | ||
196 | struct isp116x_ep *ep; | ||
197 | struct ptd *ptd; | ||
198 | int buflen = isp116x->atl_last_dir == PTD_DIR_IN | ||
199 | ? isp116x->atl_buflen : isp116x->atl_bufshrt; | ||
200 | |||
201 | isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); | ||
202 | isp116x_write_reg16(isp116x, HCXFERCTR, buflen); | ||
203 | isp116x_write_addr(isp116x, HCATLPORT); | ||
204 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
205 | ptd = &ep->ptd; | ||
206 | ptd->count = isp116x_read_data16(isp116x); | ||
207 | ptd->mps = isp116x_read_data16(isp116x); | ||
208 | ptd->len = isp116x_read_data16(isp116x); | ||
209 | ptd->faddr = isp116x_read_data16(isp116x); | ||
210 | buflen -= sizeof(struct ptd); | ||
211 | /* Skip reading data for last Setup or Out PTD */ | ||
212 | if (ep->active || (isp116x->atl_last_dir == PTD_DIR_IN)) { | ||
213 | read_ptddata_from_fifo(isp116x, ep->data, ep->length); | ||
214 | buflen -= ALIGN(ep->length, 4); | ||
215 | } | ||
216 | dump_ptd(ptd); | ||
217 | dump_ptd_in_data(ptd, ep->data); | ||
218 | } | ||
219 | BUG_ON(buflen); | ||
220 | } | ||
221 | |||
222 | /*---------------------------------------------------------------*/ | ||
223 | |||
224 | /* | ||
225 | Set up PTD's. | ||
226 | */ | ||
227 | static void preproc_atl_queue(struct isp116x *isp116x) | ||
228 | { | ||
229 | struct isp116x_ep *ep; | ||
230 | struct urb *urb; | ||
231 | struct ptd *ptd; | ||
232 | u16 toggle, dir, len; | ||
233 | |||
234 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
235 | BUG_ON(list_empty(&ep->hep->urb_list)); | ||
236 | urb = container_of(ep->hep->urb_list.next, | ||
237 | struct urb, urb_list); | ||
238 | ptd = &ep->ptd; | ||
239 | len = ep->length; | ||
240 | spin_lock(&urb->lock); | ||
241 | ep->data = (unsigned char *)urb->transfer_buffer | ||
242 | + urb->actual_length; | ||
243 | |||
244 | switch (ep->nextpid) { | ||
245 | case USB_PID_IN: | ||
246 | toggle = usb_gettoggle(urb->dev, ep->epnum, 0); | ||
247 | dir = PTD_DIR_IN; | ||
248 | break; | ||
249 | case USB_PID_OUT: | ||
250 | toggle = usb_gettoggle(urb->dev, ep->epnum, 1); | ||
251 | dir = PTD_DIR_OUT; | ||
252 | break; | ||
253 | case USB_PID_SETUP: | ||
254 | toggle = 0; | ||
255 | dir = PTD_DIR_SETUP; | ||
256 | len = sizeof(struct usb_ctrlrequest); | ||
257 | ep->data = urb->setup_packet; | ||
258 | break; | ||
259 | case USB_PID_ACK: | ||
260 | toggle = 1; | ||
261 | len = 0; | ||
262 | dir = (urb->transfer_buffer_length | ||
263 | && usb_pipein(urb->pipe)) | ||
264 | ? PTD_DIR_OUT : PTD_DIR_IN; | ||
265 | break; | ||
266 | default: | ||
267 | /* To please gcc */ | ||
268 | toggle = dir = 0; | ||
269 | ERR("%s %d: ep->nextpid %d\n", __func__, __LINE__, | ||
270 | ep->nextpid); | ||
271 | BUG_ON(1); | ||
272 | } | ||
273 | |||
274 | ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | PTD_TOGGLE(toggle); | ||
275 | ptd->mps = PTD_MPS(ep->maxpacket) | ||
276 | | PTD_SPD(urb->dev->speed == USB_SPEED_LOW) | ||
277 | | PTD_EP(ep->epnum); | ||
278 | ptd->len = PTD_LEN(len) | PTD_DIR(dir); | ||
279 | ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe)); | ||
280 | spin_unlock(&urb->lock); | ||
281 | if (!ep->active) { | ||
282 | ptd->mps |= PTD_LAST_MSK; | ||
283 | isp116x->atl_last_dir = dir; | ||
284 | } | ||
285 | isp116x->atl_bufshrt = sizeof(struct ptd) + isp116x->atl_buflen; | ||
286 | isp116x->atl_buflen = isp116x->atl_bufshrt + ALIGN(len, 4); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | /* | ||
291 | Analyze transfer results, handle partial transfers and errors | ||
292 | */ | ||
293 | static void postproc_atl_queue(struct isp116x *isp116x) | ||
294 | { | ||
295 | struct isp116x_ep *ep; | ||
296 | struct urb *urb; | ||
297 | struct usb_device *udev; | ||
298 | struct ptd *ptd; | ||
299 | int short_not_ok; | ||
300 | u8 cc; | ||
301 | |||
302 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
303 | BUG_ON(list_empty(&ep->hep->urb_list)); | ||
304 | urb = | ||
305 | container_of(ep->hep->urb_list.next, struct urb, urb_list); | ||
306 | udev = urb->dev; | ||
307 | ptd = &ep->ptd; | ||
308 | cc = PTD_GET_CC(ptd); | ||
309 | |||
310 | spin_lock(&urb->lock); | ||
311 | short_not_ok = 1; | ||
312 | |||
313 | /* Data underrun is special. For allowed underrun | ||
314 | we clear the error and continue as normal. For | ||
315 | forbidden underrun we finish the DATA stage | ||
316 | immediately while for control transfer, | ||
317 | we do a STATUS stage. */ | ||
318 | if (cc == TD_DATAUNDERRUN) { | ||
319 | if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) { | ||
320 | DBG("Allowed data underrun\n"); | ||
321 | cc = TD_CC_NOERROR; | ||
322 | short_not_ok = 0; | ||
323 | } else { | ||
324 | ep->error_count = 1; | ||
325 | if (usb_pipecontrol(urb->pipe)) | ||
326 | ep->nextpid = USB_PID_ACK; | ||
327 | else | ||
328 | usb_settoggle(udev, ep->epnum, | ||
329 | ep->nextpid == | ||
330 | USB_PID_OUT, | ||
331 | PTD_GET_TOGGLE(ptd) ^ 1); | ||
332 | urb->status = cc_to_error[TD_DATAUNDERRUN]; | ||
333 | spin_unlock(&urb->lock); | ||
334 | continue; | ||
335 | } | ||
336 | } | ||
337 | /* Keep underrun error through the STATUS stage */ | ||
338 | if (urb->status == cc_to_error[TD_DATAUNDERRUN]) | ||
339 | cc = TD_DATAUNDERRUN; | ||
340 | |||
341 | if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED | ||
342 | && (++ep->error_count >= 3 || cc == TD_CC_STALL | ||
343 | || cc == TD_DATAOVERRUN)) { | ||
344 | if (urb->status == -EINPROGRESS) | ||
345 | urb->status = cc_to_error[cc]; | ||
346 | if (ep->nextpid == USB_PID_ACK) | ||
347 | ep->nextpid = 0; | ||
348 | spin_unlock(&urb->lock); | ||
349 | continue; | ||
350 | } | ||
351 | /* According to usb spec, zero-length Int transfer signals | ||
352 | finishing of the urb. Hey, does this apply only | ||
353 | for IN endpoints? */ | ||
354 | if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) { | ||
355 | if (urb->status == -EINPROGRESS) | ||
356 | urb->status = 0; | ||
357 | spin_unlock(&urb->lock); | ||
358 | continue; | ||
359 | } | ||
360 | |||
361 | /* Relax after previously failed, but later succeeded | ||
362 | or correctly NAK'ed retransmission attempt */ | ||
363 | if (ep->error_count | ||
364 | && (cc == TD_CC_NOERROR || cc == TD_NOTACCESSED)) | ||
365 | ep->error_count = 0; | ||
366 | |||
367 | /* Take into account idiosyncracies of the isp116x chip | ||
368 | regarding toggle bit for failed transfers */ | ||
369 | if (ep->nextpid == USB_PID_OUT) | ||
370 | usb_settoggle(udev, ep->epnum, 1, PTD_GET_TOGGLE(ptd) | ||
371 | ^ (ep->error_count > 0)); | ||
372 | else if (ep->nextpid == USB_PID_IN) | ||
373 | usb_settoggle(udev, ep->epnum, 0, PTD_GET_TOGGLE(ptd) | ||
374 | ^ (ep->error_count > 0)); | ||
375 | |||
376 | switch (ep->nextpid) { | ||
377 | case USB_PID_IN: | ||
378 | case USB_PID_OUT: | ||
379 | urb->actual_length += PTD_GET_COUNT(ptd); | ||
380 | if (PTD_GET_ACTIVE(ptd) | ||
381 | || (cc != TD_CC_NOERROR && cc < 0x0E)) | ||
382 | break; | ||
383 | if (urb->transfer_buffer_length != urb->actual_length) { | ||
384 | if (short_not_ok) | ||
385 | break; | ||
386 | } else { | ||
387 | if (urb->transfer_flags & URB_ZERO_PACKET | ||
388 | && ep->nextpid == USB_PID_OUT | ||
389 | && !(PTD_GET_COUNT(ptd) % ep->maxpacket)) { | ||
390 | DBG("Zero packet requested\n"); | ||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | /* All data for this URB is transferred, let's finish */ | ||
395 | if (usb_pipecontrol(urb->pipe)) | ||
396 | ep->nextpid = USB_PID_ACK; | ||
397 | else if (urb->status == -EINPROGRESS) | ||
398 | urb->status = 0; | ||
399 | break; | ||
400 | case USB_PID_SETUP: | ||
401 | if (PTD_GET_ACTIVE(ptd) | ||
402 | || (cc != TD_CC_NOERROR && cc < 0x0E)) | ||
403 | break; | ||
404 | if (urb->transfer_buffer_length == urb->actual_length) | ||
405 | ep->nextpid = USB_PID_ACK; | ||
406 | else if (usb_pipeout(urb->pipe)) { | ||
407 | usb_settoggle(udev, 0, 1, 1); | ||
408 | ep->nextpid = USB_PID_OUT; | ||
409 | } else { | ||
410 | usb_settoggle(udev, 0, 0, 1); | ||
411 | ep->nextpid = USB_PID_IN; | ||
412 | } | ||
413 | break; | ||
414 | case USB_PID_ACK: | ||
415 | if (PTD_GET_ACTIVE(ptd) | ||
416 | || (cc != TD_CC_NOERROR && cc < 0x0E)) | ||
417 | break; | ||
418 | if (urb->status == -EINPROGRESS) | ||
419 | urb->status = 0; | ||
420 | ep->nextpid = 0; | ||
421 | break; | ||
422 | default: | ||
423 | BUG_ON(1); | ||
424 | } | ||
425 | spin_unlock(&urb->lock); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | Take done or failed requests out of schedule. Give back | ||
431 | processed urbs. | ||
432 | */ | ||
433 | static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep, | ||
434 | struct urb *urb, struct pt_regs *regs) | ||
435 | __releases(isp116x->lock) __acquires(isp116x->lock) | ||
436 | { | ||
437 | unsigned i; | ||
438 | |||
439 | urb->hcpriv = NULL; | ||
440 | ep->error_count = 0; | ||
441 | |||
442 | if (usb_pipecontrol(urb->pipe)) | ||
443 | ep->nextpid = USB_PID_SETUP; | ||
444 | |||
445 | urb_dbg(urb, "Finish"); | ||
446 | |||
447 | spin_unlock(&isp116x->lock); | ||
448 | usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb, regs); | ||
449 | spin_lock(&isp116x->lock); | ||
450 | |||
451 | /* take idle endpoints out of the schedule */ | ||
452 | if (!list_empty(&ep->hep->urb_list)) | ||
453 | return; | ||
454 | |||
455 | /* async deschedule */ | ||
456 | if (!list_empty(&ep->schedule)) { | ||
457 | list_del_init(&ep->schedule); | ||
458 | return; | ||
459 | } | ||
460 | |||
461 | /* periodic deschedule */ | ||
462 | DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); | ||
463 | for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { | ||
464 | struct isp116x_ep *temp; | ||
465 | struct isp116x_ep **prev = &isp116x->periodic[i]; | ||
466 | |||
467 | while (*prev && ((temp = *prev) != ep)) | ||
468 | prev = &temp->next; | ||
469 | if (*prev) | ||
470 | *prev = ep->next; | ||
471 | isp116x->load[i] -= ep->load; | ||
472 | } | ||
473 | ep->branch = PERIODIC_SIZE; | ||
474 | isp116x_to_hcd(isp116x)->self.bandwidth_allocated -= | ||
475 | ep->load / ep->period; | ||
476 | |||
477 | /* switch irq type? */ | ||
478 | if (!--isp116x->periodic_count) { | ||
479 | isp116x->irqenb &= ~HCuPINT_SOF; | ||
480 | isp116x->irqenb |= HCuPINT_ATL; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | Scan transfer lists, schedule transfers, send data off | ||
486 | to chip. | ||
487 | */ | ||
488 | static void start_atl_transfers(struct isp116x *isp116x) | ||
489 | { | ||
490 | struct isp116x_ep *last_ep = NULL, *ep; | ||
491 | struct urb *urb; | ||
492 | u16 load = 0; | ||
493 | int len, index, speed, byte_time; | ||
494 | |||
495 | if (atomic_read(&isp116x->atl_finishing)) | ||
496 | return; | ||
497 | |||
498 | if (!HC_IS_RUNNING(isp116x_to_hcd(isp116x)->state)) | ||
499 | return; | ||
500 | |||
501 | /* FIFO not empty? */ | ||
502 | if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) | ||
503 | return; | ||
504 | |||
505 | isp116x->atl_active = NULL; | ||
506 | isp116x->atl_buflen = isp116x->atl_bufshrt = 0; | ||
507 | |||
508 | /* Schedule int transfers */ | ||
509 | if (isp116x->periodic_count) { | ||
510 | isp116x->fmindex = index = | ||
511 | (isp116x->fmindex + 1) & (PERIODIC_SIZE - 1); | ||
512 | if ((load = isp116x->load[index])) { | ||
513 | /* Bring all int transfers for this frame | ||
514 | into the active queue */ | ||
515 | isp116x->atl_active = last_ep = | ||
516 | isp116x->periodic[index]; | ||
517 | while (last_ep->next) | ||
518 | last_ep = (last_ep->active = last_ep->next); | ||
519 | last_ep->active = NULL; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | /* Schedule control/bulk transfers */ | ||
524 | list_for_each_entry(ep, &isp116x->async, schedule) { | ||
525 | urb = container_of(ep->hep->urb_list.next, | ||
526 | struct urb, urb_list); | ||
527 | speed = urb->dev->speed; | ||
528 | byte_time = speed == USB_SPEED_LOW | ||
529 | ? BYTE_TIME_LOWSPEED : BYTE_TIME_FULLSPEED; | ||
530 | |||
531 | if (ep->nextpid == USB_PID_SETUP) { | ||
532 | len = sizeof(struct usb_ctrlrequest); | ||
533 | } else if (ep->nextpid == USB_PID_ACK) { | ||
534 | len = 0; | ||
535 | } else { | ||
536 | /* Find current free length ... */ | ||
537 | len = (MAX_LOAD_LIMIT - load) / byte_time; | ||
538 | |||
539 | /* ... then limit it to configured max size ... */ | ||
540 | len = min(len, speed == USB_SPEED_LOW ? | ||
541 | MAX_TRANSFER_SIZE_LOWSPEED : | ||
542 | MAX_TRANSFER_SIZE_FULLSPEED); | ||
543 | |||
544 | /* ... and finally cut to the multiple of MaxPacketSize, | ||
545 | or to the real length if there's enough room. */ | ||
546 | if (len < | ||
547 | (urb->transfer_buffer_length - | ||
548 | urb->actual_length)) { | ||
549 | len -= len % ep->maxpacket; | ||
550 | if (!len) | ||
551 | continue; | ||
552 | } else | ||
553 | len = urb->transfer_buffer_length - | ||
554 | urb->actual_length; | ||
555 | BUG_ON(len < 0); | ||
556 | } | ||
557 | |||
558 | load += len * byte_time; | ||
559 | if (load > MAX_LOAD_LIMIT) | ||
560 | break; | ||
561 | |||
562 | ep->active = NULL; | ||
563 | ep->length = len; | ||
564 | if (last_ep) | ||
565 | last_ep->active = ep; | ||
566 | else | ||
567 | isp116x->atl_active = ep; | ||
568 | last_ep = ep; | ||
569 | } | ||
570 | |||
571 | /* Avoid starving of endpoints */ | ||
572 | if ((&isp116x->async)->next != (&isp116x->async)->prev) | ||
573 | list_move(&isp116x->async, (&isp116x->async)->next); | ||
574 | |||
575 | if (isp116x->atl_active) { | ||
576 | preproc_atl_queue(isp116x); | ||
577 | pack_fifo(isp116x); | ||
578 | } | ||
579 | } | ||
580 | |||
581 | /* | ||
582 | Finish the processed transfers | ||
583 | */ | ||
584 | static void finish_atl_transfers(struct isp116x *isp116x, struct pt_regs *regs) | ||
585 | { | ||
586 | struct isp116x_ep *ep; | ||
587 | struct urb *urb; | ||
588 | |||
589 | if (!isp116x->atl_active) | ||
590 | return; | ||
591 | /* Fifo not ready? */ | ||
592 | if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) | ||
593 | return; | ||
594 | |||
595 | atomic_inc(&isp116x->atl_finishing); | ||
596 | unpack_fifo(isp116x); | ||
597 | postproc_atl_queue(isp116x); | ||
598 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
599 | urb = | ||
600 | container_of(ep->hep->urb_list.next, struct urb, urb_list); | ||
601 | /* USB_PID_ACK check here avoids finishing of | ||
602 | control transfers, for which TD_DATAUNDERRUN | ||
603 | occured, while URB_SHORT_NOT_OK was set */ | ||
604 | if (urb && urb->status != -EINPROGRESS | ||
605 | && ep->nextpid != USB_PID_ACK) | ||
606 | finish_request(isp116x, ep, urb, regs); | ||
607 | } | ||
608 | atomic_dec(&isp116x->atl_finishing); | ||
609 | } | ||
610 | |||
611 | static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) | ||
612 | { | ||
613 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
614 | u16 irqstat; | ||
615 | irqreturn_t ret = IRQ_NONE; | ||
616 | |||
617 | spin_lock(&isp116x->lock); | ||
618 | isp116x_write_reg16(isp116x, HCuPINTENB, 0); | ||
619 | irqstat = isp116x_read_reg16(isp116x, HCuPINT); | ||
620 | isp116x_write_reg16(isp116x, HCuPINT, irqstat); | ||
621 | |||
622 | if (irqstat & (HCuPINT_ATL | HCuPINT_SOF)) { | ||
623 | ret = IRQ_HANDLED; | ||
624 | finish_atl_transfers(isp116x, regs); | ||
625 | } | ||
626 | |||
627 | if (irqstat & HCuPINT_OPR) { | ||
628 | u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT); | ||
629 | isp116x_write_reg32(isp116x, HCINTSTAT, intstat); | ||
630 | if (intstat & HCINT_UE) { | ||
631 | ERR("Unrecoverable error\n"); | ||
632 | /* What should we do here? Reset? */ | ||
633 | } | ||
634 | if (intstat & HCINT_RHSC) { | ||
635 | isp116x->rhstatus = | ||
636 | isp116x_read_reg32(isp116x, HCRHSTATUS); | ||
637 | isp116x->rhport[0] = | ||
638 | isp116x_read_reg32(isp116x, HCRHPORT1); | ||
639 | isp116x->rhport[1] = | ||
640 | isp116x_read_reg32(isp116x, HCRHPORT2); | ||
641 | } | ||
642 | if (intstat & HCINT_RD) { | ||
643 | DBG("---- remote wakeup\n"); | ||
644 | schedule_work(&isp116x->rh_resume); | ||
645 | ret = IRQ_HANDLED; | ||
646 | } | ||
647 | irqstat &= ~HCuPINT_OPR; | ||
648 | ret = IRQ_HANDLED; | ||
649 | } | ||
650 | |||
651 | if (irqstat & (HCuPINT_ATL | HCuPINT_SOF)) { | ||
652 | start_atl_transfers(isp116x); | ||
653 | } | ||
654 | |||
655 | isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); | ||
656 | spin_unlock(&isp116x->lock); | ||
657 | return ret; | ||
658 | } | ||
659 | |||
660 | /*-----------------------------------------------------------------*/ | ||
661 | |||
662 | /* usb 1.1 says max 90% of a frame is available for periodic transfers. | ||
663 | * this driver doesn't promise that much since it's got to handle an | ||
664 | * IRQ per packet; irq handling latencies also use up that time. | ||
665 | */ | ||
666 | |||
667 | /* out of 1000 us */ | ||
668 | #define MAX_PERIODIC_LOAD 600 | ||
669 | static int balance(struct isp116x *isp116x, u16 period, u16 load) | ||
670 | { | ||
671 | int i, branch = -ENOSPC; | ||
672 | |||
673 | /* search for the least loaded schedule branch of that period | ||
674 | which has enough bandwidth left unreserved. */ | ||
675 | for (i = 0; i < period; i++) { | ||
676 | if (branch < 0 || isp116x->load[branch] > isp116x->load[i]) { | ||
677 | int j; | ||
678 | |||
679 | for (j = i; j < PERIODIC_SIZE; j += period) { | ||
680 | if ((isp116x->load[j] + load) | ||
681 | > MAX_PERIODIC_LOAD) | ||
682 | break; | ||
683 | } | ||
684 | if (j < PERIODIC_SIZE) | ||
685 | continue; | ||
686 | branch = i; | ||
687 | } | ||
688 | } | ||
689 | return branch; | ||
690 | } | ||
691 | |||
692 | /* NB! ALL the code above this point runs with isp116x->lock | ||
693 | held, irqs off | ||
694 | */ | ||
695 | |||
696 | /*-----------------------------------------------------------------*/ | ||
697 | |||
698 | static int isp116x_urb_enqueue(struct usb_hcd *hcd, | ||
699 | struct usb_host_endpoint *hep, struct urb *urb, | ||
700 | int mem_flags) | ||
701 | { | ||
702 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
703 | struct usb_device *udev = urb->dev; | ||
704 | unsigned int pipe = urb->pipe; | ||
705 | int is_out = !usb_pipein(pipe); | ||
706 | int type = usb_pipetype(pipe); | ||
707 | int epnum = usb_pipeendpoint(pipe); | ||
708 | struct isp116x_ep *ep = NULL; | ||
709 | unsigned long flags; | ||
710 | int i; | ||
711 | int ret = 0; | ||
712 | |||
713 | urb_dbg(urb, "Enqueue"); | ||
714 | |||
715 | if (type == PIPE_ISOCHRONOUS) { | ||
716 | ERR("Isochronous transfers not supported\n"); | ||
717 | urb_dbg(urb, "Refused to enqueue"); | ||
718 | return -ENXIO; | ||
719 | } | ||
720 | /* avoid all allocations within spinlocks: request or endpoint */ | ||
721 | if (!hep->hcpriv) { | ||
722 | ep = kcalloc(1, sizeof *ep, (__force unsigned)mem_flags); | ||
723 | if (!ep) | ||
724 | return -ENOMEM; | ||
725 | } | ||
726 | |||
727 | spin_lock_irqsave(&isp116x->lock, flags); | ||
728 | if (!HC_IS_RUNNING(hcd->state)) { | ||
729 | ret = -ENODEV; | ||
730 | goto fail; | ||
731 | } | ||
732 | |||
733 | if (hep->hcpriv) | ||
734 | ep = hep->hcpriv; | ||
735 | else { | ||
736 | INIT_LIST_HEAD(&ep->schedule); | ||
737 | ep->udev = usb_get_dev(udev); | ||
738 | ep->epnum = epnum; | ||
739 | ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); | ||
740 | usb_settoggle(udev, epnum, is_out, 0); | ||
741 | |||
742 | if (type == PIPE_CONTROL) { | ||
743 | ep->nextpid = USB_PID_SETUP; | ||
744 | } else if (is_out) { | ||
745 | ep->nextpid = USB_PID_OUT; | ||
746 | } else { | ||
747 | ep->nextpid = USB_PID_IN; | ||
748 | } | ||
749 | |||
750 | if (urb->interval) { | ||
751 | /* | ||
752 | With INT URBs submitted, the driver works with SOF | ||
753 | interrupt enabled and ATL interrupt disabled. After | ||
754 | the PTDs are written to fifo ram, the chip starts | ||
755 | fifo processing and usb transfers after the next | ||
756 | SOF and continues until the transfers are finished | ||
757 | (succeeded or failed) or the frame ends. Therefore, | ||
758 | the transfers occur only in every second frame, | ||
759 | while fifo reading/writing and data processing | ||
760 | occur in every other second frame. */ | ||
761 | if (urb->interval < 2) | ||
762 | urb->interval = 2; | ||
763 | if (urb->interval > 2 * PERIODIC_SIZE) | ||
764 | urb->interval = 2 * PERIODIC_SIZE; | ||
765 | ep->period = urb->interval >> 1; | ||
766 | ep->branch = PERIODIC_SIZE; | ||
767 | ep->load = usb_calc_bus_time(udev->speed, | ||
768 | !is_out, | ||
769 | (type == PIPE_ISOCHRONOUS), | ||
770 | usb_maxpacket(udev, pipe, | ||
771 | is_out)) / | ||
772 | 1000; | ||
773 | } | ||
774 | hep->hcpriv = ep; | ||
775 | ep->hep = hep; | ||
776 | } | ||
777 | |||
778 | /* maybe put endpoint into schedule */ | ||
779 | switch (type) { | ||
780 | case PIPE_CONTROL: | ||
781 | case PIPE_BULK: | ||
782 | if (list_empty(&ep->schedule)) | ||
783 | list_add_tail(&ep->schedule, &isp116x->async); | ||
784 | break; | ||
785 | case PIPE_INTERRUPT: | ||
786 | urb->interval = ep->period; | ||
787 | ep->length = min((int)ep->maxpacket, | ||
788 | urb->transfer_buffer_length); | ||
789 | |||
790 | /* urb submitted for already existing endpoint */ | ||
791 | if (ep->branch < PERIODIC_SIZE) | ||
792 | break; | ||
793 | |||
794 | ret = ep->branch = balance(isp116x, ep->period, ep->load); | ||
795 | if (ret < 0) | ||
796 | goto fail; | ||
797 | ret = 0; | ||
798 | |||
799 | urb->start_frame = (isp116x->fmindex & (PERIODIC_SIZE - 1)) | ||
800 | + ep->branch; | ||
801 | |||
802 | /* sort each schedule branch by period (slow before fast) | ||
803 | to share the faster parts of the tree without needing | ||
804 | dummy/placeholder nodes */ | ||
805 | DBG("schedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); | ||
806 | for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { | ||
807 | struct isp116x_ep **prev = &isp116x->periodic[i]; | ||
808 | struct isp116x_ep *here = *prev; | ||
809 | |||
810 | while (here && ep != here) { | ||
811 | if (ep->period > here->period) | ||
812 | break; | ||
813 | prev = &here->next; | ||
814 | here = *prev; | ||
815 | } | ||
816 | if (ep != here) { | ||
817 | ep->next = here; | ||
818 | *prev = ep; | ||
819 | } | ||
820 | isp116x->load[i] += ep->load; | ||
821 | } | ||
822 | hcd->self.bandwidth_allocated += ep->load / ep->period; | ||
823 | |||
824 | /* switch over to SOFint */ | ||
825 | if (!isp116x->periodic_count++) { | ||
826 | isp116x->irqenb &= ~HCuPINT_ATL; | ||
827 | isp116x->irqenb |= HCuPINT_SOF; | ||
828 | isp116x_write_reg16(isp116x, HCuPINTENB, | ||
829 | isp116x->irqenb); | ||
830 | } | ||
831 | } | ||
832 | |||
833 | /* in case of unlink-during-submit */ | ||
834 | spin_lock(&urb->lock); | ||
835 | if (urb->status != -EINPROGRESS) { | ||
836 | spin_unlock(&urb->lock); | ||
837 | finish_request(isp116x, ep, urb, NULL); | ||
838 | ret = 0; | ||
839 | goto fail; | ||
840 | } | ||
841 | urb->hcpriv = hep; | ||
842 | spin_unlock(&urb->lock); | ||
843 | start_atl_transfers(isp116x); | ||
844 | |||
845 | fail: | ||
846 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
847 | return ret; | ||
848 | } | ||
849 | |||
850 | /* | ||
851 | Dequeue URBs. | ||
852 | */ | ||
853 | static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | ||
854 | { | ||
855 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
856 | struct usb_host_endpoint *hep; | ||
857 | struct isp116x_ep *ep, *ep_act; | ||
858 | unsigned long flags; | ||
859 | |||
860 | spin_lock_irqsave(&isp116x->lock, flags); | ||
861 | hep = urb->hcpriv; | ||
862 | /* URB already unlinked (or never linked)? */ | ||
863 | if (!hep) { | ||
864 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
865 | return 0; | ||
866 | } | ||
867 | ep = hep->hcpriv; | ||
868 | WARN_ON(hep != ep->hep); | ||
869 | |||
870 | /* In front of queue? */ | ||
871 | if (ep->hep->urb_list.next == &urb->urb_list) | ||
872 | /* active? */ | ||
873 | for (ep_act = isp116x->atl_active; ep_act; | ||
874 | ep_act = ep_act->active) | ||
875 | if (ep_act == ep) { | ||
876 | VDBG("dequeue, urb %p active; wait for irq\n", | ||
877 | urb); | ||
878 | urb = NULL; | ||
879 | break; | ||
880 | } | ||
881 | |||
882 | if (urb) | ||
883 | finish_request(isp116x, ep, urb, NULL); | ||
884 | |||
885 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
886 | return 0; | ||
887 | } | ||
888 | |||
889 | static void isp116x_endpoint_disable(struct usb_hcd *hcd, | ||
890 | struct usb_host_endpoint *hep) | ||
891 | { | ||
892 | int i; | ||
893 | struct isp116x_ep *ep = hep->hcpriv;; | ||
894 | |||
895 | if (!ep) | ||
896 | return; | ||
897 | |||
898 | /* assume we'd just wait for the irq */ | ||
899 | for (i = 0; i < 100 && !list_empty(&hep->urb_list); i++) | ||
900 | msleep(3); | ||
901 | if (!list_empty(&hep->urb_list)) | ||
902 | WARN("ep %p not empty?\n", ep); | ||
903 | |||
904 | usb_put_dev(ep->udev); | ||
905 | kfree(ep); | ||
906 | hep->hcpriv = NULL; | ||
907 | } | ||
908 | |||
909 | static int isp116x_get_frame(struct usb_hcd *hcd) | ||
910 | { | ||
911 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
912 | u32 fmnum; | ||
913 | unsigned long flags; | ||
914 | |||
915 | spin_lock_irqsave(&isp116x->lock, flags); | ||
916 | fmnum = isp116x_read_reg32(isp116x, HCFMNUM); | ||
917 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
918 | return (int)fmnum; | ||
919 | } | ||
920 | |||
921 | /*----------------------------------------------------------------*/ | ||
922 | |||
923 | /* | ||
924 | Adapted from ohci-hub.c. Currently we don't support autosuspend. | ||
925 | */ | ||
926 | static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
927 | { | ||
928 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
929 | int ports, i, changed = 0; | ||
930 | |||
931 | if (!HC_IS_RUNNING(hcd->state)) | ||
932 | return -ESHUTDOWN; | ||
933 | |||
934 | ports = isp116x->rhdesca & RH_A_NDP; | ||
935 | |||
936 | /* init status */ | ||
937 | if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC)) | ||
938 | buf[0] = changed = 1; | ||
939 | else | ||
940 | buf[0] = 0; | ||
941 | |||
942 | for (i = 0; i < ports; i++) { | ||
943 | u32 status = isp116x->rhport[i]; | ||
944 | |||
945 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | ||
946 | | RH_PS_OCIC | RH_PS_PRSC)) { | ||
947 | changed = 1; | ||
948 | buf[0] |= 1 << (i + 1); | ||
949 | continue; | ||
950 | } | ||
951 | } | ||
952 | return changed; | ||
953 | } | ||
954 | |||
955 | static void isp116x_hub_descriptor(struct isp116x *isp116x, | ||
956 | struct usb_hub_descriptor *desc) | ||
957 | { | ||
958 | u32 reg = isp116x->rhdesca; | ||
959 | |||
960 | desc->bDescriptorType = 0x29; | ||
961 | desc->bDescLength = 9; | ||
962 | desc->bHubContrCurrent = 0; | ||
963 | desc->bNbrPorts = (u8) (reg & 0x3); | ||
964 | /* Power switching, device type, overcurrent. */ | ||
965 | desc->wHubCharacteristics = | ||
966 | (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f)); | ||
967 | desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff); | ||
968 | /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ | ||
969 | desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; | ||
970 | desc->bitmap[1] = ~0; | ||
971 | } | ||
972 | |||
973 | /* Perform reset of a given port. | ||
974 | It would be great to just start the reset and let the | ||
975 | USB core to clear the reset in due time. However, | ||
976 | root hub ports should be reset for at least 50 ms, while | ||
977 | our chip stays in reset for about 10 ms. I.e., we must | ||
978 | repeatedly reset it ourself here. | ||
979 | */ | ||
980 | static inline void root_port_reset(struct isp116x *isp116x, unsigned port) | ||
981 | { | ||
982 | u32 tmp; | ||
983 | unsigned long flags, t; | ||
984 | |||
985 | /* Root hub reset should be 50 ms, but some devices | ||
986 | want it even longer. */ | ||
987 | t = jiffies + msecs_to_jiffies(100); | ||
988 | |||
989 | while (time_before(jiffies, t)) { | ||
990 | spin_lock_irqsave(&isp116x->lock, flags); | ||
991 | /* spin until any current reset finishes */ | ||
992 | for (;;) { | ||
993 | tmp = isp116x_read_reg32(isp116x, port ? | ||
994 | HCRHPORT2 : HCRHPORT1); | ||
995 | if (!(tmp & RH_PS_PRS)) | ||
996 | break; | ||
997 | udelay(500); | ||
998 | } | ||
999 | /* Don't reset a disconnected port */ | ||
1000 | if (!(tmp & RH_PS_CCS)) { | ||
1001 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1002 | break; | ||
1003 | } | ||
1004 | /* Reset lasts 10ms (claims datasheet) */ | ||
1005 | isp116x_write_reg32(isp116x, port ? HCRHPORT2 : | ||
1006 | HCRHPORT1, (RH_PS_PRS)); | ||
1007 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1008 | msleep(10); | ||
1009 | } | ||
1010 | } | ||
1011 | |||
1012 | /* Adapted from ohci-hub.c */ | ||
1013 | static int isp116x_hub_control(struct usb_hcd *hcd, | ||
1014 | u16 typeReq, | ||
1015 | u16 wValue, u16 wIndex, char *buf, u16 wLength) | ||
1016 | { | ||
1017 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1018 | int ret = 0; | ||
1019 | unsigned long flags; | ||
1020 | int ports = isp116x->rhdesca & RH_A_NDP; | ||
1021 | u32 tmp = 0; | ||
1022 | |||
1023 | switch (typeReq) { | ||
1024 | case ClearHubFeature: | ||
1025 | DBG("ClearHubFeature: "); | ||
1026 | switch (wValue) { | ||
1027 | case C_HUB_OVER_CURRENT: | ||
1028 | DBG("C_HUB_OVER_CURRENT\n"); | ||
1029 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1030 | isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC); | ||
1031 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1032 | case C_HUB_LOCAL_POWER: | ||
1033 | DBG("C_HUB_LOCAL_POWER\n"); | ||
1034 | break; | ||
1035 | default: | ||
1036 | goto error; | ||
1037 | } | ||
1038 | break; | ||
1039 | case SetHubFeature: | ||
1040 | DBG("SetHubFeature: "); | ||
1041 | switch (wValue) { | ||
1042 | case C_HUB_OVER_CURRENT: | ||
1043 | case C_HUB_LOCAL_POWER: | ||
1044 | DBG("C_HUB_OVER_CURRENT or C_HUB_LOCAL_POWER\n"); | ||
1045 | break; | ||
1046 | default: | ||
1047 | goto error; | ||
1048 | } | ||
1049 | break; | ||
1050 | case GetHubDescriptor: | ||
1051 | DBG("GetHubDescriptor\n"); | ||
1052 | isp116x_hub_descriptor(isp116x, | ||
1053 | (struct usb_hub_descriptor *)buf); | ||
1054 | break; | ||
1055 | case GetHubStatus: | ||
1056 | DBG("GetHubStatus\n"); | ||
1057 | *(__le32 *) buf = cpu_to_le32(0); | ||
1058 | break; | ||
1059 | case GetPortStatus: | ||
1060 | DBG("GetPortStatus\n"); | ||
1061 | if (!wIndex || wIndex > ports) | ||
1062 | goto error; | ||
1063 | tmp = isp116x->rhport[--wIndex]; | ||
1064 | *(__le32 *) buf = cpu_to_le32(tmp); | ||
1065 | DBG("GetPortStatus: port[%d] %08x\n", wIndex + 1, tmp); | ||
1066 | break; | ||
1067 | case ClearPortFeature: | ||
1068 | DBG("ClearPortFeature: "); | ||
1069 | if (!wIndex || wIndex > ports) | ||
1070 | goto error; | ||
1071 | wIndex--; | ||
1072 | |||
1073 | switch (wValue) { | ||
1074 | case USB_PORT_FEAT_ENABLE: | ||
1075 | DBG("USB_PORT_FEAT_ENABLE\n"); | ||
1076 | tmp = RH_PS_CCS; | ||
1077 | break; | ||
1078 | case USB_PORT_FEAT_C_ENABLE: | ||
1079 | DBG("USB_PORT_FEAT_C_ENABLE\n"); | ||
1080 | tmp = RH_PS_PESC; | ||
1081 | break; | ||
1082 | case USB_PORT_FEAT_SUSPEND: | ||
1083 | DBG("USB_PORT_FEAT_SUSPEND\n"); | ||
1084 | tmp = RH_PS_POCI; | ||
1085 | break; | ||
1086 | case USB_PORT_FEAT_C_SUSPEND: | ||
1087 | DBG("USB_PORT_FEAT_C_SUSPEND\n"); | ||
1088 | tmp = RH_PS_PSSC; | ||
1089 | break; | ||
1090 | case USB_PORT_FEAT_POWER: | ||
1091 | DBG("USB_PORT_FEAT_POWER\n"); | ||
1092 | tmp = RH_PS_LSDA; | ||
1093 | break; | ||
1094 | case USB_PORT_FEAT_C_CONNECTION: | ||
1095 | DBG("USB_PORT_FEAT_C_CONNECTION\n"); | ||
1096 | tmp = RH_PS_CSC; | ||
1097 | break; | ||
1098 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
1099 | DBG("USB_PORT_FEAT_C_OVER_CURRENT\n"); | ||
1100 | tmp = RH_PS_OCIC; | ||
1101 | break; | ||
1102 | case USB_PORT_FEAT_C_RESET: | ||
1103 | DBG("USB_PORT_FEAT_C_RESET\n"); | ||
1104 | tmp = RH_PS_PRSC; | ||
1105 | break; | ||
1106 | default: | ||
1107 | goto error; | ||
1108 | } | ||
1109 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1110 | isp116x_write_reg32(isp116x, wIndex | ||
1111 | ? HCRHPORT2 : HCRHPORT1, tmp); | ||
1112 | isp116x->rhport[wIndex] = | ||
1113 | isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1); | ||
1114 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1115 | break; | ||
1116 | case SetPortFeature: | ||
1117 | DBG("SetPortFeature: "); | ||
1118 | if (!wIndex || wIndex > ports) | ||
1119 | goto error; | ||
1120 | wIndex--; | ||
1121 | switch (wValue) { | ||
1122 | case USB_PORT_FEAT_SUSPEND: | ||
1123 | DBG("USB_PORT_FEAT_SUSPEND\n"); | ||
1124 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1125 | isp116x_write_reg32(isp116x, wIndex | ||
1126 | ? HCRHPORT2 : HCRHPORT1, RH_PS_PSS); | ||
1127 | break; | ||
1128 | case USB_PORT_FEAT_POWER: | ||
1129 | DBG("USB_PORT_FEAT_POWER\n"); | ||
1130 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1131 | isp116x_write_reg32(isp116x, wIndex | ||
1132 | ? HCRHPORT2 : HCRHPORT1, RH_PS_PPS); | ||
1133 | break; | ||
1134 | case USB_PORT_FEAT_RESET: | ||
1135 | DBG("USB_PORT_FEAT_RESET\n"); | ||
1136 | root_port_reset(isp116x, wIndex); | ||
1137 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1138 | break; | ||
1139 | default: | ||
1140 | goto error; | ||
1141 | } | ||
1142 | isp116x->rhport[wIndex] = | ||
1143 | isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1); | ||
1144 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1145 | break; | ||
1146 | |||
1147 | default: | ||
1148 | error: | ||
1149 | /* "protocol stall" on error */ | ||
1150 | DBG("PROTOCOL STALL\n"); | ||
1151 | ret = -EPIPE; | ||
1152 | } | ||
1153 | return ret; | ||
1154 | } | ||
1155 | |||
1156 | #ifdef CONFIG_PM | ||
1157 | |||
1158 | static int isp116x_hub_suspend(struct usb_hcd *hcd) | ||
1159 | { | ||
1160 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1161 | unsigned long flags; | ||
1162 | u32 val; | ||
1163 | int ret = 0; | ||
1164 | |||
1165 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1166 | |||
1167 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1168 | switch (val & HCCONTROL_HCFS) { | ||
1169 | case HCCONTROL_USB_OPER: | ||
1170 | hcd->state = HC_STATE_QUIESCING; | ||
1171 | val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); | ||
1172 | val |= HCCONTROL_USB_SUSPEND; | ||
1173 | if (hcd->remote_wakeup) | ||
1174 | val |= HCCONTROL_RWE; | ||
1175 | /* Wait for usb transfers to finish */ | ||
1176 | mdelay(2); | ||
1177 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1178 | hcd->state = HC_STATE_SUSPENDED; | ||
1179 | /* Wait for devices to suspend */ | ||
1180 | mdelay(5); | ||
1181 | case HCCONTROL_USB_SUSPEND: | ||
1182 | break; | ||
1183 | case HCCONTROL_USB_RESUME: | ||
1184 | isp116x_write_reg32(isp116x, HCCONTROL, | ||
1185 | (val & ~HCCONTROL_HCFS) | | ||
1186 | HCCONTROL_USB_RESET); | ||
1187 | case HCCONTROL_USB_RESET: | ||
1188 | ret = -EBUSY; | ||
1189 | break; | ||
1190 | default: | ||
1191 | ret = -EINVAL; | ||
1192 | } | ||
1193 | |||
1194 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1195 | return ret; | ||
1196 | } | ||
1197 | |||
1198 | static int isp116x_hub_resume(struct usb_hcd *hcd) | ||
1199 | { | ||
1200 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1201 | u32 val; | ||
1202 | int ret = -EINPROGRESS; | ||
1203 | |||
1204 | msleep(5); | ||
1205 | spin_lock_irq(&isp116x->lock); | ||
1206 | |||
1207 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1208 | switch (val & HCCONTROL_HCFS) { | ||
1209 | case HCCONTROL_USB_SUSPEND: | ||
1210 | val &= ~HCCONTROL_HCFS; | ||
1211 | val |= HCCONTROL_USB_RESUME; | ||
1212 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1213 | case HCCONTROL_USB_RESUME: | ||
1214 | break; | ||
1215 | case HCCONTROL_USB_OPER: | ||
1216 | /* Without setting power_state here the | ||
1217 | SUSPENDED state won't be removed from | ||
1218 | sysfs/usbN/power.state as a response to remote | ||
1219 | wakeup. Maybe in the future. */ | ||
1220 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1221 | ret = 0; | ||
1222 | break; | ||
1223 | default: | ||
1224 | ret = -EBUSY; | ||
1225 | } | ||
1226 | |||
1227 | if (ret != -EINPROGRESS) { | ||
1228 | spin_unlock_irq(&isp116x->lock); | ||
1229 | return ret; | ||
1230 | } | ||
1231 | |||
1232 | val = isp116x->rhdesca & RH_A_NDP; | ||
1233 | while (val--) { | ||
1234 | u32 stat = | ||
1235 | isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1); | ||
1236 | /* force global, not selective, resume */ | ||
1237 | if (!(stat & RH_PS_PSS)) | ||
1238 | continue; | ||
1239 | DBG("%s: Resuming port %d\n", __func__, val); | ||
1240 | isp116x_write_reg32(isp116x, RH_PS_POCI, val | ||
1241 | ? HCRHPORT2 : HCRHPORT1); | ||
1242 | } | ||
1243 | spin_unlock_irq(&isp116x->lock); | ||
1244 | |||
1245 | hcd->state = HC_STATE_RESUMING; | ||
1246 | mdelay(20); | ||
1247 | |||
1248 | /* Go operational */ | ||
1249 | spin_lock_irq(&isp116x->lock); | ||
1250 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1251 | isp116x_write_reg32(isp116x, HCCONTROL, | ||
1252 | (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER); | ||
1253 | spin_unlock_irq(&isp116x->lock); | ||
1254 | /* see analogous comment above */ | ||
1255 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1256 | hcd->state = HC_STATE_RUNNING; | ||
1257 | |||
1258 | return 0; | ||
1259 | } | ||
1260 | |||
1261 | static void isp116x_rh_resume(void *_hcd) | ||
1262 | { | ||
1263 | struct usb_hcd *hcd = _hcd; | ||
1264 | |||
1265 | usb_resume_device(hcd->self.root_hub); | ||
1266 | } | ||
1267 | |||
1268 | #else | ||
1269 | |||
1270 | #define isp116x_hub_suspend NULL | ||
1271 | #define isp116x_hub_resume NULL | ||
1272 | |||
1273 | static void isp116x_rh_resume(void *_hcd) | ||
1274 | { | ||
1275 | } | ||
1276 | |||
1277 | #endif | ||
1278 | |||
1279 | /*-----------------------------------------------------------------*/ | ||
1280 | |||
1281 | #ifdef STUB_DEBUG_FILE | ||
1282 | |||
1283 | static inline void create_debug_file(struct isp116x *isp116x) | ||
1284 | { | ||
1285 | } | ||
1286 | |||
1287 | static inline void remove_debug_file(struct isp116x *isp116x) | ||
1288 | { | ||
1289 | } | ||
1290 | |||
1291 | #else | ||
1292 | |||
1293 | #include <linux/proc_fs.h> | ||
1294 | #include <linux/seq_file.h> | ||
1295 | |||
1296 | static void dump_irq(struct seq_file *s, char *label, u16 mask) | ||
1297 | { | ||
1298 | seq_printf(s, "%s %04x%s%s%s%s%s%s\n", label, mask, | ||
1299 | mask & HCuPINT_CLKRDY ? " clkrdy" : "", | ||
1300 | mask & HCuPINT_SUSP ? " susp" : "", | ||
1301 | mask & HCuPINT_OPR ? " opr" : "", | ||
1302 | mask & HCuPINT_AIIEOT ? " eot" : "", | ||
1303 | mask & HCuPINT_ATL ? " atl" : "", | ||
1304 | mask & HCuPINT_SOF ? " sof" : ""); | ||
1305 | } | ||
1306 | |||
1307 | static void dump_int(struct seq_file *s, char *label, u32 mask) | ||
1308 | { | ||
1309 | seq_printf(s, "%s %08x%s%s%s%s%s%s%s\n", label, mask, | ||
1310 | mask & HCINT_MIE ? " MIE" : "", | ||
1311 | mask & HCINT_RHSC ? " rhsc" : "", | ||
1312 | mask & HCINT_FNO ? " fno" : "", | ||
1313 | mask & HCINT_UE ? " ue" : "", | ||
1314 | mask & HCINT_RD ? " rd" : "", | ||
1315 | mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : ""); | ||
1316 | } | ||
1317 | |||
1318 | static int proc_isp116x_show(struct seq_file *s, void *unused) | ||
1319 | { | ||
1320 | struct isp116x *isp116x = s->private; | ||
1321 | struct isp116x_ep *ep; | ||
1322 | struct urb *urb; | ||
1323 | unsigned i; | ||
1324 | char *str; | ||
1325 | |||
1326 | seq_printf(s, "%s\n%s version %s\n", | ||
1327 | isp116x_to_hcd(isp116x)->product_desc, hcd_name, | ||
1328 | DRIVER_VERSION); | ||
1329 | |||
1330 | if (HC_IS_SUSPENDED(isp116x_to_hcd(isp116x)->state)) { | ||
1331 | seq_printf(s, "HCD is suspended\n"); | ||
1332 | return 0; | ||
1333 | } | ||
1334 | if (!HC_IS_RUNNING(isp116x_to_hcd(isp116x)->state)) { | ||
1335 | seq_printf(s, "HCD not running\n"); | ||
1336 | return 0; | ||
1337 | } | ||
1338 | |||
1339 | spin_lock_irq(&isp116x->lock); | ||
1340 | |||
1341 | dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB)); | ||
1342 | dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT)); | ||
1343 | dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB)); | ||
1344 | dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT)); | ||
1345 | |||
1346 | list_for_each_entry(ep, &isp116x->async, schedule) { | ||
1347 | |||
1348 | switch (ep->nextpid) { | ||
1349 | case USB_PID_IN: | ||
1350 | str = "in"; | ||
1351 | break; | ||
1352 | case USB_PID_OUT: | ||
1353 | str = "out"; | ||
1354 | break; | ||
1355 | case USB_PID_SETUP: | ||
1356 | str = "setup"; | ||
1357 | break; | ||
1358 | case USB_PID_ACK: | ||
1359 | str = "status"; | ||
1360 | break; | ||
1361 | default: | ||
1362 | str = "?"; | ||
1363 | break; | ||
1364 | }; | ||
1365 | seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep, | ||
1366 | ep->epnum, str, ep->maxpacket); | ||
1367 | list_for_each_entry(urb, &ep->hep->urb_list, urb_list) { | ||
1368 | seq_printf(s, " urb%p, %d/%d\n", urb, | ||
1369 | urb->actual_length, | ||
1370 | urb->transfer_buffer_length); | ||
1371 | } | ||
1372 | } | ||
1373 | if (!list_empty(&isp116x->async)) | ||
1374 | seq_printf(s, "\n"); | ||
1375 | |||
1376 | seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE); | ||
1377 | |||
1378 | for (i = 0; i < PERIODIC_SIZE; i++) { | ||
1379 | ep = isp116x->periodic[i]; | ||
1380 | if (!ep) | ||
1381 | continue; | ||
1382 | seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]); | ||
1383 | |||
1384 | /* DUMB: prints shared entries multiple times */ | ||
1385 | do { | ||
1386 | seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n", | ||
1387 | ep->period, ep, | ||
1388 | (ep->udev->speed == | ||
1389 | USB_SPEED_FULL) ? "" : "ls ", | ||
1390 | ep->udev->devnum, ep->epnum, | ||
1391 | (ep->epnum == | ||
1392 | 0) ? "" : ((ep->nextpid == | ||
1393 | USB_PID_IN) ? "in" : "out"), | ||
1394 | ep->maxpacket); | ||
1395 | ep = ep->next; | ||
1396 | } while (ep); | ||
1397 | } | ||
1398 | spin_unlock_irq(&isp116x->lock); | ||
1399 | seq_printf(s, "\n"); | ||
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static int proc_isp116x_open(struct inode *inode, struct file *file) | ||
1405 | { | ||
1406 | return single_open(file, proc_isp116x_show, PDE(inode)->data); | ||
1407 | } | ||
1408 | |||
1409 | static struct file_operations proc_ops = { | ||
1410 | .open = proc_isp116x_open, | ||
1411 | .read = seq_read, | ||
1412 | .llseek = seq_lseek, | ||
1413 | .release = single_release, | ||
1414 | }; | ||
1415 | |||
1416 | /* expect just one isp116x per system */ | ||
1417 | static const char proc_filename[] = "driver/isp116x"; | ||
1418 | |||
1419 | static void create_debug_file(struct isp116x *isp116x) | ||
1420 | { | ||
1421 | struct proc_dir_entry *pde; | ||
1422 | |||
1423 | pde = create_proc_entry(proc_filename, 0, NULL); | ||
1424 | if (pde == NULL) | ||
1425 | return; | ||
1426 | |||
1427 | pde->proc_fops = &proc_ops; | ||
1428 | pde->data = isp116x; | ||
1429 | isp116x->pde = pde; | ||
1430 | } | ||
1431 | |||
1432 | static void remove_debug_file(struct isp116x *isp116x) | ||
1433 | { | ||
1434 | if (isp116x->pde) | ||
1435 | remove_proc_entry(proc_filename, NULL); | ||
1436 | } | ||
1437 | |||
1438 | #endif | ||
1439 | |||
1440 | /*-----------------------------------------------------------------*/ | ||
1441 | |||
1442 | /* | ||
1443 | Software reset - can be called from any contect. | ||
1444 | */ | ||
1445 | static int isp116x_sw_reset(struct isp116x *isp116x) | ||
1446 | { | ||
1447 | int retries = 15; | ||
1448 | unsigned long flags; | ||
1449 | int ret = 0; | ||
1450 | |||
1451 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1452 | isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC); | ||
1453 | isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR); | ||
1454 | while (--retries) { | ||
1455 | /* It usually resets within 1 ms */ | ||
1456 | mdelay(1); | ||
1457 | if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR)) | ||
1458 | break; | ||
1459 | } | ||
1460 | if (!retries) { | ||
1461 | ERR("Software reset timeout\n"); | ||
1462 | ret = -ETIME; | ||
1463 | } | ||
1464 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1465 | return ret; | ||
1466 | } | ||
1467 | |||
1468 | /* | ||
1469 | Reset. Tries to perform platform-specific hardware | ||
1470 | reset first; falls back to software reset. | ||
1471 | */ | ||
1472 | static int isp116x_reset(struct usb_hcd *hcd) | ||
1473 | { | ||
1474 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1475 | unsigned long t; | ||
1476 | u16 clkrdy = 0; | ||
1477 | int ret = 0, timeout = 15 /* ms */ ; | ||
1478 | |||
1479 | if (isp116x->board && isp116x->board->reset) { | ||
1480 | /* Hardware reset */ | ||
1481 | isp116x->board->reset(hcd->self.controller, 1); | ||
1482 | msleep(10); | ||
1483 | if (isp116x->board->clock) | ||
1484 | isp116x->board->clock(hcd->self.controller, 1); | ||
1485 | msleep(1); | ||
1486 | isp116x->board->reset(hcd->self.controller, 0); | ||
1487 | } else | ||
1488 | ret = isp116x_sw_reset(isp116x); | ||
1489 | |||
1490 | if (ret) | ||
1491 | return ret; | ||
1492 | |||
1493 | t = jiffies + msecs_to_jiffies(timeout); | ||
1494 | while (time_before_eq(jiffies, t)) { | ||
1495 | msleep(4); | ||
1496 | spin_lock_irq(&isp116x->lock); | ||
1497 | clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY; | ||
1498 | spin_unlock_irq(&isp116x->lock); | ||
1499 | if (clkrdy) | ||
1500 | break; | ||
1501 | } | ||
1502 | if (!clkrdy) { | ||
1503 | ERR("Clock not ready after 20ms\n"); | ||
1504 | /* After sw_reset the clock won't report to be ready, if | ||
1505 | H_WAKEUP pin is high. */ | ||
1506 | if (!isp116x->board || !isp116x->board->reset) | ||
1507 | ERR("The driver does not support hardware wakeup.\n"); | ||
1508 | ERR("Please make sure that the H_WAKEUP pin " | ||
1509 | "is pulled low!\n"); | ||
1510 | ret = -ENODEV; | ||
1511 | } | ||
1512 | return ret; | ||
1513 | } | ||
1514 | |||
1515 | static void isp116x_stop(struct usb_hcd *hcd) | ||
1516 | { | ||
1517 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1518 | unsigned long flags; | ||
1519 | u32 val; | ||
1520 | |||
1521 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1522 | isp116x_write_reg16(isp116x, HCuPINTENB, 0); | ||
1523 | |||
1524 | /* Switch off ports' power, some devices don't come up | ||
1525 | after next 'insmod' without this */ | ||
1526 | val = isp116x_read_reg32(isp116x, HCRHDESCA); | ||
1527 | val &= ~(RH_A_NPS | RH_A_PSM); | ||
1528 | isp116x_write_reg32(isp116x, HCRHDESCA, val); | ||
1529 | isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); | ||
1530 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1531 | |||
1532 | /* Put the chip into reset state */ | ||
1533 | if (isp116x->board && isp116x->board->reset) | ||
1534 | isp116x->board->reset(hcd->self.controller, 0); | ||
1535 | else | ||
1536 | isp116x_sw_reset(isp116x); | ||
1537 | |||
1538 | /* Stop the clock */ | ||
1539 | if (isp116x->board && isp116x->board->clock) | ||
1540 | isp116x->board->clock(hcd->self.controller, 0); | ||
1541 | } | ||
1542 | |||
1543 | /* | ||
1544 | Configure the chip. The chip must be successfully reset by now. | ||
1545 | */ | ||
1546 | static int isp116x_start(struct usb_hcd *hcd) | ||
1547 | { | ||
1548 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1549 | struct isp116x_platform_data *board = isp116x->board; | ||
1550 | u32 val; | ||
1551 | unsigned long flags; | ||
1552 | |||
1553 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1554 | |||
1555 | /* clear interrupt status and disable all interrupt sources */ | ||
1556 | isp116x_write_reg16(isp116x, HCuPINT, 0xff); | ||
1557 | isp116x_write_reg16(isp116x, HCuPINTENB, 0); | ||
1558 | |||
1559 | val = isp116x_read_reg16(isp116x, HCCHIPID); | ||
1560 | if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) { | ||
1561 | ERR("Invalid chip ID %04x\n", val); | ||
1562 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1563 | return -ENODEV; | ||
1564 | } | ||
1565 | |||
1566 | isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); | ||
1567 | isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); | ||
1568 | |||
1569 | /* ----- HW conf */ | ||
1570 | val = HCHWCFG_INT_ENABLE | HCHWCFG_DBWIDTH(1); | ||
1571 | if (board->sel15Kres) | ||
1572 | val |= HCHWCFG_15KRSEL; | ||
1573 | /* Remote wakeup won't work without working clock */ | ||
1574 | if (board->clknotstop || board->remote_wakeup_enable) | ||
1575 | val |= HCHWCFG_CLKNOTSTOP; | ||
1576 | if (board->oc_enable) | ||
1577 | val |= HCHWCFG_ANALOG_OC; | ||
1578 | if (board->int_act_high) | ||
1579 | val |= HCHWCFG_INT_POL; | ||
1580 | if (board->int_edge_triggered) | ||
1581 | val |= HCHWCFG_INT_TRIGGER; | ||
1582 | isp116x_write_reg16(isp116x, HCHWCFG, val); | ||
1583 | |||
1584 | /* ----- Root hub conf */ | ||
1585 | val = 0; | ||
1586 | /* AN10003_1.pdf recommends NPS to be always 1 */ | ||
1587 | if (board->no_power_switching) | ||
1588 | val |= RH_A_NPS; | ||
1589 | if (board->power_switching_mode) | ||
1590 | val |= RH_A_PSM; | ||
1591 | if (board->potpg) | ||
1592 | val |= (board->potpg << 24) & RH_A_POTPGT; | ||
1593 | else | ||
1594 | val |= (25 << 24) & RH_A_POTPGT; | ||
1595 | isp116x_write_reg32(isp116x, HCRHDESCA, val); | ||
1596 | isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); | ||
1597 | |||
1598 | val = RH_B_PPCM; | ||
1599 | isp116x_write_reg32(isp116x, HCRHDESCB, val); | ||
1600 | isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB); | ||
1601 | |||
1602 | val = 0; | ||
1603 | if (board->remote_wakeup_enable) { | ||
1604 | hcd->can_wakeup = 1; | ||
1605 | val |= RH_HS_DRWE; | ||
1606 | } | ||
1607 | isp116x_write_reg32(isp116x, HCRHSTATUS, val); | ||
1608 | isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS); | ||
1609 | |||
1610 | isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf); | ||
1611 | |||
1612 | hcd->state = HC_STATE_RUNNING; | ||
1613 | |||
1614 | /* Set up interrupts */ | ||
1615 | isp116x->intenb = HCINT_MIE | HCINT_RHSC | HCINT_UE; | ||
1616 | if (board->remote_wakeup_enable) | ||
1617 | isp116x->intenb |= HCINT_RD; | ||
1618 | isp116x->irqenb = HCuPINT_ATL | HCuPINT_OPR; /* | HCuPINT_SUSP; */ | ||
1619 | isp116x_write_reg32(isp116x, HCINTENB, isp116x->intenb); | ||
1620 | isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); | ||
1621 | |||
1622 | /* Go operational */ | ||
1623 | val = HCCONTROL_USB_OPER; | ||
1624 | /* Remote wakeup connected - NOT SUPPORTED */ | ||
1625 | /* if (board->remote_wakeup_connected) | ||
1626 | val |= HCCONTROL_RWC; */ | ||
1627 | if (board->remote_wakeup_enable) | ||
1628 | val |= HCCONTROL_RWE; | ||
1629 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1630 | |||
1631 | /* Disable ports to avoid race in device enumeration */ | ||
1632 | isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); | ||
1633 | isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); | ||
1634 | |||
1635 | isp116x_show_regs(isp116x); | ||
1636 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1637 | return 0; | ||
1638 | } | ||
1639 | |||
1640 | /*-----------------------------------------------------------------*/ | ||
1641 | |||
1642 | static struct hc_driver isp116x_hc_driver = { | ||
1643 | .description = hcd_name, | ||
1644 | .product_desc = "ISP116x Host Controller", | ||
1645 | .hcd_priv_size = sizeof(struct isp116x), | ||
1646 | |||
1647 | .irq = isp116x_irq, | ||
1648 | .flags = HCD_USB11, | ||
1649 | |||
1650 | .reset = isp116x_reset, | ||
1651 | .start = isp116x_start, | ||
1652 | .stop = isp116x_stop, | ||
1653 | |||
1654 | .urb_enqueue = isp116x_urb_enqueue, | ||
1655 | .urb_dequeue = isp116x_urb_dequeue, | ||
1656 | .endpoint_disable = isp116x_endpoint_disable, | ||
1657 | |||
1658 | .get_frame_number = isp116x_get_frame, | ||
1659 | |||
1660 | .hub_status_data = isp116x_hub_status_data, | ||
1661 | .hub_control = isp116x_hub_control, | ||
1662 | .hub_suspend = isp116x_hub_suspend, | ||
1663 | .hub_resume = isp116x_hub_resume, | ||
1664 | }; | ||
1665 | |||
1666 | /*----------------------------------------------------------------*/ | ||
1667 | |||
1668 | static int __init_or_module isp116x_remove(struct device *dev) | ||
1669 | { | ||
1670 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
1671 | struct isp116x *isp116x; | ||
1672 | struct platform_device *pdev; | ||
1673 | struct resource *res; | ||
1674 | |||
1675 | if(!hcd) | ||
1676 | return 0; | ||
1677 | isp116x = hcd_to_isp116x(hcd); | ||
1678 | pdev = container_of(dev, struct platform_device, dev); | ||
1679 | remove_debug_file(isp116x); | ||
1680 | usb_remove_hcd(hcd); | ||
1681 | |||
1682 | iounmap(isp116x->data_reg); | ||
1683 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1684 | release_mem_region(res->start, 2); | ||
1685 | iounmap(isp116x->addr_reg); | ||
1686 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1687 | release_mem_region(res->start, 2); | ||
1688 | |||
1689 | usb_put_hcd(hcd); | ||
1690 | return 0; | ||
1691 | } | ||
1692 | |||
1693 | #define resource_len(r) (((r)->end - (r)->start) + 1) | ||
1694 | |||
1695 | static int __init isp116x_probe(struct device *dev) | ||
1696 | { | ||
1697 | struct usb_hcd *hcd; | ||
1698 | struct isp116x *isp116x; | ||
1699 | struct platform_device *pdev; | ||
1700 | struct resource *addr, *data; | ||
1701 | void __iomem *addr_reg; | ||
1702 | void __iomem *data_reg; | ||
1703 | int irq; | ||
1704 | int ret = 0; | ||
1705 | |||
1706 | pdev = container_of(dev, struct platform_device, dev); | ||
1707 | if (pdev->num_resources < 3) { | ||
1708 | ret = -ENODEV; | ||
1709 | goto err1; | ||
1710 | } | ||
1711 | |||
1712 | data = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1713 | addr = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1714 | irq = platform_get_irq(pdev, 0); | ||
1715 | if (!addr || !data || irq < 0) { | ||
1716 | ret = -ENODEV; | ||
1717 | goto err1; | ||
1718 | } | ||
1719 | |||
1720 | if (dev->dma_mask) { | ||
1721 | DBG("DMA not supported\n"); | ||
1722 | ret = -EINVAL; | ||
1723 | goto err1; | ||
1724 | } | ||
1725 | |||
1726 | if (!request_mem_region(addr->start, 2, hcd_name)) { | ||
1727 | ret = -EBUSY; | ||
1728 | goto err1; | ||
1729 | } | ||
1730 | addr_reg = ioremap(addr->start, resource_len(addr)); | ||
1731 | if (addr_reg == NULL) { | ||
1732 | ret = -ENOMEM; | ||
1733 | goto err2; | ||
1734 | } | ||
1735 | if (!request_mem_region(data->start, 2, hcd_name)) { | ||
1736 | ret = -EBUSY; | ||
1737 | goto err3; | ||
1738 | } | ||
1739 | data_reg = ioremap(data->start, resource_len(data)); | ||
1740 | if (data_reg == NULL) { | ||
1741 | ret = -ENOMEM; | ||
1742 | goto err4; | ||
1743 | } | ||
1744 | |||
1745 | /* allocate and initialize hcd */ | ||
1746 | hcd = usb_create_hcd(&isp116x_hc_driver, dev, dev->bus_id); | ||
1747 | if (!hcd) { | ||
1748 | ret = -ENOMEM; | ||
1749 | goto err5; | ||
1750 | } | ||
1751 | /* this rsrc_start is bogus */ | ||
1752 | hcd->rsrc_start = addr->start; | ||
1753 | isp116x = hcd_to_isp116x(hcd); | ||
1754 | isp116x->data_reg = data_reg; | ||
1755 | isp116x->addr_reg = addr_reg; | ||
1756 | spin_lock_init(&isp116x->lock); | ||
1757 | INIT_LIST_HEAD(&isp116x->async); | ||
1758 | INIT_WORK(&isp116x->rh_resume, isp116x_rh_resume, hcd); | ||
1759 | isp116x->board = dev->platform_data; | ||
1760 | |||
1761 | if (!isp116x->board) { | ||
1762 | ERR("Platform data structure not initialized\n"); | ||
1763 | ret = -ENODEV; | ||
1764 | goto err6; | ||
1765 | } | ||
1766 | if (isp116x_check_platform_delay(isp116x)) { | ||
1767 | ERR("USE_PLATFORM_DELAY defined, but delay function not " | ||
1768 | "implemented.\n"); | ||
1769 | ERR("See comments in drivers/usb/host/isp116x-hcd.c\n"); | ||
1770 | ret = -ENODEV; | ||
1771 | goto err6; | ||
1772 | } | ||
1773 | |||
1774 | ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); | ||
1775 | if (ret != 0) | ||
1776 | goto err6; | ||
1777 | |||
1778 | create_debug_file(isp116x); | ||
1779 | return 0; | ||
1780 | |||
1781 | err6: | ||
1782 | usb_put_hcd(hcd); | ||
1783 | err5: | ||
1784 | iounmap(data_reg); | ||
1785 | err4: | ||
1786 | release_mem_region(data->start, 2); | ||
1787 | err3: | ||
1788 | iounmap(addr_reg); | ||
1789 | err2: | ||
1790 | release_mem_region(addr->start, 2); | ||
1791 | err1: | ||
1792 | ERR("init error, %d\n", ret); | ||
1793 | return ret; | ||
1794 | } | ||
1795 | |||
1796 | #ifdef CONFIG_PM | ||
1797 | /* | ||
1798 | Suspend of platform device | ||
1799 | */ | ||
1800 | static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase) | ||
1801 | { | ||
1802 | int ret = 0; | ||
1803 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
1804 | |||
1805 | VDBG("%s: state %x, phase %x\n", __func__, state, phase); | ||
1806 | |||
1807 | if (phase != SUSPEND_DISABLE && phase != SUSPEND_POWER_DOWN) | ||
1808 | return 0; | ||
1809 | |||
1810 | ret = usb_suspend_device(hcd->self.root_hub, state); | ||
1811 | if (!ret) { | ||
1812 | dev->power.power_state = state; | ||
1813 | INFO("%s suspended\n", (char *)hcd_name); | ||
1814 | } else | ||
1815 | ERR("%s suspend failed\n", (char *)hcd_name); | ||
1816 | |||
1817 | return ret; | ||
1818 | } | ||
1819 | |||
1820 | /* | ||
1821 | Resume platform device | ||
1822 | */ | ||
1823 | static int isp116x_resume(struct device *dev, u32 phase) | ||
1824 | { | ||
1825 | int ret = 0; | ||
1826 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
1827 | |||
1828 | VDBG("%s: state %x, phase %x\n", __func__, dev->power.power_state, | ||
1829 | phase); | ||
1830 | if (phase != RESUME_POWER_ON) | ||
1831 | return 0; | ||
1832 | |||
1833 | ret = usb_resume_device(hcd->self.root_hub); | ||
1834 | if (!ret) { | ||
1835 | dev->power.power_state = PMSG_ON; | ||
1836 | VDBG("%s resumed\n", (char *)hcd_name); | ||
1837 | } | ||
1838 | return ret; | ||
1839 | } | ||
1840 | |||
1841 | #else | ||
1842 | |||
1843 | #define isp116x_suspend NULL | ||
1844 | #define isp116x_resume NULL | ||
1845 | |||
1846 | #endif | ||
1847 | |||
1848 | static struct device_driver isp116x_driver = { | ||
1849 | .name = (char *)hcd_name, | ||
1850 | .bus = &platform_bus_type, | ||
1851 | .probe = isp116x_probe, | ||
1852 | .remove = isp116x_remove, | ||
1853 | .suspend = isp116x_suspend, | ||
1854 | .resume = isp116x_resume, | ||
1855 | }; | ||
1856 | |||
1857 | /*-----------------------------------------------------------------*/ | ||
1858 | |||
1859 | static int __init isp116x_init(void) | ||
1860 | { | ||
1861 | if (usb_disabled()) | ||
1862 | return -ENODEV; | ||
1863 | |||
1864 | INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION); | ||
1865 | return driver_register(&isp116x_driver); | ||
1866 | } | ||
1867 | |||
1868 | module_init(isp116x_init); | ||
1869 | |||
1870 | static void __exit isp116x_cleanup(void) | ||
1871 | { | ||
1872 | driver_unregister(&isp116x_driver); | ||
1873 | } | ||
1874 | |||
1875 | module_exit(isp116x_cleanup); | ||
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h new file mode 100644 index 000000000000..58873470dcf5 --- /dev/null +++ b/drivers/usb/host/isp116x.h | |||
@@ -0,0 +1,583 @@ | |||
1 | /* | ||
2 | * ISP116x register declarations and HCD data structures | ||
3 | * | ||
4 | * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee> | ||
5 | * Portions: | ||
6 | * Copyright (C) 2004 Lothar Wassmann | ||
7 | * Copyright (C) 2004 Psion Teklogix | ||
8 | * Copyright (C) 2004 David Brownell | ||
9 | */ | ||
10 | |||
11 | /* us of 1ms frame */ | ||
12 | #define MAX_LOAD_LIMIT 850 | ||
13 | |||
14 | /* Full speed: max # of bytes to transfer for a single urb | ||
15 | at a time must be < 1024 && must be multiple of 64. | ||
16 | 832 allows transfering 4kiB within 5 frames. */ | ||
17 | #define MAX_TRANSFER_SIZE_FULLSPEED 832 | ||
18 | |||
19 | /* Low speed: there is no reason to schedule in very big | ||
20 | chunks; often the requested long transfers are for | ||
21 | string descriptors containing short strings. */ | ||
22 | #define MAX_TRANSFER_SIZE_LOWSPEED 64 | ||
23 | |||
24 | /* Bytetime (us), a rough indication of how much time it | ||
25 | would take to transfer a byte of useful data over USB */ | ||
26 | #define BYTE_TIME_FULLSPEED 1 | ||
27 | #define BYTE_TIME_LOWSPEED 20 | ||
28 | |||
29 | /* Buffer sizes */ | ||
30 | #define ISP116x_BUF_SIZE 4096 | ||
31 | #define ISP116x_ITL_BUFSIZE 0 | ||
32 | #define ISP116x_ATL_BUFSIZE ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE)) | ||
33 | |||
34 | #define ISP116x_WRITE_OFFSET 0x80 | ||
35 | |||
36 | /*------------ ISP116x registers/bits ------------*/ | ||
37 | #define HCREVISION 0x00 | ||
38 | #define HCCONTROL 0x01 | ||
39 | #define HCCONTROL_HCFS (3 << 6) /* host controller | ||
40 | functional state */ | ||
41 | #define HCCONTROL_USB_RESET (0 << 6) | ||
42 | #define HCCONTROL_USB_RESUME (1 << 6) | ||
43 | #define HCCONTROL_USB_OPER (2 << 6) | ||
44 | #define HCCONTROL_USB_SUSPEND (3 << 6) | ||
45 | #define HCCONTROL_RWC (1 << 9) /* remote wakeup connected */ | ||
46 | #define HCCONTROL_RWE (1 << 10) /* remote wakeup enable */ | ||
47 | #define HCCMDSTAT 0x02 | ||
48 | #define HCCMDSTAT_HCR (1 << 0) /* host controller reset */ | ||
49 | #define HCCMDSTAT_SOC (3 << 16) /* scheduling overrun count */ | ||
50 | #define HCINTSTAT 0x03 | ||
51 | #define HCINT_SO (1 << 0) /* scheduling overrun */ | ||
52 | #define HCINT_WDH (1 << 1) /* writeback of done_head */ | ||
53 | #define HCINT_SF (1 << 2) /* start frame */ | ||
54 | #define HCINT_RD (1 << 3) /* resume detect */ | ||
55 | #define HCINT_UE (1 << 4) /* unrecoverable error */ | ||
56 | #define HCINT_FNO (1 << 5) /* frame number overflow */ | ||
57 | #define HCINT_RHSC (1 << 6) /* root hub status change */ | ||
58 | #define HCINT_OC (1 << 30) /* ownership change */ | ||
59 | #define HCINT_MIE (1 << 31) /* master interrupt enable */ | ||
60 | #define HCINTENB 0x04 | ||
61 | #define HCINTDIS 0x05 | ||
62 | #define HCFMINTVL 0x0d | ||
63 | #define HCFMREM 0x0e | ||
64 | #define HCFMNUM 0x0f | ||
65 | #define HCLSTHRESH 0x11 | ||
66 | #define HCRHDESCA 0x12 | ||
67 | #define RH_A_NDP (0x3 << 0) /* # downstream ports */ | ||
68 | #define RH_A_PSM (1 << 8) /* power switching mode */ | ||
69 | #define RH_A_NPS (1 << 9) /* no power switching */ | ||
70 | #define RH_A_DT (1 << 10) /* device type (mbz) */ | ||
71 | #define RH_A_OCPM (1 << 11) /* overcurrent protection | ||
72 | mode */ | ||
73 | #define RH_A_NOCP (1 << 12) /* no overcurrent protection */ | ||
74 | #define RH_A_POTPGT (0xff << 24) /* power on -> power good | ||
75 | time */ | ||
76 | #define HCRHDESCB 0x13 | ||
77 | #define RH_B_DR (0xffff << 0) /* device removable flags */ | ||
78 | #define RH_B_PPCM (0xffff << 16) /* port power control mask */ | ||
79 | #define HCRHSTATUS 0x14 | ||
80 | #define RH_HS_LPS (1 << 0) /* local power status */ | ||
81 | #define RH_HS_OCI (1 << 1) /* over current indicator */ | ||
82 | #define RH_HS_DRWE (1 << 15) /* device remote wakeup | ||
83 | enable */ | ||
84 | #define RH_HS_LPSC (1 << 16) /* local power status change */ | ||
85 | #define RH_HS_OCIC (1 << 17) /* over current indicator | ||
86 | change */ | ||
87 | #define RH_HS_CRWE (1 << 31) /* clear remote wakeup | ||
88 | enable */ | ||
89 | #define HCRHPORT1 0x15 | ||
90 | #define RH_PS_CCS (1 << 0) /* current connect status */ | ||
91 | #define RH_PS_PES (1 << 1) /* port enable status */ | ||
92 | #define RH_PS_PSS (1 << 2) /* port suspend status */ | ||
93 | #define RH_PS_POCI (1 << 3) /* port over current | ||
94 | indicator */ | ||
95 | #define RH_PS_PRS (1 << 4) /* port reset status */ | ||
96 | #define RH_PS_PPS (1 << 8) /* port power status */ | ||
97 | #define RH_PS_LSDA (1 << 9) /* low speed device attached */ | ||
98 | #define RH_PS_CSC (1 << 16) /* connect status change */ | ||
99 | #define RH_PS_PESC (1 << 17) /* port enable status change */ | ||
100 | #define RH_PS_PSSC (1 << 18) /* port suspend status | ||
101 | change */ | ||
102 | #define RH_PS_OCIC (1 << 19) /* over current indicator | ||
103 | change */ | ||
104 | #define RH_PS_PRSC (1 << 20) /* port reset status change */ | ||
105 | #define HCRHPORT_CLRMASK (0x1f << 16) | ||
106 | #define HCRHPORT2 0x16 | ||
107 | #define HCHWCFG 0x20 | ||
108 | #define HCHWCFG_15KRSEL (1 << 12) | ||
109 | #define HCHWCFG_CLKNOTSTOP (1 << 11) | ||
110 | #define HCHWCFG_ANALOG_OC (1 << 10) | ||
111 | #define HCHWCFG_DACK_MODE (1 << 8) | ||
112 | #define HCHWCFG_EOT_POL (1 << 7) | ||
113 | #define HCHWCFG_DACK_POL (1 << 6) | ||
114 | #define HCHWCFG_DREQ_POL (1 << 5) | ||
115 | #define HCHWCFG_DBWIDTH_MASK (0x03 << 3) | ||
116 | #define HCHWCFG_DBWIDTH(n) (((n) << 3) & HCHWCFG_DBWIDTH_MASK) | ||
117 | #define HCHWCFG_INT_POL (1 << 2) | ||
118 | #define HCHWCFG_INT_TRIGGER (1 << 1) | ||
119 | #define HCHWCFG_INT_ENABLE (1 << 0) | ||
120 | #define HCDMACFG 0x21 | ||
121 | #define HCDMACFG_BURST_LEN_MASK (0x03 << 5) | ||
122 | #define HCDMACFG_BURST_LEN(n) (((n) << 5) & HCDMACFG_BURST_LEN_MASK) | ||
123 | #define HCDMACFG_BURST_LEN_1 HCDMACFG_BURST_LEN(0) | ||
124 | #define HCDMACFG_BURST_LEN_4 HCDMACFG_BURST_LEN(1) | ||
125 | #define HCDMACFG_BURST_LEN_8 HCDMACFG_BURST_LEN(2) | ||
126 | #define HCDMACFG_DMA_ENABLE (1 << 4) | ||
127 | #define HCDMACFG_BUF_TYPE_MASK (0x07 << 1) | ||
128 | #define HCDMACFG_CTR_SEL (1 << 2) | ||
129 | #define HCDMACFG_ITLATL_SEL (1 << 1) | ||
130 | #define HCDMACFG_DMA_RW_SELECT (1 << 0) | ||
131 | #define HCXFERCTR 0x22 | ||
132 | #define HCuPINT 0x24 | ||
133 | #define HCuPINT_SOF (1 << 0) | ||
134 | #define HCuPINT_ATL (1 << 1) | ||
135 | #define HCuPINT_AIIEOT (1 << 2) | ||
136 | #define HCuPINT_OPR (1 << 4) | ||
137 | #define HCuPINT_SUSP (1 << 5) | ||
138 | #define HCuPINT_CLKRDY (1 << 6) | ||
139 | #define HCuPINTENB 0x25 | ||
140 | #define HCCHIPID 0x27 | ||
141 | #define HCCHIPID_MASK 0xff00 | ||
142 | #define HCCHIPID_MAGIC 0x6100 | ||
143 | #define HCSCRATCH 0x28 | ||
144 | #define HCSWRES 0x29 | ||
145 | #define HCSWRES_MAGIC 0x00f6 | ||
146 | #define HCITLBUFLEN 0x2a | ||
147 | #define HCATLBUFLEN 0x2b | ||
148 | #define HCBUFSTAT 0x2c | ||
149 | #define HCBUFSTAT_ITL0_FULL (1 << 0) | ||
150 | #define HCBUFSTAT_ITL1_FULL (1 << 1) | ||
151 | #define HCBUFSTAT_ATL_FULL (1 << 2) | ||
152 | #define HCBUFSTAT_ITL0_DONE (1 << 3) | ||
153 | #define HCBUFSTAT_ITL1_DONE (1 << 4) | ||
154 | #define HCBUFSTAT_ATL_DONE (1 << 5) | ||
155 | #define HCRDITL0LEN 0x2d | ||
156 | #define HCRDITL1LEN 0x2e | ||
157 | #define HCITLPORT 0x40 | ||
158 | #define HCATLPORT 0x41 | ||
159 | |||
160 | /* Philips transfer descriptor */ | ||
161 | struct ptd { | ||
162 | u16 count; | ||
163 | #define PTD_COUNT_MSK (0x3ff << 0) | ||
164 | #define PTD_TOGGLE_MSK (1 << 10) | ||
165 | #define PTD_ACTIVE_MSK (1 << 11) | ||
166 | #define PTD_CC_MSK (0xf << 12) | ||
167 | u16 mps; | ||
168 | #define PTD_MPS_MSK (0x3ff << 0) | ||
169 | #define PTD_SPD_MSK (1 << 10) | ||
170 | #define PTD_LAST_MSK (1 << 11) | ||
171 | #define PTD_EP_MSK (0xf << 12) | ||
172 | u16 len; | ||
173 | #define PTD_LEN_MSK (0x3ff << 0) | ||
174 | #define PTD_DIR_MSK (3 << 10) | ||
175 | #define PTD_DIR_SETUP (0) | ||
176 | #define PTD_DIR_OUT (1) | ||
177 | #define PTD_DIR_IN (2) | ||
178 | #define PTD_B5_5_MSK (1 << 13) | ||
179 | u16 faddr; | ||
180 | #define PTD_FA_MSK (0x7f << 0) | ||
181 | #define PTD_FMT_MSK (1 << 7) | ||
182 | } __attribute__ ((packed, aligned(2))); | ||
183 | |||
184 | /* PTD accessor macros. */ | ||
185 | #define PTD_GET_COUNT(p) (((p)->count & PTD_COUNT_MSK) >> 0) | ||
186 | #define PTD_COUNT(v) (((v) << 0) & PTD_COUNT_MSK) | ||
187 | #define PTD_GET_TOGGLE(p) (((p)->count & PTD_TOGGLE_MSK) >> 10) | ||
188 | #define PTD_TOGGLE(v) (((v) << 10) & PTD_TOGGLE_MSK) | ||
189 | #define PTD_GET_ACTIVE(p) (((p)->count & PTD_ACTIVE_MSK) >> 11) | ||
190 | #define PTD_ACTIVE(v) (((v) << 11) & PTD_ACTIVE_MSK) | ||
191 | #define PTD_GET_CC(p) (((p)->count & PTD_CC_MSK) >> 12) | ||
192 | #define PTD_CC(v) (((v) << 12) & PTD_CC_MSK) | ||
193 | #define PTD_GET_MPS(p) (((p)->mps & PTD_MPS_MSK) >> 0) | ||
194 | #define PTD_MPS(v) (((v) << 0) & PTD_MPS_MSK) | ||
195 | #define PTD_GET_SPD(p) (((p)->mps & PTD_SPD_MSK) >> 10) | ||
196 | #define PTD_SPD(v) (((v) << 10) & PTD_SPD_MSK) | ||
197 | #define PTD_GET_LAST(p) (((p)->mps & PTD_LAST_MSK) >> 11) | ||
198 | #define PTD_LAST(v) (((v) << 11) & PTD_LAST_MSK) | ||
199 | #define PTD_GET_EP(p) (((p)->mps & PTD_EP_MSK) >> 12) | ||
200 | #define PTD_EP(v) (((v) << 12) & PTD_EP_MSK) | ||
201 | #define PTD_GET_LEN(p) (((p)->len & PTD_LEN_MSK) >> 0) | ||
202 | #define PTD_LEN(v) (((v) << 0) & PTD_LEN_MSK) | ||
203 | #define PTD_GET_DIR(p) (((p)->len & PTD_DIR_MSK) >> 10) | ||
204 | #define PTD_DIR(v) (((v) << 10) & PTD_DIR_MSK) | ||
205 | #define PTD_GET_B5_5(p) (((p)->len & PTD_B5_5_MSK) >> 13) | ||
206 | #define PTD_B5_5(v) (((v) << 13) & PTD_B5_5_MSK) | ||
207 | #define PTD_GET_FA(p) (((p)->faddr & PTD_FA_MSK) >> 0) | ||
208 | #define PTD_FA(v) (((v) << 0) & PTD_FA_MSK) | ||
209 | #define PTD_GET_FMT(p) (((p)->faddr & PTD_FMT_MSK) >> 7) | ||
210 | #define PTD_FMT(v) (((v) << 7) & PTD_FMT_MSK) | ||
211 | |||
212 | /* Hardware transfer status codes -- CC from ptd->count */ | ||
213 | #define TD_CC_NOERROR 0x00 | ||
214 | #define TD_CC_CRC 0x01 | ||
215 | #define TD_CC_BITSTUFFING 0x02 | ||
216 | #define TD_CC_DATATOGGLEM 0x03 | ||
217 | #define TD_CC_STALL 0x04 | ||
218 | #define TD_DEVNOTRESP 0x05 | ||
219 | #define TD_PIDCHECKFAIL 0x06 | ||
220 | #define TD_UNEXPECTEDPID 0x07 | ||
221 | #define TD_DATAOVERRUN 0x08 | ||
222 | #define TD_DATAUNDERRUN 0x09 | ||
223 | /* 0x0A, 0x0B reserved for hardware */ | ||
224 | #define TD_BUFFEROVERRUN 0x0C | ||
225 | #define TD_BUFFERUNDERRUN 0x0D | ||
226 | /* 0x0E, 0x0F reserved for HCD */ | ||
227 | #define TD_NOTACCESSED 0x0F | ||
228 | |||
229 | /* map PTD status codes (CC) to errno values */ | ||
230 | static const int cc_to_error[16] = { | ||
231 | /* No Error */ 0, | ||
232 | /* CRC Error */ -EILSEQ, | ||
233 | /* Bit Stuff */ -EPROTO, | ||
234 | /* Data Togg */ -EILSEQ, | ||
235 | /* Stall */ -EPIPE, | ||
236 | /* DevNotResp */ -ETIMEDOUT, | ||
237 | /* PIDCheck */ -EPROTO, | ||
238 | /* UnExpPID */ -EPROTO, | ||
239 | /* DataOver */ -EOVERFLOW, | ||
240 | /* DataUnder */ -EREMOTEIO, | ||
241 | /* (for hw) */ -EIO, | ||
242 | /* (for hw) */ -EIO, | ||
243 | /* BufferOver */ -ECOMM, | ||
244 | /* BuffUnder */ -ENOSR, | ||
245 | /* (for HCD) */ -EALREADY, | ||
246 | /* (for HCD) */ -EALREADY | ||
247 | }; | ||
248 | |||
249 | /*--------------------------------------------------------------*/ | ||
250 | |||
251 | #define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */ | ||
252 | #define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE) | ||
253 | |||
254 | struct isp116x { | ||
255 | spinlock_t lock; | ||
256 | struct work_struct rh_resume; | ||
257 | |||
258 | void __iomem *addr_reg; | ||
259 | void __iomem *data_reg; | ||
260 | |||
261 | struct isp116x_platform_data *board; | ||
262 | |||
263 | struct proc_dir_entry *pde; | ||
264 | unsigned long stat1, stat2, stat4, stat8, stat16; | ||
265 | |||
266 | /* HC registers */ | ||
267 | u32 intenb; /* "OHCI" interrupts */ | ||
268 | u16 irqenb; /* uP interrupts */ | ||
269 | |||
270 | /* Root hub registers */ | ||
271 | u32 rhdesca; | ||
272 | u32 rhdescb; | ||
273 | u32 rhstatus; | ||
274 | u32 rhport[2]; | ||
275 | |||
276 | /* async schedule: control, bulk */ | ||
277 | struct list_head async; | ||
278 | |||
279 | /* periodic schedule: int */ | ||
280 | u16 load[PERIODIC_SIZE]; | ||
281 | struct isp116x_ep *periodic[PERIODIC_SIZE]; | ||
282 | unsigned periodic_count; | ||
283 | u16 fmindex; | ||
284 | |||
285 | /* Schedule for the current frame */ | ||
286 | struct isp116x_ep *atl_active; | ||
287 | int atl_buflen; | ||
288 | int atl_bufshrt; | ||
289 | int atl_last_dir; | ||
290 | atomic_t atl_finishing; | ||
291 | }; | ||
292 | |||
293 | static inline struct isp116x *hcd_to_isp116x(struct usb_hcd *hcd) | ||
294 | { | ||
295 | return (struct isp116x *)(hcd->hcd_priv); | ||
296 | } | ||
297 | |||
298 | static inline struct usb_hcd *isp116x_to_hcd(struct isp116x *isp116x) | ||
299 | { | ||
300 | return container_of((void *)isp116x, struct usb_hcd, hcd_priv); | ||
301 | } | ||
302 | |||
303 | struct isp116x_ep { | ||
304 | struct usb_host_endpoint *hep; | ||
305 | struct usb_device *udev; | ||
306 | struct ptd ptd; | ||
307 | |||
308 | u8 maxpacket; | ||
309 | u8 epnum; | ||
310 | u8 nextpid; | ||
311 | u16 error_count; | ||
312 | u16 length; /* of current packet */ | ||
313 | unsigned char *data; /* to databuf */ | ||
314 | /* queue of active EP's (the ones scheduled for the | ||
315 | current frame) */ | ||
316 | struct isp116x_ep *active; | ||
317 | |||
318 | /* periodic schedule */ | ||
319 | u16 period; | ||
320 | u16 branch; | ||
321 | u16 load; | ||
322 | struct isp116x_ep *next; | ||
323 | |||
324 | /* async schedule */ | ||
325 | struct list_head schedule; | ||
326 | }; | ||
327 | |||
328 | /*-------------------------------------------------------------------------*/ | ||
329 | |||
330 | #ifdef DEBUG | ||
331 | #define DBG(stuff...) printk(KERN_DEBUG "116x: " stuff) | ||
332 | #else | ||
333 | #define DBG(stuff...) do{}while(0) | ||
334 | #endif | ||
335 | |||
336 | #ifdef VERBOSE | ||
337 | # define VDBG DBG | ||
338 | #else | ||
339 | # define VDBG(stuff...) do{}while(0) | ||
340 | #endif | ||
341 | |||
342 | #define ERR(stuff...) printk(KERN_ERR "116x: " stuff) | ||
343 | #define WARN(stuff...) printk(KERN_WARNING "116x: " stuff) | ||
344 | #define INFO(stuff...) printk(KERN_INFO "116x: " stuff) | ||
345 | |||
346 | /* ------------------------------------------------- */ | ||
347 | |||
348 | #if defined(USE_PLATFORM_DELAY) | ||
349 | #if defined(USE_NDELAY) | ||
350 | #error USE_PLATFORM_DELAY and USE_NDELAY simultaneously defined. | ||
351 | #endif | ||
352 | #define isp116x_delay(h,d) (h)->board->delay( \ | ||
353 | isp116x_to_hcd(h)->self.controller,d) | ||
354 | #define isp116x_check_platform_delay(h) ((h)->board->delay == NULL) | ||
355 | #elif defined(USE_NDELAY) | ||
356 | #define isp116x_delay(h,d) ndelay(d) | ||
357 | #define isp116x_check_platform_delay(h) 0 | ||
358 | #else | ||
359 | #define isp116x_delay(h,d) do{}while(0) | ||
360 | #define isp116x_check_platform_delay(h) 0 | ||
361 | #endif | ||
362 | |||
363 | #if defined(DEBUG) | ||
364 | #define IRQ_TEST() BUG_ON(!irqs_disabled()) | ||
365 | #else | ||
366 | #define IRQ_TEST() do{}while(0) | ||
367 | #endif | ||
368 | |||
369 | static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg) | ||
370 | { | ||
371 | IRQ_TEST(); | ||
372 | writew(reg & 0xff, isp116x->addr_reg); | ||
373 | isp116x_delay(isp116x, 300); | ||
374 | } | ||
375 | |||
376 | static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val) | ||
377 | { | ||
378 | writew(val, isp116x->data_reg); | ||
379 | isp116x_delay(isp116x, 150); | ||
380 | } | ||
381 | |||
382 | static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val) | ||
383 | { | ||
384 | __raw_writew(val, isp116x->data_reg); | ||
385 | isp116x_delay(isp116x, 150); | ||
386 | } | ||
387 | |||
388 | static inline u16 isp116x_read_data16(struct isp116x *isp116x) | ||
389 | { | ||
390 | u16 val; | ||
391 | |||
392 | val = readw(isp116x->data_reg); | ||
393 | isp116x_delay(isp116x, 150); | ||
394 | return val; | ||
395 | } | ||
396 | |||
397 | static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x) | ||
398 | { | ||
399 | u16 val; | ||
400 | |||
401 | val = __raw_readw(isp116x->data_reg); | ||
402 | isp116x_delay(isp116x, 150); | ||
403 | return val; | ||
404 | } | ||
405 | |||
406 | static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val) | ||
407 | { | ||
408 | writew(val & 0xffff, isp116x->data_reg); | ||
409 | isp116x_delay(isp116x, 150); | ||
410 | writew(val >> 16, isp116x->data_reg); | ||
411 | isp116x_delay(isp116x, 150); | ||
412 | } | ||
413 | |||
414 | static inline u32 isp116x_read_data32(struct isp116x *isp116x) | ||
415 | { | ||
416 | u32 val; | ||
417 | |||
418 | val = (u32) readw(isp116x->data_reg); | ||
419 | isp116x_delay(isp116x, 150); | ||
420 | val |= ((u32) readw(isp116x->data_reg)) << 16; | ||
421 | isp116x_delay(isp116x, 150); | ||
422 | return val; | ||
423 | } | ||
424 | |||
425 | /* Let's keep register access functions out of line. Hint: | ||
426 | we wait at least 150 ns at every access. | ||
427 | */ | ||
428 | static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg) | ||
429 | { | ||
430 | isp116x_write_addr(isp116x, reg); | ||
431 | return isp116x_read_data16(isp116x); | ||
432 | } | ||
433 | |||
434 | static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg) | ||
435 | { | ||
436 | isp116x_write_addr(isp116x, reg); | ||
437 | return isp116x_read_data32(isp116x); | ||
438 | } | ||
439 | |||
440 | static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg, | ||
441 | unsigned val) | ||
442 | { | ||
443 | isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); | ||
444 | isp116x_write_data16(isp116x, (u16) (val & 0xffff)); | ||
445 | } | ||
446 | |||
447 | static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg, | ||
448 | unsigned val) | ||
449 | { | ||
450 | isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); | ||
451 | isp116x_write_data32(isp116x, (u32) val); | ||
452 | } | ||
453 | |||
454 | #define isp116x_show_reg(d,r) { \ | ||
455 | if ((r) < 0x20) { \ | ||
456 | DBG("%-12s[%02x]: %08x\n", #r, \ | ||
457 | r, isp116x_read_reg32(d, r)); \ | ||
458 | } else { \ | ||
459 | DBG("%-12s[%02x]: %04x\n", #r, \ | ||
460 | r, isp116x_read_reg16(d, r)); \ | ||
461 | } \ | ||
462 | } | ||
463 | |||
464 | static inline void isp116x_show_regs(struct isp116x *isp116x) | ||
465 | { | ||
466 | isp116x_show_reg(isp116x, HCREVISION); | ||
467 | isp116x_show_reg(isp116x, HCCONTROL); | ||
468 | isp116x_show_reg(isp116x, HCCMDSTAT); | ||
469 | isp116x_show_reg(isp116x, HCINTSTAT); | ||
470 | isp116x_show_reg(isp116x, HCINTENB); | ||
471 | isp116x_show_reg(isp116x, HCFMINTVL); | ||
472 | isp116x_show_reg(isp116x, HCFMREM); | ||
473 | isp116x_show_reg(isp116x, HCFMNUM); | ||
474 | isp116x_show_reg(isp116x, HCLSTHRESH); | ||
475 | isp116x_show_reg(isp116x, HCRHDESCA); | ||
476 | isp116x_show_reg(isp116x, HCRHDESCB); | ||
477 | isp116x_show_reg(isp116x, HCRHSTATUS); | ||
478 | isp116x_show_reg(isp116x, HCRHPORT1); | ||
479 | isp116x_show_reg(isp116x, HCRHPORT2); | ||
480 | isp116x_show_reg(isp116x, HCHWCFG); | ||
481 | isp116x_show_reg(isp116x, HCDMACFG); | ||
482 | isp116x_show_reg(isp116x, HCXFERCTR); | ||
483 | isp116x_show_reg(isp116x, HCuPINT); | ||
484 | isp116x_show_reg(isp116x, HCuPINTENB); | ||
485 | isp116x_show_reg(isp116x, HCCHIPID); | ||
486 | isp116x_show_reg(isp116x, HCSCRATCH); | ||
487 | isp116x_show_reg(isp116x, HCITLBUFLEN); | ||
488 | isp116x_show_reg(isp116x, HCATLBUFLEN); | ||
489 | isp116x_show_reg(isp116x, HCBUFSTAT); | ||
490 | isp116x_show_reg(isp116x, HCRDITL0LEN); | ||
491 | isp116x_show_reg(isp116x, HCRDITL1LEN); | ||
492 | } | ||
493 | |||
494 | #if defined(URB_TRACE) | ||
495 | |||
496 | #define PIPETYPE(pipe) ({ char *__s; \ | ||
497 | if (usb_pipecontrol(pipe)) __s = "ctrl"; \ | ||
498 | else if (usb_pipeint(pipe)) __s = "int"; \ | ||
499 | else if (usb_pipebulk(pipe)) __s = "bulk"; \ | ||
500 | else __s = "iso"; \ | ||
501 | __s;}) | ||
502 | #define PIPEDIR(pipe) ({ usb_pipein(pipe) ? "in" : "out"; }) | ||
503 | #define URB_NOTSHORT(urb) ({ (urb)->transfer_flags & URB_SHORT_NOT_OK ? \ | ||
504 | "short_not_ok" : ""; }) | ||
505 | |||
506 | /* print debug info about the URB */ | ||
507 | static void urb_dbg(struct urb *urb, char *msg) | ||
508 | { | ||
509 | unsigned int pipe; | ||
510 | |||
511 | if (!urb) { | ||
512 | DBG("%s: zero urb\n", msg); | ||
513 | return; | ||
514 | } | ||
515 | pipe = urb->pipe; | ||
516 | DBG("%s: FA %d ep%d%s %s: len %d/%d %s\n", msg, | ||
517 | usb_pipedevice(pipe), usb_pipeendpoint(pipe), | ||
518 | PIPEDIR(pipe), PIPETYPE(pipe), | ||
519 | urb->transfer_buffer_length, urb->actual_length, URB_NOTSHORT(urb)); | ||
520 | } | ||
521 | |||
522 | #else | ||
523 | |||
524 | #define urb_dbg(urb,msg) do{}while(0) | ||
525 | |||
526 | #endif /* ! defined(URB_TRACE) */ | ||
527 | |||
528 | #if defined(PTD_TRACE) | ||
529 | |||
530 | #define PTD_DIR_STR(ptd) ({char __c; \ | ||
531 | switch(PTD_GET_DIR(ptd)){ \ | ||
532 | case 0: __c = 's'; break; \ | ||
533 | case 1: __c = 'o'; break; \ | ||
534 | default: __c = 'i'; break; \ | ||
535 | }; __c;}) | ||
536 | |||
537 | /* | ||
538 | Dump PTD info. The code documents the format | ||
539 | perfectly, right :) | ||
540 | */ | ||
541 | static inline void dump_ptd(struct ptd *ptd) | ||
542 | { | ||
543 | printk("td: %x %d%c%d %d,%d,%d %x %x%x%x\n", | ||
544 | PTD_GET_CC(ptd), PTD_GET_FA(ptd), | ||
545 | PTD_DIR_STR(ptd), PTD_GET_EP(ptd), | ||
546 | PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), | ||
547 | PTD_GET_TOGGLE(ptd), PTD_GET_ACTIVE(ptd), | ||
548 | PTD_GET_SPD(ptd), PTD_GET_LAST(ptd)); | ||
549 | } | ||
550 | |||
551 | static inline void dump_ptd_out_data(struct ptd *ptd, u8 * buf) | ||
552 | { | ||
553 | int k; | ||
554 | |||
555 | if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) { | ||
556 | printk("-> "); | ||
557 | for (k = 0; k < PTD_GET_LEN(ptd); ++k) | ||
558 | printk("%02x ", ((u8 *) buf)[k]); | ||
559 | printk("\n"); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | static inline void dump_ptd_in_data(struct ptd *ptd, u8 * buf) | ||
564 | { | ||
565 | int k; | ||
566 | |||
567 | if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) { | ||
568 | printk("<- "); | ||
569 | for (k = 0; k < PTD_GET_COUNT(ptd); ++k) | ||
570 | printk("%02x ", ((u8 *) buf)[k]); | ||
571 | printk("\n"); | ||
572 | } | ||
573 | if (PTD_GET_LAST(ptd)) | ||
574 | printk("-\n"); | ||
575 | } | ||
576 | |||
577 | #else | ||
578 | |||
579 | #define dump_ptd(ptd) do{}while(0) | ||
580 | #define dump_ptd_in_data(ptd,buf) do{}while(0) | ||
581 | #define dump_ptd_out_data(ptd,buf) do{}while(0) | ||
582 | |||
583 | #endif /* ! defined(PTD_TRACE) */ | ||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 1e27f10c1592..13cd2177b557 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -95,12 +95,11 @@ | |||
95 | #include <linux/init.h> | 95 | #include <linux/init.h> |
96 | #include <linux/timer.h> | 96 | #include <linux/timer.h> |
97 | #include <linux/list.h> | 97 | #include <linux/list.h> |
98 | #include <linux/interrupt.h> /* for in_interrupt () */ | ||
99 | #include <linux/usb.h> | 98 | #include <linux/usb.h> |
100 | #include <linux/usb_otg.h> | 99 | #include <linux/usb_otg.h> |
101 | #include "../core/hcd.h" | ||
102 | #include <linux/dma-mapping.h> | 100 | #include <linux/dma-mapping.h> |
103 | #include <linux/dmapool.h> /* needed by ohci-mem.c when no PCI */ | 101 | #include <linux/dmapool.h> |
102 | #include <linux/reboot.h> | ||
104 | 103 | ||
105 | #include <asm/io.h> | 104 | #include <asm/io.h> |
106 | #include <asm/irq.h> | 105 | #include <asm/irq.h> |
@@ -108,8 +107,9 @@ | |||
108 | #include <asm/unaligned.h> | 107 | #include <asm/unaligned.h> |
109 | #include <asm/byteorder.h> | 108 | #include <asm/byteorder.h> |
110 | 109 | ||
110 | #include "../core/hcd.h" | ||
111 | 111 | ||
112 | #define DRIVER_VERSION "2004 Nov 08" | 112 | #define DRIVER_VERSION "2005 April 22" |
113 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" | 113 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" |
114 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" | 114 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" |
115 | 115 | ||
@@ -141,6 +141,7 @@ static const char hcd_name [] = "ohci_hcd"; | |||
141 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); | 141 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); |
142 | static int ohci_init (struct ohci_hcd *ohci); | 142 | static int ohci_init (struct ohci_hcd *ohci); |
143 | static void ohci_stop (struct usb_hcd *hcd); | 143 | static void ohci_stop (struct usb_hcd *hcd); |
144 | static int ohci_reboot (struct notifier_block *, unsigned long , void *); | ||
144 | 145 | ||
145 | #include "ohci-hub.c" | 146 | #include "ohci-hub.c" |
146 | #include "ohci-dbg.c" | 147 | #include "ohci-dbg.c" |
@@ -420,6 +421,23 @@ static void ohci_usb_reset (struct ohci_hcd *ohci) | |||
420 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 421 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
421 | } | 422 | } |
422 | 423 | ||
424 | /* reboot notifier forcibly disables IRQs and DMA, helping kexec and | ||
425 | * other cases where the next software may expect clean state from the | ||
426 | * "firmware". this is bus-neutral, unlike shutdown() methods. | ||
427 | */ | ||
428 | static int | ||
429 | ohci_reboot (struct notifier_block *block, unsigned long code, void *null) | ||
430 | { | ||
431 | struct ohci_hcd *ohci; | ||
432 | |||
433 | ohci = container_of (block, struct ohci_hcd, reboot_notifier); | ||
434 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | ||
435 | ohci_usb_reset (ohci); | ||
436 | /* flush the writes */ | ||
437 | (void) ohci_readl (ohci, &ohci->regs->control); | ||
438 | return 0; | ||
439 | } | ||
440 | |||
423 | /*-------------------------------------------------------------------------* | 441 | /*-------------------------------------------------------------------------* |
424 | * HC functions | 442 | * HC functions |
425 | *-------------------------------------------------------------------------*/ | 443 | *-------------------------------------------------------------------------*/ |
@@ -487,13 +505,10 @@ static int ohci_init (struct ohci_hcd *ohci) | |||
487 | /* Start an OHCI controller, set the BUS operational | 505 | /* Start an OHCI controller, set the BUS operational |
488 | * resets USB and controller | 506 | * resets USB and controller |
489 | * enable interrupts | 507 | * enable interrupts |
490 | * connect the virtual root hub | ||
491 | */ | 508 | */ |
492 | static int ohci_run (struct ohci_hcd *ohci) | 509 | static int ohci_run (struct ohci_hcd *ohci) |
493 | { | 510 | { |
494 | u32 mask, temp; | 511 | u32 mask, temp; |
495 | struct usb_device *udev; | ||
496 | struct usb_bus *bus; | ||
497 | int first = ohci->fminterval == 0; | 512 | int first = ohci->fminterval == 0; |
498 | 513 | ||
499 | disable (ohci); | 514 | disable (ohci); |
@@ -654,37 +669,13 @@ retry: | |||
654 | 669 | ||
655 | // POTPGT delay is bits 24-31, in 2 ms units. | 670 | // POTPGT delay is bits 24-31, in 2 ms units. |
656 | mdelay ((temp >> 23) & 0x1fe); | 671 | mdelay ((temp >> 23) & 0x1fe); |
657 | bus = &ohci_to_hcd(ohci)->self; | ||
658 | ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; | 672 | ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; |
659 | 673 | ||
660 | ohci_dump (ohci, 1); | 674 | ohci_dump (ohci, 1); |
661 | 675 | ||
662 | udev = bus->root_hub; | 676 | if (ohci_to_hcd(ohci)->self.root_hub == NULL) |
663 | if (udev) { | 677 | create_debug_files (ohci); |
664 | return 0; | ||
665 | } | ||
666 | |||
667 | /* connect the virtual root hub */ | ||
668 | udev = usb_alloc_dev (NULL, bus, 0); | ||
669 | if (!udev) { | ||
670 | disable (ohci); | ||
671 | ohci->hc_control &= ~OHCI_CTRL_HCFS; | ||
672 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | ||
673 | return -ENOMEM; | ||
674 | } | ||
675 | |||
676 | udev->speed = USB_SPEED_FULL; | ||
677 | if (usb_hcd_register_root_hub (udev, ohci_to_hcd(ohci)) != 0) { | ||
678 | usb_put_dev (udev); | ||
679 | disable (ohci); | ||
680 | ohci->hc_control &= ~OHCI_CTRL_HCFS; | ||
681 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | ||
682 | return -ENODEV; | ||
683 | } | ||
684 | if (ohci->power_budget) | ||
685 | hub_set_power_budget(udev, ohci->power_budget); | ||
686 | 678 | ||
687 | create_debug_files (ohci); | ||
688 | return 0; | 679 | return 0; |
689 | } | 680 | } |
690 | 681 | ||
@@ -781,6 +772,7 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
781 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | 772 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); |
782 | 773 | ||
783 | remove_debug_files (ohci); | 774 | remove_debug_files (ohci); |
775 | unregister_reboot_notifier (&ohci->reboot_notifier); | ||
784 | ohci_mem_cleanup (ohci); | 776 | ohci_mem_cleanup (ohci); |
785 | if (ohci->hcca) { | 777 | if (ohci->hcca) { |
786 | dma_free_coherent (hcd->self.controller, | 778 | dma_free_coherent (hcd->self.controller, |
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index e55682b4919d..23735a36af00 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c | |||
@@ -29,6 +29,7 @@ static void ohci_hcd_init (struct ohci_hcd *ohci) | |||
29 | spin_lock_init (&ohci->lock); | 29 | spin_lock_init (&ohci->lock); |
30 | INIT_LIST_HEAD (&ohci->pending); | 30 | INIT_LIST_HEAD (&ohci->pending); |
31 | INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci)); | 31 | INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci)); |
32 | ohci->reboot_notifier.notifier_call = ohci_reboot; | ||
32 | } | 33 | } |
33 | 34 | ||
34 | /*-------------------------------------------------------------------------*/ | 35 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 8aab5907afe9..b62d69937694 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c | |||
@@ -181,7 +181,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | |||
181 | if (config->otg) { | 181 | if (config->otg) { |
182 | ohci_to_hcd(ohci)->self.otg_port = config->otg; | 182 | ohci_to_hcd(ohci)->self.otg_port = config->otg; |
183 | /* default/minimum OTG power budget: 8 mA */ | 183 | /* default/minimum OTG power budget: 8 mA */ |
184 | ohci->power_budget = 8; | 184 | ohci_to_hcd(ohci)->power_budget = 8; |
185 | } | 185 | } |
186 | 186 | ||
187 | /* boards can use OTG transceivers in non-OTG modes */ | 187 | /* boards can use OTG transceivers in non-OTG modes */ |
@@ -230,7 +230,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | |||
230 | 230 | ||
231 | /* TPS2045 switch for internal transceiver (port 1) */ | 231 | /* TPS2045 switch for internal transceiver (port 1) */ |
232 | if (machine_is_omap_osk()) { | 232 | if (machine_is_omap_osk()) { |
233 | ohci->power_budget = 250; | 233 | ohci_to_hcd(ohci)->power_budget = 250; |
234 | 234 | ||
235 | rh &= ~RH_A_NOCP; | 235 | rh &= ~RH_A_NOCP; |
236 | 236 | ||
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 57fd07d00549..eede6be098d2 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -14,14 +14,11 @@ | |||
14 | * This file is licenced under the GPL. | 14 | * This file is licenced under the GPL. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifdef CONFIG_PMAC_PBOOK | 17 | #ifdef CONFIG_PPC_PMAC |
18 | #include <asm/machdep.h> | 18 | #include <asm/machdep.h> |
19 | #include <asm/pmac_feature.h> | 19 | #include <asm/pmac_feature.h> |
20 | #include <asm/pci-bridge.h> | 20 | #include <asm/pci-bridge.h> |
21 | #include <asm/prom.h> | 21 | #include <asm/prom.h> |
22 | #ifndef CONFIG_PM | ||
23 | # define CONFIG_PM | ||
24 | #endif | ||
25 | #endif | 22 | #endif |
26 | 23 | ||
27 | #ifndef CONFIG_PCI | 24 | #ifndef CONFIG_PCI |
@@ -132,7 +129,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | |||
132 | /* let things settle down a bit */ | 129 | /* let things settle down a bit */ |
133 | msleep (100); | 130 | msleep (100); |
134 | 131 | ||
135 | #ifdef CONFIG_PMAC_PBOOK | 132 | #ifdef CONFIG_PPC_PMAC |
136 | if (_machine == _MACH_Pmac) { | 133 | if (_machine == _MACH_Pmac) { |
137 | struct device_node *of_node; | 134 | struct device_node *of_node; |
138 | 135 | ||
@@ -141,7 +138,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | |||
141 | if (of_node) | 138 | if (of_node) |
142 | pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); | 139 | pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); |
143 | } | 140 | } |
144 | #endif /* CONFIG_PMAC_PBOOK */ | 141 | #endif /* CONFIG_PPC_PMAC */ |
145 | return 0; | 142 | return 0; |
146 | } | 143 | } |
147 | 144 | ||
@@ -151,7 +148,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd) | |||
151 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 148 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
152 | int retval = 0; | 149 | int retval = 0; |
153 | 150 | ||
154 | #ifdef CONFIG_PMAC_PBOOK | 151 | #ifdef CONFIG_PPC_PMAC |
155 | if (_machine == _MACH_Pmac) { | 152 | if (_machine == _MACH_Pmac) { |
156 | struct device_node *of_node; | 153 | struct device_node *of_node; |
157 | 154 | ||
@@ -160,7 +157,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd) | |||
160 | if (of_node) | 157 | if (of_node) |
161 | pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); | 158 | pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); |
162 | } | 159 | } |
163 | #endif /* CONFIG_PMAC_PBOOK */ | 160 | #endif /* CONFIG_PPC_PMAC */ |
164 | 161 | ||
165 | /* resume root hub */ | 162 | /* resume root hub */ |
166 | if (time_before (jiffies, ohci->next_statechange)) | 163 | if (time_before (jiffies, ohci->next_statechange)) |
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 22e1ac138ac0..71cdd2262860 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -371,7 +371,6 @@ struct ohci_hcd { | |||
371 | * other external transceivers should be software-transparent | 371 | * other external transceivers should be software-transparent |
372 | */ | 372 | */ |
373 | struct otg_transceiver *transceiver; | 373 | struct otg_transceiver *transceiver; |
374 | unsigned power_budget; | ||
375 | 374 | ||
376 | /* | 375 | /* |
377 | * memory management for queue data structures | 376 | * memory management for queue data structures |
@@ -390,6 +389,7 @@ struct ohci_hcd { | |||
390 | u32 fminterval; /* saved register */ | 389 | u32 fminterval; /* saved register */ |
391 | 390 | ||
392 | struct work_struct rh_resume; | 391 | struct work_struct rh_resume; |
392 | struct notifier_block reboot_notifier; | ||
393 | 393 | ||
394 | unsigned long flags; /* for HC bugs */ | 394 | unsigned long flags; /* for HC bugs */ |
395 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ | 395 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 99d43f758ad0..6c3f910bc307 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -1563,29 +1563,15 @@ static int | |||
1563 | sl811h_start(struct usb_hcd *hcd) | 1563 | sl811h_start(struct usb_hcd *hcd) |
1564 | { | 1564 | { |
1565 | struct sl811 *sl811 = hcd_to_sl811(hcd); | 1565 | struct sl811 *sl811 = hcd_to_sl811(hcd); |
1566 | struct usb_device *udev; | ||
1567 | 1566 | ||
1568 | /* chip has been reset, VBUS power is off */ | 1567 | /* chip has been reset, VBUS power is off */ |
1569 | |||
1570 | udev = usb_alloc_dev(NULL, &hcd->self, 0); | ||
1571 | if (!udev) | ||
1572 | return -ENOMEM; | ||
1573 | |||
1574 | udev->speed = USB_SPEED_FULL; | ||
1575 | hcd->state = HC_STATE_RUNNING; | 1568 | hcd->state = HC_STATE_RUNNING; |
1576 | 1569 | ||
1577 | if (sl811->board) | 1570 | if (sl811->board) { |
1578 | hcd->can_wakeup = sl811->board->can_wakeup; | 1571 | hcd->can_wakeup = sl811->board->can_wakeup; |
1579 | 1572 | hcd->power_budget = sl811->board->power * 2; | |
1580 | if (usb_hcd_register_root_hub(udev, hcd) != 0) { | ||
1581 | usb_put_dev(udev); | ||
1582 | sl811h_stop(hcd); | ||
1583 | return -ENODEV; | ||
1584 | } | 1573 | } |
1585 | 1574 | ||
1586 | if (sl811->board && sl811->board->power) | ||
1587 | hub_set_power_budget(udev, sl811->board->power * 2); | ||
1588 | |||
1589 | /* enable power and interupts */ | 1575 | /* enable power and interupts */ |
1590 | port_power(sl811, 1); | 1576 | port_power(sl811, 1); |
1591 | 1577 | ||
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 24c73c5a3435..4538a98b6f9d 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -237,6 +237,37 @@ static int uhci_show_sc(int port, unsigned short status, char *buf, int len) | |||
237 | return out - buf; | 237 | return out - buf; |
238 | } | 238 | } |
239 | 239 | ||
240 | static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len) | ||
241 | { | ||
242 | char *out = buf; | ||
243 | char *rh_state; | ||
244 | |||
245 | /* Try to make sure there's enough memory */ | ||
246 | if (len < 60) | ||
247 | return 0; | ||
248 | |||
249 | switch (uhci->rh_state) { | ||
250 | case UHCI_RH_RESET: | ||
251 | rh_state = "reset"; break; | ||
252 | case UHCI_RH_SUSPENDED: | ||
253 | rh_state = "suspended"; break; | ||
254 | case UHCI_RH_AUTO_STOPPED: | ||
255 | rh_state = "auto-stopped"; break; | ||
256 | case UHCI_RH_RESUMING: | ||
257 | rh_state = "resuming"; break; | ||
258 | case UHCI_RH_SUSPENDING: | ||
259 | rh_state = "suspending"; break; | ||
260 | case UHCI_RH_RUNNING: | ||
261 | rh_state = "running"; break; | ||
262 | case UHCI_RH_RUNNING_NODEVS: | ||
263 | rh_state = "running, no devs"; break; | ||
264 | default: | ||
265 | rh_state = "?"; break; | ||
266 | } | ||
267 | out += sprintf(out, "Root-hub state: %s\n", rh_state); | ||
268 | return out - buf; | ||
269 | } | ||
270 | |||
240 | static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) | 271 | static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) |
241 | { | 272 | { |
242 | char *out = buf; | 273 | char *out = buf; |
@@ -408,6 +439,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
408 | 439 | ||
409 | spin_lock_irqsave(&uhci->lock, flags); | 440 | spin_lock_irqsave(&uhci->lock, flags); |
410 | 441 | ||
442 | out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); | ||
411 | out += sprintf(out, "HC status\n"); | 443 | out += sprintf(out, "HC status\n"); |
412 | out += uhci_show_status(uhci, out, len - (out - buf)); | 444 | out += uhci_show_status(uhci, out, len - (out - buf)); |
413 | 445 | ||
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 49bd83ee0c75..0d5d2545bf07 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -13,18 +13,13 @@ | |||
13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface | 13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface |
14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). | 14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). |
15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) | 15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) |
16 | * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu | 16 | * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu |
17 | * | 17 | * |
18 | * Intel documents this fairly well, and as far as I know there | 18 | * Intel documents this fairly well, and as far as I know there |
19 | * are no royalties or anything like that, but even so there are | 19 | * are no royalties or anything like that, but even so there are |
20 | * people who decided that they want to do the same thing in a | 20 | * people who decided that they want to do the same thing in a |
21 | * completely different way. | 21 | * completely different way. |
22 | * | 22 | * |
23 | * WARNING! The USB documentation is downright evil. Most of it | ||
24 | * is just crap, written by a committee. You're better off ignoring | ||
25 | * most of it, the important stuff is: | ||
26 | * - the low-level protocol (fairly simple but lots of small details) | ||
27 | * - working around the horridness of the rest | ||
28 | */ | 23 | */ |
29 | 24 | ||
30 | #include <linux/config.h> | 25 | #include <linux/config.h> |
@@ -64,7 +59,7 @@ | |||
64 | /* | 59 | /* |
65 | * Version Information | 60 | * Version Information |
66 | */ | 61 | */ |
67 | #define DRIVER_VERSION "v2.2" | 62 | #define DRIVER_VERSION "v2.3" |
68 | #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ | 63 | #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ |
69 | Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ | 64 | Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ |
70 | Alan Stern" | 65 | Alan Stern" |
@@ -89,8 +84,9 @@ static char *errbuf; | |||
89 | 84 | ||
90 | static kmem_cache_t *uhci_up_cachep; /* urb_priv */ | 85 | static kmem_cache_t *uhci_up_cachep; /* urb_priv */ |
91 | 86 | ||
87 | static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); | ||
88 | static void wakeup_rh(struct uhci_hcd *uhci); | ||
92 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | 89 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); |
93 | static void hc_state_transitions(struct uhci_hcd *uhci); | ||
94 | 90 | ||
95 | /* If a transfer is still active after this much time, turn off FSBR */ | 91 | /* If a transfer is still active after this much time, turn off FSBR */ |
96 | #define IDLE_TIMEOUT msecs_to_jiffies(50) | 92 | #define IDLE_TIMEOUT msecs_to_jiffies(50) |
@@ -101,308 +97,352 @@ static void hc_state_transitions(struct uhci_hcd *uhci); | |||
101 | /* to make sure it doesn't hog all of the bandwidth */ | 97 | /* to make sure it doesn't hog all of the bandwidth */ |
102 | #define DEPTH_INTERVAL 5 | 98 | #define DEPTH_INTERVAL 5 |
103 | 99 | ||
100 | static inline void restart_timer(struct uhci_hcd *uhci) | ||
101 | { | ||
102 | mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100)); | ||
103 | } | ||
104 | |||
104 | #include "uhci-hub.c" | 105 | #include "uhci-hub.c" |
105 | #include "uhci-debug.c" | 106 | #include "uhci-debug.c" |
106 | #include "uhci-q.c" | 107 | #include "uhci-q.c" |
107 | 108 | ||
108 | static int init_stall_timer(struct usb_hcd *hcd); | 109 | /* |
109 | 110 | * Make sure the controller is completely inactive, unable to | |
110 | static void stall_callback(unsigned long ptr) | 111 | * generate interrupts or do DMA. |
112 | */ | ||
113 | static void reset_hc(struct uhci_hcd *uhci) | ||
111 | { | 114 | { |
112 | struct usb_hcd *hcd = (struct usb_hcd *)ptr; | 115 | int port; |
113 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
114 | struct urb_priv *up; | ||
115 | unsigned long flags; | ||
116 | 116 | ||
117 | spin_lock_irqsave(&uhci->lock, flags); | 117 | /* Turn off PIRQ enable and SMI enable. (This also turns off the |
118 | uhci_scan_schedule(uhci, NULL); | 118 | * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. |
119 | 119 | */ | |
120 | list_for_each_entry(up, &uhci->urb_list, urb_list) { | 120 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, |
121 | struct urb *u = up->urb; | 121 | USBLEGSUP_RWC); |
122 | |||
123 | spin_lock(&u->lock); | ||
124 | |||
125 | /* Check if the FSBR timed out */ | ||
126 | if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) | ||
127 | uhci_fsbr_timeout(uhci, u); | ||
128 | 122 | ||
129 | spin_unlock(&u->lock); | 123 | /* Reset the HC - this will force us to get a |
130 | } | 124 | * new notification of any already connected |
125 | * ports due to the virtual disconnect that it | ||
126 | * implies. | ||
127 | */ | ||
128 | outw(USBCMD_HCRESET, uhci->io_addr + USBCMD); | ||
129 | mb(); | ||
130 | udelay(5); | ||
131 | if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET) | ||
132 | dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n"); | ||
131 | 133 | ||
132 | /* Really disable FSBR */ | 134 | /* Just to be safe, disable interrupt requests and |
133 | if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { | 135 | * make sure the controller is stopped. |
134 | uhci->fsbrtimeout = 0; | 136 | */ |
135 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | 137 | outw(0, uhci->io_addr + USBINTR); |
136 | } | 138 | outw(0, uhci->io_addr + USBCMD); |
137 | 139 | ||
138 | /* Poll for and perform state transitions */ | 140 | /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect |
139 | hc_state_transitions(uhci); | 141 | * bits in the port status and control registers. |
140 | if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED)) | 142 | * We have to clear them by hand. |
141 | uhci_check_ports(uhci); | 143 | */ |
144 | for (port = 0; port < uhci->rh_numports; ++port) | ||
145 | outw(0, uhci->io_addr + USBPORTSC1 + (port * 2)); | ||
142 | 146 | ||
143 | init_stall_timer(hcd); | 147 | uhci->port_c_suspend = uhci->suspended_ports = |
144 | spin_unlock_irqrestore(&uhci->lock, flags); | 148 | uhci->resuming_ports = 0; |
149 | uhci->rh_state = UHCI_RH_RESET; | ||
150 | uhci->is_stopped = UHCI_IS_STOPPED; | ||
151 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; | ||
152 | uhci_to_hcd(uhci)->poll_rh = 0; | ||
145 | } | 153 | } |
146 | 154 | ||
147 | static int init_stall_timer(struct usb_hcd *hcd) | 155 | /* |
156 | * Last rites for a defunct/nonfunctional controller | ||
157 | * or one we don't want to use any more. | ||
158 | */ | ||
159 | static void hc_died(struct uhci_hcd *uhci) | ||
148 | { | 160 | { |
149 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 161 | reset_hc(uhci); |
150 | 162 | uhci->hc_inaccessible = 1; | |
151 | init_timer(&uhci->stall_timer); | 163 | del_timer(&uhci->stall_timer); |
152 | uhci->stall_timer.function = stall_callback; | ||
153 | uhci->stall_timer.data = (unsigned long)hcd; | ||
154 | uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100); | ||
155 | add_timer(&uhci->stall_timer); | ||
156 | |||
157 | return 0; | ||
158 | } | 164 | } |
159 | 165 | ||
160 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | 166 | /* |
167 | * Initialize a controller that was newly discovered or has just been | ||
168 | * resumed. In either case we can't be sure of its previous state. | ||
169 | */ | ||
170 | static void check_and_reset_hc(struct uhci_hcd *uhci) | ||
161 | { | 171 | { |
162 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 172 | u16 legsup; |
163 | unsigned long io_addr = uhci->io_addr; | 173 | unsigned int cmd, intr; |
164 | unsigned short status; | ||
165 | 174 | ||
166 | /* | 175 | /* |
167 | * Read the interrupt status, and write it back to clear the | 176 | * When restarting a suspended controller, we expect all the |
168 | * interrupt cause. Contrary to the UHCI specification, the | 177 | * settings to be the same as we left them: |
169 | * "HC Halted" status bit is persistent: it is RO, not R/WC. | 178 | * |
179 | * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; | ||
180 | * Controller is stopped and configured with EGSM set; | ||
181 | * No interrupts enabled except possibly Resume Detect. | ||
182 | * | ||
183 | * If any of these conditions are violated we do a complete reset. | ||
170 | */ | 184 | */ |
171 | status = inw(io_addr + USBSTS); | 185 | pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup); |
172 | if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */ | 186 | if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) { |
173 | return IRQ_NONE; | 187 | dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n", |
174 | outw(status, io_addr + USBSTS); /* Clear it */ | 188 | __FUNCTION__, legsup); |
175 | 189 | goto reset_needed; | |
176 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { | ||
177 | if (status & USBSTS_HSE) | ||
178 | dev_err(uhci_dev(uhci), "host system error, " | ||
179 | "PCI problems?\n"); | ||
180 | if (status & USBSTS_HCPE) | ||
181 | dev_err(uhci_dev(uhci), "host controller process " | ||
182 | "error, something bad happened!\n"); | ||
183 | if ((status & USBSTS_HCH) && uhci->state > 0) { | ||
184 | dev_err(uhci_dev(uhci), "host controller halted, " | ||
185 | "very bad!\n"); | ||
186 | /* FIXME: Reset the controller, fix the offending TD */ | ||
187 | } | ||
188 | } | 190 | } |
189 | 191 | ||
190 | if (status & USBSTS_RD) | 192 | cmd = inw(uhci->io_addr + USBCMD); |
191 | uhci->resume_detect = 1; | 193 | if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) { |
194 | dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n", | ||
195 | __FUNCTION__, cmd); | ||
196 | goto reset_needed; | ||
197 | } | ||
192 | 198 | ||
193 | spin_lock(&uhci->lock); | 199 | intr = inw(uhci->io_addr + USBINTR); |
194 | uhci_scan_schedule(uhci, regs); | 200 | if (intr & (~USBINTR_RESUME)) { |
195 | spin_unlock(&uhci->lock); | 201 | dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n", |
202 | __FUNCTION__, intr); | ||
203 | goto reset_needed; | ||
204 | } | ||
205 | return; | ||
196 | 206 | ||
197 | return IRQ_HANDLED; | 207 | reset_needed: |
208 | dev_dbg(uhci_dev(uhci), "Performing full reset\n"); | ||
209 | reset_hc(uhci); | ||
198 | } | 210 | } |
199 | 211 | ||
200 | static void reset_hc(struct uhci_hcd *uhci) | 212 | /* |
213 | * Store the basic register settings needed by the controller. | ||
214 | */ | ||
215 | static void configure_hc(struct uhci_hcd *uhci) | ||
201 | { | 216 | { |
202 | unsigned long io_addr = uhci->io_addr; | 217 | /* Set the frame length to the default: 1 ms exactly */ |
218 | outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); | ||
203 | 219 | ||
204 | /* Turn off PIRQ, SMI, and all interrupts. This also turns off | 220 | /* Store the frame list base address */ |
205 | * the BIOS's USB Legacy Support. | 221 | outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); |
206 | */ | ||
207 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | ||
208 | outw(0, uhci->io_addr + USBINTR); | ||
209 | 222 | ||
210 | /* Global reset for 50ms */ | 223 | /* Set the current frame number */ |
211 | uhci->state = UHCI_RESET; | 224 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); |
212 | outw(USBCMD_GRESET, io_addr + USBCMD); | ||
213 | msleep(50); | ||
214 | outw(0, io_addr + USBCMD); | ||
215 | 225 | ||
216 | /* Another 10ms delay */ | 226 | /* Mark controller as running before we enable interrupts */ |
217 | msleep(10); | 227 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; |
218 | uhci->resume_detect = 0; | 228 | mb(); |
219 | uhci->is_stopped = UHCI_IS_STOPPED; | 229 | |
230 | /* Enable PIRQ */ | ||
231 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | ||
232 | USBLEGSUP_DEFAULT); | ||
220 | } | 233 | } |
221 | 234 | ||
222 | static void suspend_hc(struct uhci_hcd *uhci) | 235 | |
236 | static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci) | ||
223 | { | 237 | { |
224 | unsigned long io_addr = uhci->io_addr; | 238 | int port; |
225 | 239 | ||
226 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); | 240 | switch (to_pci_dev(uhci_dev(uhci))->vendor) { |
227 | uhci->state = UHCI_SUSPENDED; | 241 | default: |
228 | uhci->resume_detect = 0; | 242 | break; |
229 | outw(USBCMD_EGSM, io_addr + USBCMD); | ||
230 | 243 | ||
231 | /* FIXME: Wait for the controller to actually stop */ | 244 | case PCI_VENDOR_ID_GENESYS: |
232 | uhci_get_current_frame_number(uhci); | 245 | /* Genesys Logic's GL880S controllers don't generate |
233 | uhci->is_stopped = UHCI_IS_STOPPED; | 246 | * resume-detect interrupts. |
247 | */ | ||
248 | return 1; | ||
234 | 249 | ||
235 | uhci_scan_schedule(uhci, NULL); | 250 | case PCI_VENDOR_ID_INTEL: |
251 | /* Some of Intel's USB controllers have a bug that causes | ||
252 | * resume-detect interrupts if any port has an over-current | ||
253 | * condition. To make matters worse, some motherboards | ||
254 | * hardwire unused USB ports' over-current inputs active! | ||
255 | * To prevent problems, we will not enable resume-detect | ||
256 | * interrupts if any ports are OC. | ||
257 | */ | ||
258 | for (port = 0; port < uhci->rh_numports; ++port) { | ||
259 | if (inw(uhci->io_addr + USBPORTSC1 + port * 2) & | ||
260 | USBPORTSC_OC) | ||
261 | return 1; | ||
262 | } | ||
263 | break; | ||
264 | } | ||
265 | return 0; | ||
236 | } | 266 | } |
237 | 267 | ||
238 | static void wakeup_hc(struct uhci_hcd *uhci) | 268 | static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state) |
269 | __releases(uhci->lock) | ||
270 | __acquires(uhci->lock) | ||
239 | { | 271 | { |
240 | unsigned long io_addr = uhci->io_addr; | 272 | int auto_stop; |
273 | int int_enable; | ||
241 | 274 | ||
242 | switch (uhci->state) { | 275 | auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); |
243 | case UHCI_SUSPENDED: /* Start the resume */ | 276 | dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, |
244 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); | 277 | (auto_stop ? " (auto-stop)" : "")); |
245 | |||
246 | /* Global resume for >= 20ms */ | ||
247 | outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD); | ||
248 | uhci->state = UHCI_RESUMING_1; | ||
249 | uhci->state_end = jiffies + msecs_to_jiffies(20); | ||
250 | uhci->is_stopped = 0; | ||
251 | break; | ||
252 | 278 | ||
253 | case UHCI_RESUMING_1: /* End global resume */ | 279 | /* If we get a suspend request when we're already auto-stopped |
254 | uhci->state = UHCI_RESUMING_2; | 280 | * then there's nothing to do. |
255 | outw(0, io_addr + USBCMD); | 281 | */ |
256 | /* Falls through */ | 282 | if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) { |
257 | 283 | uhci->rh_state = new_state; | |
258 | case UHCI_RESUMING_2: /* Wait for EOP to be sent */ | 284 | return; |
259 | if (inw(io_addr + USBCMD) & USBCMD_FGR) | 285 | } |
260 | break; | ||
261 | |||
262 | /* Run for at least 1 second, and | ||
263 | * mark it configured with a 64-byte max packet */ | ||
264 | uhci->state = UHCI_RUNNING_GRACE; | ||
265 | uhci->state_end = jiffies + HZ; | ||
266 | outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, | ||
267 | io_addr + USBCMD); | ||
268 | break; | ||
269 | 286 | ||
270 | case UHCI_RUNNING_GRACE: /* Now allowed to suspend */ | 287 | /* Enable resume-detect interrupts if they work. |
271 | uhci->state = UHCI_RUNNING; | 288 | * Then enter Global Suspend mode, still configured. |
272 | break; | 289 | */ |
290 | int_enable = (resume_detect_interrupts_are_broken(uhci) ? | ||
291 | 0 : USBINTR_RESUME); | ||
292 | outw(int_enable, uhci->io_addr + USBINTR); | ||
293 | outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); | ||
294 | mb(); | ||
295 | udelay(5); | ||
273 | 296 | ||
274 | default: | 297 | /* If we're auto-stopping then no devices have been attached |
275 | break; | 298 | * for a while, so there shouldn't be any active URBs and the |
299 | * controller should stop after a few microseconds. Otherwise | ||
300 | * we will give the controller one frame to stop. | ||
301 | */ | ||
302 | if (!auto_stop && !(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) { | ||
303 | uhci->rh_state = UHCI_RH_SUSPENDING; | ||
304 | spin_unlock_irq(&uhci->lock); | ||
305 | msleep(1); | ||
306 | spin_lock_irq(&uhci->lock); | ||
307 | if (uhci->hc_inaccessible) /* Died */ | ||
308 | return; | ||
276 | } | 309 | } |
277 | } | 310 | if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) |
311 | dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); | ||
278 | 312 | ||
279 | static int ports_active(struct uhci_hcd *uhci) | 313 | uhci_get_current_frame_number(uhci); |
280 | { | 314 | smp_wmb(); |
281 | unsigned long io_addr = uhci->io_addr; | ||
282 | int connection = 0; | ||
283 | int i; | ||
284 | 315 | ||
285 | for (i = 0; i < uhci->rh_numports; i++) | 316 | uhci->rh_state = new_state; |
286 | connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS); | 317 | uhci->is_stopped = UHCI_IS_STOPPED; |
318 | del_timer(&uhci->stall_timer); | ||
319 | uhci_to_hcd(uhci)->poll_rh = !int_enable; | ||
287 | 320 | ||
288 | return connection; | 321 | uhci_scan_schedule(uhci, NULL); |
289 | } | 322 | } |
290 | 323 | ||
291 | static int suspend_allowed(struct uhci_hcd *uhci) | 324 | static void start_rh(struct uhci_hcd *uhci) |
292 | { | 325 | { |
293 | unsigned long io_addr = uhci->io_addr; | 326 | uhci->is_stopped = 0; |
294 | int i; | 327 | smp_wmb(); |
295 | |||
296 | if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL) | ||
297 | return 1; | ||
298 | 328 | ||
299 | /* Some of Intel's USB controllers have a bug that causes false | 329 | /* Mark it configured and running with a 64-byte max packet. |
300 | * resume indications if any port has an over current condition. | 330 | * All interrupts are enabled, even though RESUME won't do anything. |
301 | * To prevent problems, we will not allow a global suspend if | ||
302 | * any ports are OC. | ||
303 | * | ||
304 | * Some motherboards using Intel's chipsets (but not using all | ||
305 | * the USB ports) appear to hardwire the over current inputs active | ||
306 | * to disable the USB ports. | ||
307 | */ | 331 | */ |
308 | 332 | outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD); | |
309 | /* check for over current condition on any port */ | 333 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, |
310 | for (i = 0; i < uhci->rh_numports; i++) { | 334 | uhci->io_addr + USBINTR); |
311 | if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC) | 335 | mb(); |
312 | return 0; | 336 | uhci->rh_state = UHCI_RH_RUNNING; |
313 | } | 337 | uhci_to_hcd(uhci)->poll_rh = 1; |
314 | 338 | restart_timer(uhci); | |
315 | return 1; | ||
316 | } | 339 | } |
317 | 340 | ||
318 | static void hc_state_transitions(struct uhci_hcd *uhci) | 341 | static void wakeup_rh(struct uhci_hcd *uhci) |
342 | __releases(uhci->lock) | ||
343 | __acquires(uhci->lock) | ||
319 | { | 344 | { |
320 | switch (uhci->state) { | 345 | dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, |
321 | case UHCI_RUNNING: | 346 | uhci->rh_state == UHCI_RH_AUTO_STOPPED ? |
347 | " (auto-start)" : ""); | ||
322 | 348 | ||
323 | /* global suspend if nothing connected for 1 second */ | 349 | /* If we are auto-stopped then no devices are attached so there's |
324 | if (!ports_active(uhci) && suspend_allowed(uhci)) { | 350 | * no need for wakeup signals. Otherwise we send Global Resume |
325 | uhci->state = UHCI_SUSPENDING_GRACE; | 351 | * for 20 ms. |
326 | uhci->state_end = jiffies + HZ; | 352 | */ |
327 | } | 353 | if (uhci->rh_state == UHCI_RH_SUSPENDED) { |
328 | break; | 354 | uhci->rh_state = UHCI_RH_RESUMING; |
329 | 355 | outw(USBCMD_FGR | USBCMD_EGSM | USBCMD_CF, | |
330 | case UHCI_SUSPENDING_GRACE: | 356 | uhci->io_addr + USBCMD); |
331 | if (ports_active(uhci)) | 357 | spin_unlock_irq(&uhci->lock); |
332 | uhci->state = UHCI_RUNNING; | 358 | msleep(20); |
333 | else if (time_after_eq(jiffies, uhci->state_end)) | 359 | spin_lock_irq(&uhci->lock); |
334 | suspend_hc(uhci); | 360 | if (uhci->hc_inaccessible) /* Died */ |
335 | break; | 361 | return; |
336 | 362 | ||
337 | case UHCI_SUSPENDED: | 363 | /* End Global Resume and wait for EOP to be sent */ |
338 | 364 | outw(USBCMD_CF, uhci->io_addr + USBCMD); | |
339 | /* wakeup if requested by a device */ | 365 | mb(); |
340 | if (uhci->resume_detect) | 366 | udelay(4); |
341 | wakeup_hc(uhci); | 367 | if (inw(uhci->io_addr + USBCMD) & USBCMD_FGR) |
342 | break; | 368 | dev_warn(uhci_dev(uhci), "FGR not stopped yet!\n"); |
369 | } | ||
343 | 370 | ||
344 | case UHCI_RESUMING_1: | 371 | start_rh(uhci); |
345 | case UHCI_RESUMING_2: | ||
346 | case UHCI_RUNNING_GRACE: | ||
347 | if (time_after_eq(jiffies, uhci->state_end)) | ||
348 | wakeup_hc(uhci); | ||
349 | break; | ||
350 | 372 | ||
351 | default: | 373 | /* Restart root hub polling */ |
352 | break; | 374 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); |
353 | } | ||
354 | } | 375 | } |
355 | 376 | ||
356 | /* | 377 | static void stall_callback(unsigned long _uhci) |
357 | * Store the current frame number in uhci->frame_number if the controller | ||
358 | * is runnning | ||
359 | */ | ||
360 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) | ||
361 | { | 378 | { |
379 | struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; | ||
380 | unsigned long flags; | ||
381 | |||
382 | spin_lock_irqsave(&uhci->lock, flags); | ||
383 | uhci_scan_schedule(uhci, NULL); | ||
384 | check_fsbr(uhci); | ||
385 | |||
362 | if (!uhci->is_stopped) | 386 | if (!uhci->is_stopped) |
363 | uhci->frame_number = inw(uhci->io_addr + USBFRNUM); | 387 | restart_timer(uhci); |
388 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
364 | } | 389 | } |
365 | 390 | ||
366 | static int start_hc(struct uhci_hcd *uhci) | 391 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) |
367 | { | 392 | { |
368 | unsigned long io_addr = uhci->io_addr; | 393 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
369 | int timeout = 10; | 394 | unsigned short status; |
395 | unsigned long flags; | ||
370 | 396 | ||
371 | /* | 397 | /* |
372 | * Reset the HC - this will force us to get a | 398 | * Read the interrupt status, and write it back to clear the |
373 | * new notification of any already connected | 399 | * interrupt cause. Contrary to the UHCI specification, the |
374 | * ports due to the virtual disconnect that it | 400 | * "HC Halted" status bit is persistent: it is RO, not R/WC. |
375 | * implies. | ||
376 | */ | 401 | */ |
377 | outw(USBCMD_HCRESET, io_addr + USBCMD); | 402 | status = inw(uhci->io_addr + USBSTS); |
378 | while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { | 403 | if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */ |
379 | if (--timeout < 0) { | 404 | return IRQ_NONE; |
380 | dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n"); | 405 | outw(status, uhci->io_addr + USBSTS); /* Clear it */ |
381 | return -ETIMEDOUT; | 406 | |
407 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { | ||
408 | if (status & USBSTS_HSE) | ||
409 | dev_err(uhci_dev(uhci), "host system error, " | ||
410 | "PCI problems?\n"); | ||
411 | if (status & USBSTS_HCPE) | ||
412 | dev_err(uhci_dev(uhci), "host controller process " | ||
413 | "error, something bad happened!\n"); | ||
414 | if (status & USBSTS_HCH) { | ||
415 | spin_lock_irqsave(&uhci->lock, flags); | ||
416 | if (uhci->rh_state >= UHCI_RH_RUNNING) { | ||
417 | dev_err(uhci_dev(uhci), | ||
418 | "host controller halted, " | ||
419 | "very bad!\n"); | ||
420 | hc_died(uhci); | ||
421 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
422 | return IRQ_HANDLED; | ||
423 | } | ||
424 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
382 | } | 425 | } |
383 | msleep(1); | ||
384 | } | 426 | } |
385 | 427 | ||
386 | /* Mark controller as running before we enable interrupts */ | 428 | if (status & USBSTS_RD) |
387 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | 429 | usb_hcd_poll_rh_status(hcd); |
388 | |||
389 | /* Turn on PIRQ and all interrupts */ | ||
390 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | ||
391 | USBLEGSUP_DEFAULT); | ||
392 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, | ||
393 | io_addr + USBINTR); | ||
394 | 430 | ||
395 | /* Start at frame 0 */ | 431 | spin_lock_irqsave(&uhci->lock, flags); |
396 | outw(0, io_addr + USBFRNUM); | 432 | uhci_scan_schedule(uhci, regs); |
397 | outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); | 433 | spin_unlock_irqrestore(&uhci->lock, flags); |
398 | 434 | ||
399 | /* Run and mark it configured with a 64-byte max packet */ | 435 | return IRQ_HANDLED; |
400 | uhci->state = UHCI_RUNNING_GRACE; | 436 | } |
401 | uhci->state_end = jiffies + HZ; | ||
402 | outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); | ||
403 | uhci->is_stopped = 0; | ||
404 | 437 | ||
405 | return 0; | 438 | /* |
439 | * Store the current frame number in uhci->frame_number if the controller | ||
440 | * is runnning | ||
441 | */ | ||
442 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) | ||
443 | { | ||
444 | if (!uhci->is_stopped) | ||
445 | uhci->frame_number = inw(uhci->io_addr + USBFRNUM); | ||
406 | } | 446 | } |
407 | 447 | ||
408 | /* | 448 | /* |
@@ -448,16 +488,58 @@ static void release_uhci(struct uhci_hcd *uhci) | |||
448 | static int uhci_reset(struct usb_hcd *hcd) | 488 | static int uhci_reset(struct usb_hcd *hcd) |
449 | { | 489 | { |
450 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 490 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
491 | unsigned io_size = (unsigned) hcd->rsrc_len; | ||
492 | int port; | ||
451 | 493 | ||
452 | uhci->io_addr = (unsigned long) hcd->rsrc_start; | 494 | uhci->io_addr = (unsigned long) hcd->rsrc_start; |
453 | 495 | ||
454 | /* Kick BIOS off this hardware and reset, so we won't get | 496 | /* The UHCI spec says devices must have 2 ports, and goes on to say |
455 | * interrupts from any previous setup. | 497 | * they may have more but gives no way to determine how many there |
498 | * are. However according to the UHCI spec, Bit 7 of the port | ||
499 | * status and control register is always set to 1. So we try to | ||
500 | * use this to our advantage. Another common failure mode when | ||
501 | * a nonexistent register is addressed is to return all ones, so | ||
502 | * we test for that also. | ||
456 | */ | 503 | */ |
457 | reset_hc(uhci); | 504 | for (port = 0; port < (io_size - USBPORTSC1) / 2; port++) { |
505 | unsigned int portstatus; | ||
506 | |||
507 | portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2)); | ||
508 | if (!(portstatus & 0x0080) || portstatus == 0xffff) | ||
509 | break; | ||
510 | } | ||
511 | if (debug) | ||
512 | dev_info(uhci_dev(uhci), "detected %d ports\n", port); | ||
513 | |||
514 | /* Anything greater than 7 is weird so we'll ignore it. */ | ||
515 | if (port > UHCI_RH_MAXCHILD) { | ||
516 | dev_info(uhci_dev(uhci), "port count misdetected? " | ||
517 | "forcing to 2 ports\n"); | ||
518 | port = 2; | ||
519 | } | ||
520 | uhci->rh_numports = port; | ||
521 | |||
522 | /* Kick BIOS off this hardware and reset if the controller | ||
523 | * isn't already safely quiescent. | ||
524 | */ | ||
525 | check_and_reset_hc(uhci); | ||
458 | return 0; | 526 | return 0; |
459 | } | 527 | } |
460 | 528 | ||
529 | /* Make sure the controller is quiescent and that we're not using it | ||
530 | * any more. This is mainly for the benefit of programs which, like kexec, | ||
531 | * expect the hardware to be idle: not doing DMA or generating IRQs. | ||
532 | * | ||
533 | * This routine may be called in a damaged or failing kernel. Hence we | ||
534 | * do not acquire the spinlock before shutting down the controller. | ||
535 | */ | ||
536 | static void uhci_shutdown(struct pci_dev *pdev) | ||
537 | { | ||
538 | struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev); | ||
539 | |||
540 | hc_died(hcd_to_uhci(hcd)); | ||
541 | } | ||
542 | |||
461 | /* | 543 | /* |
462 | * Allocate a frame list, and then setup the skeleton | 544 | * Allocate a frame list, and then setup the skeleton |
463 | * | 545 | * |
@@ -478,17 +560,20 @@ static int uhci_start(struct usb_hcd *hcd) | |||
478 | { | 560 | { |
479 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 561 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
480 | int retval = -EBUSY; | 562 | int retval = -EBUSY; |
481 | int i, port; | 563 | int i; |
482 | unsigned io_size; | ||
483 | dma_addr_t dma_handle; | 564 | dma_addr_t dma_handle; |
484 | struct usb_device *udev; | ||
485 | struct dentry *dentry; | 565 | struct dentry *dentry; |
486 | 566 | ||
487 | io_size = (unsigned) hcd->rsrc_len; | 567 | hcd->uses_new_polling = 1; |
568 | if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM)) | ||
569 | hcd->can_wakeup = 1; /* Assume it supports PME# */ | ||
488 | 570 | ||
489 | dentry = debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, &uhci_debug_operations); | 571 | dentry = debugfs_create_file(hcd->self.bus_name, |
572 | S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, | ||
573 | &uhci_debug_operations); | ||
490 | if (!dentry) { | 574 | if (!dentry) { |
491 | dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n"); | 575 | dev_err(uhci_dev(uhci), |
576 | "couldn't create uhci debugfs entry\n"); | ||
492 | retval = -ENOMEM; | 577 | retval = -ENOMEM; |
493 | goto err_create_debug_entry; | 578 | goto err_create_debug_entry; |
494 | } | 579 | } |
@@ -510,6 +595,10 @@ static int uhci_start(struct usb_hcd *hcd) | |||
510 | 595 | ||
511 | init_waitqueue_head(&uhci->waitqh); | 596 | init_waitqueue_head(&uhci->waitqh); |
512 | 597 | ||
598 | init_timer(&uhci->stall_timer); | ||
599 | uhci->stall_timer.function = stall_callback; | ||
600 | uhci->stall_timer.data = (unsigned long) uhci; | ||
601 | |||
513 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | 602 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), |
514 | &dma_handle, 0); | 603 | &dma_handle, 0); |
515 | if (!uhci->fl) { | 604 | if (!uhci->fl) { |
@@ -536,46 +625,14 @@ static int uhci_start(struct usb_hcd *hcd) | |||
536 | goto err_create_qh_pool; | 625 | goto err_create_qh_pool; |
537 | } | 626 | } |
538 | 627 | ||
539 | /* Initialize the root hub */ | 628 | uhci->term_td = uhci_alloc_td(uhci); |
540 | |||
541 | /* UHCI specs says devices must have 2 ports, but goes on to say */ | ||
542 | /* they may have more but give no way to determine how many they */ | ||
543 | /* have. However, according to the UHCI spec, Bit 7 is always set */ | ||
544 | /* to 1. So we try to use this to our advantage */ | ||
545 | for (port = 0; port < (io_size - 0x10) / 2; port++) { | ||
546 | unsigned int portstatus; | ||
547 | |||
548 | portstatus = inw(uhci->io_addr + 0x10 + (port * 2)); | ||
549 | if (!(portstatus & 0x0080)) | ||
550 | break; | ||
551 | } | ||
552 | if (debug) | ||
553 | dev_info(uhci_dev(uhci), "detected %d ports\n", port); | ||
554 | |||
555 | /* This is experimental so anything less than 2 or greater than 8 is */ | ||
556 | /* something weird and we'll ignore it */ | ||
557 | if (port < 2 || port > UHCI_RH_MAXCHILD) { | ||
558 | dev_info(uhci_dev(uhci), "port count misdetected? " | ||
559 | "forcing to 2 ports\n"); | ||
560 | port = 2; | ||
561 | } | ||
562 | |||
563 | uhci->rh_numports = port; | ||
564 | |||
565 | udev = usb_alloc_dev(NULL, &hcd->self, 0); | ||
566 | if (!udev) { | ||
567 | dev_err(uhci_dev(uhci), "unable to allocate root hub\n"); | ||
568 | goto err_alloc_root_hub; | ||
569 | } | ||
570 | |||
571 | uhci->term_td = uhci_alloc_td(uhci, udev); | ||
572 | if (!uhci->term_td) { | 629 | if (!uhci->term_td) { |
573 | dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n"); | 630 | dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n"); |
574 | goto err_alloc_term_td; | 631 | goto err_alloc_term_td; |
575 | } | 632 | } |
576 | 633 | ||
577 | for (i = 0; i < UHCI_NUM_SKELQH; i++) { | 634 | for (i = 0; i < UHCI_NUM_SKELQH; i++) { |
578 | uhci->skelqh[i] = uhci_alloc_qh(uhci, udev); | 635 | uhci->skelqh[i] = uhci_alloc_qh(uhci); |
579 | if (!uhci->skelqh[i]) { | 636 | if (!uhci->skelqh[i]) { |
580 | dev_err(uhci_dev(uhci), "unable to allocate QH\n"); | 637 | dev_err(uhci_dev(uhci), "unable to allocate QH\n"); |
581 | goto err_alloc_skelqh; | 638 | goto err_alloc_skelqh; |
@@ -641,32 +698,17 @@ static int uhci_start(struct usb_hcd *hcd) | |||
641 | 698 | ||
642 | /* | 699 | /* |
643 | * Some architectures require a full mb() to enforce completion of | 700 | * Some architectures require a full mb() to enforce completion of |
644 | * the memory writes above before the I/O transfers in start_hc(). | 701 | * the memory writes above before the I/O transfers in configure_hc(). |
645 | */ | 702 | */ |
646 | mb(); | 703 | mb(); |
647 | if ((retval = start_hc(uhci)) != 0) | ||
648 | goto err_alloc_skelqh; | ||
649 | |||
650 | init_stall_timer(hcd); | ||
651 | |||
652 | udev->speed = USB_SPEED_FULL; | ||
653 | |||
654 | if (usb_hcd_register_root_hub(udev, hcd) != 0) { | ||
655 | dev_err(uhci_dev(uhci), "unable to start root hub\n"); | ||
656 | retval = -ENOMEM; | ||
657 | goto err_start_root_hub; | ||
658 | } | ||
659 | 704 | ||
705 | configure_hc(uhci); | ||
706 | start_rh(uhci); | ||
660 | return 0; | 707 | return 0; |
661 | 708 | ||
662 | /* | 709 | /* |
663 | * error exits: | 710 | * error exits: |
664 | */ | 711 | */ |
665 | err_start_root_hub: | ||
666 | reset_hc(uhci); | ||
667 | |||
668 | del_timer_sync(&uhci->stall_timer); | ||
669 | |||
670 | err_alloc_skelqh: | 712 | err_alloc_skelqh: |
671 | for (i = 0; i < UHCI_NUM_SKELQH; i++) | 713 | for (i = 0; i < UHCI_NUM_SKELQH; i++) |
672 | if (uhci->skelqh[i]) { | 714 | if (uhci->skelqh[i]) { |
@@ -678,9 +720,6 @@ err_alloc_skelqh: | |||
678 | uhci->term_td = NULL; | 720 | uhci->term_td = NULL; |
679 | 721 | ||
680 | err_alloc_term_td: | 722 | err_alloc_term_td: |
681 | usb_put_dev(udev); | ||
682 | |||
683 | err_alloc_root_hub: | ||
684 | dma_pool_destroy(uhci->qh_pool); | 723 | dma_pool_destroy(uhci->qh_pool); |
685 | uhci->qh_pool = NULL; | 724 | uhci->qh_pool = NULL; |
686 | 725 | ||
@@ -705,73 +744,114 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
705 | { | 744 | { |
706 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 745 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
707 | 746 | ||
708 | del_timer_sync(&uhci->stall_timer); | ||
709 | reset_hc(uhci); | ||
710 | |||
711 | spin_lock_irq(&uhci->lock); | 747 | spin_lock_irq(&uhci->lock); |
748 | reset_hc(uhci); | ||
712 | uhci_scan_schedule(uhci, NULL); | 749 | uhci_scan_schedule(uhci, NULL); |
713 | spin_unlock_irq(&uhci->lock); | 750 | spin_unlock_irq(&uhci->lock); |
714 | 751 | ||
752 | del_timer_sync(&uhci->stall_timer); | ||
715 | release_uhci(uhci); | 753 | release_uhci(uhci); |
716 | } | 754 | } |
717 | 755 | ||
718 | #ifdef CONFIG_PM | 756 | #ifdef CONFIG_PM |
757 | static int uhci_rh_suspend(struct usb_hcd *hcd) | ||
758 | { | ||
759 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
760 | |||
761 | spin_lock_irq(&uhci->lock); | ||
762 | if (!uhci->hc_inaccessible) /* Not dead */ | ||
763 | suspend_rh(uhci, UHCI_RH_SUSPENDED); | ||
764 | spin_unlock_irq(&uhci->lock); | ||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | static int uhci_rh_resume(struct usb_hcd *hcd) | ||
769 | { | ||
770 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
771 | int rc = 0; | ||
772 | |||
773 | spin_lock_irq(&uhci->lock); | ||
774 | if (uhci->hc_inaccessible) { | ||
775 | if (uhci->rh_state == UHCI_RH_SUSPENDED) { | ||
776 | dev_warn(uhci_dev(uhci), "HC isn't running!\n"); | ||
777 | rc = -ENODEV; | ||
778 | } | ||
779 | /* Otherwise the HC is dead */ | ||
780 | } else | ||
781 | wakeup_rh(uhci); | ||
782 | spin_unlock_irq(&uhci->lock); | ||
783 | return rc; | ||
784 | } | ||
785 | |||
719 | static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | 786 | static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) |
720 | { | 787 | { |
721 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 788 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
789 | int rc = 0; | ||
790 | |||
791 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); | ||
722 | 792 | ||
723 | spin_lock_irq(&uhci->lock); | 793 | spin_lock_irq(&uhci->lock); |
794 | if (uhci->hc_inaccessible) /* Dead or already suspended */ | ||
795 | goto done; | ||
724 | 796 | ||
725 | /* Don't try to suspend broken motherboards, reset instead */ | 797 | #ifndef CONFIG_USB_SUSPEND |
726 | if (suspend_allowed(uhci)) | 798 | /* Otherwise this would never happen */ |
727 | suspend_hc(uhci); | 799 | suspend_rh(uhci, UHCI_RH_SUSPENDED); |
728 | else { | 800 | #endif |
729 | spin_unlock_irq(&uhci->lock); | 801 | |
730 | reset_hc(uhci); | 802 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { |
731 | spin_lock_irq(&uhci->lock); | 803 | dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); |
732 | uhci_scan_schedule(uhci, NULL); | 804 | hcd->state = HC_STATE_RUNNING; |
733 | } | 805 | rc = -EBUSY; |
806 | goto done; | ||
807 | }; | ||
734 | 808 | ||
809 | /* All PCI host controllers are required to disable IRQ generation | ||
810 | * at the source, so we must turn off PIRQ. | ||
811 | */ | ||
812 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | ||
813 | uhci->hc_inaccessible = 1; | ||
814 | |||
815 | /* FIXME: Enable non-PME# remote wakeup? */ | ||
816 | |||
817 | done: | ||
735 | spin_unlock_irq(&uhci->lock); | 818 | spin_unlock_irq(&uhci->lock); |
736 | return 0; | 819 | if (rc == 0) |
820 | del_timer_sync(&hcd->rh_timer); | ||
821 | return rc; | ||
737 | } | 822 | } |
738 | 823 | ||
739 | static int uhci_resume(struct usb_hcd *hcd) | 824 | static int uhci_resume(struct usb_hcd *hcd) |
740 | { | 825 | { |
741 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 826 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
742 | int rc; | ||
743 | 827 | ||
744 | pci_set_master(to_pci_dev(uhci_dev(uhci))); | 828 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); |
745 | 829 | ||
830 | if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ | ||
831 | return 0; | ||
746 | spin_lock_irq(&uhci->lock); | 832 | spin_lock_irq(&uhci->lock); |
747 | 833 | ||
748 | if (uhci->state == UHCI_SUSPENDED) { | 834 | /* FIXME: Disable non-PME# remote wakeup? */ |
749 | 835 | ||
750 | /* | 836 | uhci->hc_inaccessible = 0; |
751 | * Some systems don't maintain the UHCI register values | 837 | |
752 | * during a PM suspend/resume cycle, so reinitialize | 838 | /* The BIOS may have changed the controller settings during a |
753 | * the Frame Number, Framelist Base Address, Interrupt | 839 | * system wakeup. Check it and reconfigure to avoid problems. |
754 | * Enable, and Legacy Support registers. | 840 | */ |
755 | */ | 841 | check_and_reset_hc(uhci); |
756 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | 842 | configure_hc(uhci); |
757 | 0); | 843 | |
758 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); | 844 | #ifndef CONFIG_USB_SUSPEND |
759 | outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); | 845 | /* Otherwise this would never happen */ |
760 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | | 846 | wakeup_rh(uhci); |
761 | USBINTR_SP, uhci->io_addr + USBINTR); | 847 | #endif |
762 | uhci->resume_detect = 1; | 848 | if (uhci->rh_state == UHCI_RH_RESET) |
763 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | 849 | suspend_rh(uhci, UHCI_RH_SUSPENDED); |
764 | USBLEGSUP_DEFAULT); | ||
765 | } else { | ||
766 | spin_unlock_irq(&uhci->lock); | ||
767 | reset_hc(uhci); | ||
768 | if ((rc = start_hc(uhci)) != 0) | ||
769 | return rc; | ||
770 | spin_lock_irq(&uhci->lock); | ||
771 | } | ||
772 | hcd->state = HC_STATE_RUNNING; | ||
773 | 850 | ||
774 | spin_unlock_irq(&uhci->lock); | 851 | spin_unlock_irq(&uhci->lock); |
852 | |||
853 | if (hcd->poll_rh) | ||
854 | usb_hcd_poll_rh_status(hcd); | ||
775 | return 0; | 855 | return 0; |
776 | } | 856 | } |
777 | #endif | 857 | #endif |
@@ -788,13 +868,15 @@ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd, | |||
788 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) | 868 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) |
789 | { | 869 | { |
790 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 870 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
791 | int frame_number; | ||
792 | unsigned long flags; | 871 | unsigned long flags; |
872 | int is_stopped; | ||
873 | int frame_number; | ||
793 | 874 | ||
794 | /* Minimize latency by avoiding the spinlock */ | 875 | /* Minimize latency by avoiding the spinlock */ |
795 | local_irq_save(flags); | 876 | local_irq_save(flags); |
796 | rmb(); | 877 | is_stopped = uhci->is_stopped; |
797 | frame_number = (uhci->is_stopped ? uhci->frame_number : | 878 | smp_rmb(); |
879 | frame_number = (is_stopped ? uhci->frame_number : | ||
798 | inw(uhci->io_addr + USBFRNUM)); | 880 | inw(uhci->io_addr + USBFRNUM)); |
799 | local_irq_restore(flags); | 881 | local_irq_restore(flags); |
800 | return frame_number; | 882 | return frame_number; |
@@ -817,6 +899,8 @@ static const struct hc_driver uhci_driver = { | |||
817 | #ifdef CONFIG_PM | 899 | #ifdef CONFIG_PM |
818 | .suspend = uhci_suspend, | 900 | .suspend = uhci_suspend, |
819 | .resume = uhci_resume, | 901 | .resume = uhci_resume, |
902 | .hub_suspend = uhci_rh_suspend, | ||
903 | .hub_resume = uhci_rh_resume, | ||
820 | #endif | 904 | #endif |
821 | .stop = uhci_stop, | 905 | .stop = uhci_stop, |
822 | 906 | ||
@@ -845,6 +929,7 @@ static struct pci_driver uhci_pci_driver = { | |||
845 | 929 | ||
846 | .probe = usb_hcd_pci_probe, | 930 | .probe = usb_hcd_pci_probe, |
847 | .remove = usb_hcd_pci_remove, | 931 | .remove = usb_hcd_pci_remove, |
932 | .shutdown = uhci_shutdown, | ||
848 | 933 | ||
849 | #ifdef CONFIG_PM | 934 | #ifdef CONFIG_PM |
850 | .suspend = usb_hcd_pci_suspend, | 935 | .suspend = usb_hcd_pci_suspend, |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 02255d69e1fe..bf9c5f9b508b 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -41,6 +41,7 @@ | |||
41 | #define USBFRNUM 6 | 41 | #define USBFRNUM 6 |
42 | #define USBFLBASEADD 8 | 42 | #define USBFLBASEADD 8 |
43 | #define USBSOF 12 | 43 | #define USBSOF 12 |
44 | #define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */ | ||
44 | 45 | ||
45 | /* USB port status and control registers */ | 46 | /* USB port status and control registers */ |
46 | #define USBPORTSC1 16 | 47 | #define USBPORTSC1 16 |
@@ -66,6 +67,8 @@ | |||
66 | /* Legacy support register */ | 67 | /* Legacy support register */ |
67 | #define USBLEGSUP 0xc0 | 68 | #define USBLEGSUP 0xc0 |
68 | #define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ | 69 | #define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ |
70 | #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ | ||
71 | #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ | ||
69 | 72 | ||
70 | #define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ | 73 | #define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ |
71 | 74 | ||
@@ -111,7 +114,6 @@ struct uhci_qh { | |||
111 | /* Software fields */ | 114 | /* Software fields */ |
112 | dma_addr_t dma_handle; | 115 | dma_addr_t dma_handle; |
113 | 116 | ||
114 | struct usb_device *dev; | ||
115 | struct urb_priv *urbp; | 117 | struct urb_priv *urbp; |
116 | 118 | ||
117 | struct list_head list; /* P: uhci->frame_list_lock */ | 119 | struct list_head list; /* P: uhci->frame_list_lock */ |
@@ -203,7 +205,6 @@ struct uhci_td { | |||
203 | /* Software fields */ | 205 | /* Software fields */ |
204 | dma_addr_t dma_handle; | 206 | dma_addr_t dma_handle; |
205 | 207 | ||
206 | struct usb_device *dev; | ||
207 | struct urb *urb; | 208 | struct urb *urb; |
208 | 209 | ||
209 | struct list_head list; /* P: urb->lock */ | 210 | struct list_head list; /* P: urb->lock */ |
@@ -314,26 +315,32 @@ static inline int __interval_to_skel(int interval) | |||
314 | } | 315 | } |
315 | 316 | ||
316 | /* | 317 | /* |
317 | * Device states for the host controller. | 318 | * States for the root hub. |
318 | * | 319 | * |
319 | * To prevent "bouncing" in the presence of electrical noise, | 320 | * To prevent "bouncing" in the presence of electrical noise, |
320 | * we insist on a 1-second "grace" period, before switching to | 321 | * when there are no devices attached we delay for 1 second in the |
321 | * the RUNNING or SUSPENDED states, during which the state is | 322 | * RUNNING_NODEVS state before switching to the AUTO_STOPPED state. |
322 | * not allowed to change. | 323 | * |
323 | * | 324 | * (Note that the AUTO_STOPPED state won't be necessary once the hub |
324 | * The resume process is divided into substates in order to avoid | 325 | * driver learns to autosuspend.) |
325 | * potentially length delays during the timer handler. | ||
326 | * | ||
327 | * States in which the host controller is halted must have values <= 0. | ||
328 | */ | 326 | */ |
329 | enum uhci_state { | 327 | enum uhci_rh_state { |
330 | UHCI_RESET, | 328 | /* In the following states the HC must be halted. |
331 | UHCI_RUNNING_GRACE, /* Before RUNNING */ | 329 | * These two must come first */ |
332 | UHCI_RUNNING, /* The normal state */ | 330 | UHCI_RH_RESET, |
333 | UHCI_SUSPENDING_GRACE, /* Before SUSPENDED */ | 331 | UHCI_RH_SUSPENDED, |
334 | UHCI_SUSPENDED = -10, /* When no devices are attached */ | 332 | |
335 | UHCI_RESUMING_1, | 333 | UHCI_RH_AUTO_STOPPED, |
336 | UHCI_RESUMING_2 | 334 | UHCI_RH_RESUMING, |
335 | |||
336 | /* In this state the HC changes from running to halted, | ||
337 | * so it can legally appear either way. */ | ||
338 | UHCI_RH_SUSPENDING, | ||
339 | |||
340 | /* In the following states it's an error if the HC is halted. | ||
341 | * These two must come last */ | ||
342 | UHCI_RH_RUNNING, /* The normal state */ | ||
343 | UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */ | ||
337 | }; | 344 | }; |
338 | 345 | ||
339 | /* | 346 | /* |
@@ -363,15 +370,16 @@ struct uhci_hcd { | |||
363 | int fsbr; /* Full-speed bandwidth reclamation */ | 370 | int fsbr; /* Full-speed bandwidth reclamation */ |
364 | unsigned long fsbrtimeout; /* FSBR delay */ | 371 | unsigned long fsbrtimeout; /* FSBR delay */ |
365 | 372 | ||
366 | enum uhci_state state; /* FIXME: needs a spinlock */ | 373 | enum uhci_rh_state rh_state; |
367 | unsigned long state_end; /* Time of next transition */ | 374 | unsigned long auto_stop_time; /* When to AUTO_STOP */ |
375 | |||
368 | unsigned int frame_number; /* As of last check */ | 376 | unsigned int frame_number; /* As of last check */ |
369 | unsigned int is_stopped; | 377 | unsigned int is_stopped; |
370 | #define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ | 378 | #define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ |
371 | 379 | ||
372 | unsigned int scan_in_progress:1; /* Schedule scan is running */ | 380 | unsigned int scan_in_progress:1; /* Schedule scan is running */ |
373 | unsigned int need_rescan:1; /* Redo the schedule scan */ | 381 | unsigned int need_rescan:1; /* Redo the schedule scan */ |
374 | unsigned int resume_detect:1; /* Need a Global Resume */ | 382 | unsigned int hc_inaccessible:1; /* HC is suspended or dead */ |
375 | 383 | ||
376 | /* Support for port suspend/resume/reset */ | 384 | /* Support for port suspend/resume/reset */ |
377 | unsigned long port_c_suspend; /* Bit-arrays of ports */ | 385 | unsigned long port_c_suspend; /* Bit-arrays of ports */ |
@@ -451,4 +459,11 @@ struct urb_priv { | |||
451 | * #2 urb->lock | 459 | * #2 urb->lock |
452 | */ | 460 | */ |
453 | 461 | ||
462 | |||
463 | /* Some special IDs */ | ||
464 | |||
465 | #define PCI_VENDOR_ID_GENESYS 0x17a0 | ||
466 | #define PCI_DEVICE_ID_GL880S_UHCI 0x8083 | ||
467 | #define PCI_DEVICE_ID_GL880S_EHCI 0x8084 | ||
468 | |||
454 | #endif | 469 | #endif |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 4c45ba8390f8..4eace2b19ddb 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -33,9 +33,24 @@ static __u8 root_hub_hub_des[] = | |||
33 | /* status change bits: nonzero writes will clear */ | 33 | /* status change bits: nonzero writes will clear */ |
34 | #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) | 34 | #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) |
35 | 35 | ||
36 | static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | 36 | /* A port that either is connected or has a changed-bit set will prevent |
37 | * us from AUTO_STOPPING. | ||
38 | */ | ||
39 | static int any_ports_active(struct uhci_hcd *uhci) | ||
40 | { | ||
41 | int port; | ||
42 | |||
43 | for (port = 0; port < uhci->rh_numports; ++port) { | ||
44 | if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & | ||
45 | (USBPORTSC_CCS | RWC_BITS)) || | ||
46 | test_bit(port, &uhci->port_c_suspend)) | ||
47 | return 1; | ||
48 | } | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf) | ||
37 | { | 53 | { |
38 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
39 | int port; | 54 | int port; |
40 | 55 | ||
41 | *buf = 0; | 56 | *buf = 0; |
@@ -44,8 +59,6 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
44 | test_bit(port, &uhci->port_c_suspend)) | 59 | test_bit(port, &uhci->port_c_suspend)) |
45 | *buf |= (1 << (port + 1)); | 60 | *buf |= (1 << (port + 1)); |
46 | } | 61 | } |
47 | if (*buf && uhci->state == UHCI_SUSPENDED) | ||
48 | uhci->resume_detect = 1; | ||
49 | return !!*buf; | 62 | return !!*buf; |
50 | } | 63 | } |
51 | 64 | ||
@@ -115,6 +128,11 @@ static void uhci_check_ports(struct uhci_hcd *uhci) | |||
115 | set_bit(port, &uhci->resuming_ports); | 128 | set_bit(port, &uhci->resuming_ports); |
116 | uhci->ports_timeout = jiffies + | 129 | uhci->ports_timeout = jiffies + |
117 | msecs_to_jiffies(20); | 130 | msecs_to_jiffies(20); |
131 | |||
132 | /* Make sure we see the port again | ||
133 | * after the resuming period is over. */ | ||
134 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, | ||
135 | uhci->ports_timeout); | ||
118 | } else if (time_after_eq(jiffies, | 136 | } else if (time_after_eq(jiffies, |
119 | uhci->ports_timeout)) { | 137 | uhci->ports_timeout)) { |
120 | uhci_finish_suspend(uhci, port, port_addr); | 138 | uhci_finish_suspend(uhci, port, port_addr); |
@@ -123,6 +141,60 @@ static void uhci_check_ports(struct uhci_hcd *uhci) | |||
123 | } | 141 | } |
124 | } | 142 | } |
125 | 143 | ||
144 | static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
145 | { | ||
146 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
147 | unsigned long flags; | ||
148 | int status; | ||
149 | |||
150 | spin_lock_irqsave(&uhci->lock, flags); | ||
151 | if (uhci->hc_inaccessible) { | ||
152 | status = 0; | ||
153 | goto done; | ||
154 | } | ||
155 | |||
156 | uhci_check_ports(uhci); | ||
157 | status = get_hub_status_data(uhci, buf); | ||
158 | |||
159 | switch (uhci->rh_state) { | ||
160 | case UHCI_RH_SUSPENDING: | ||
161 | case UHCI_RH_SUSPENDED: | ||
162 | /* if port change, ask to be resumed */ | ||
163 | if (status) | ||
164 | usb_hcd_resume_root_hub(hcd); | ||
165 | break; | ||
166 | |||
167 | case UHCI_RH_AUTO_STOPPED: | ||
168 | /* if port change, auto start */ | ||
169 | if (status) | ||
170 | wakeup_rh(uhci); | ||
171 | break; | ||
172 | |||
173 | case UHCI_RH_RUNNING: | ||
174 | /* are any devices attached? */ | ||
175 | if (!any_ports_active(uhci)) { | ||
176 | uhci->rh_state = UHCI_RH_RUNNING_NODEVS; | ||
177 | uhci->auto_stop_time = jiffies + HZ; | ||
178 | } | ||
179 | break; | ||
180 | |||
181 | case UHCI_RH_RUNNING_NODEVS: | ||
182 | /* auto-stop if nothing connected for 1 second */ | ||
183 | if (any_ports_active(uhci)) | ||
184 | uhci->rh_state = UHCI_RH_RUNNING; | ||
185 | else if (time_after_eq(jiffies, uhci->auto_stop_time)) | ||
186 | suspend_rh(uhci, UHCI_RH_AUTO_STOPPED); | ||
187 | break; | ||
188 | |||
189 | default: | ||
190 | break; | ||
191 | } | ||
192 | |||
193 | done: | ||
194 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
195 | return status; | ||
196 | } | ||
197 | |||
126 | /* size of returned buffer is part of USB spec */ | 198 | /* size of returned buffer is part of USB spec */ |
127 | static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | 199 | static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, |
128 | u16 wIndex, char *buf, u16 wLength) | 200 | u16 wIndex, char *buf, u16 wLength) |
@@ -134,6 +206,9 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
134 | u16 wPortChange, wPortStatus; | 206 | u16 wPortChange, wPortStatus; |
135 | unsigned long flags; | 207 | unsigned long flags; |
136 | 208 | ||
209 | if (uhci->hc_inaccessible) | ||
210 | return -ETIMEDOUT; | ||
211 | |||
137 | spin_lock_irqsave(&uhci->lock, flags); | 212 | spin_lock_irqsave(&uhci->lock, flags); |
138 | switch (typeReq) { | 213 | switch (typeReq) { |
139 | 214 | ||
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 2a7c19501f24..5f18084a116d 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -32,6 +32,8 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci); | |||
32 | */ | 32 | */ |
33 | static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) | 33 | static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) |
34 | { | 34 | { |
35 | if (uhci->is_stopped) | ||
36 | mod_timer(&uhci->stall_timer, jiffies); | ||
35 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); | 37 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); |
36 | } | 38 | } |
37 | 39 | ||
@@ -46,7 +48,7 @@ static inline void uhci_moveto_complete(struct uhci_hcd *uhci, | |||
46 | list_move_tail(&urbp->urb_list, &uhci->complete_list); | 48 | list_move_tail(&urbp->urb_list, &uhci->complete_list); |
47 | } | 49 | } |
48 | 50 | ||
49 | static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev) | 51 | static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) |
50 | { | 52 | { |
51 | dma_addr_t dma_handle; | 53 | dma_addr_t dma_handle; |
52 | struct uhci_td *td; | 54 | struct uhci_td *td; |
@@ -61,14 +63,11 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *d | |||
61 | td->buffer = 0; | 63 | td->buffer = 0; |
62 | 64 | ||
63 | td->frame = -1; | 65 | td->frame = -1; |
64 | td->dev = dev; | ||
65 | 66 | ||
66 | INIT_LIST_HEAD(&td->list); | 67 | INIT_LIST_HEAD(&td->list); |
67 | INIT_LIST_HEAD(&td->remove_list); | 68 | INIT_LIST_HEAD(&td->remove_list); |
68 | INIT_LIST_HEAD(&td->fl_list); | 69 | INIT_LIST_HEAD(&td->fl_list); |
69 | 70 | ||
70 | usb_get_dev(dev); | ||
71 | |||
72 | return td; | 71 | return td; |
73 | } | 72 | } |
74 | 73 | ||
@@ -168,13 +167,10 @@ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) | |||
168 | if (!list_empty(&td->fl_list)) | 167 | if (!list_empty(&td->fl_list)) |
169 | dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); | 168 | dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); |
170 | 169 | ||
171 | if (td->dev) | ||
172 | usb_put_dev(td->dev); | ||
173 | |||
174 | dma_pool_free(uhci->td_pool, td, td->dma_handle); | 170 | dma_pool_free(uhci->td_pool, td, td->dma_handle); |
175 | } | 171 | } |
176 | 172 | ||
177 | static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev) | 173 | static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci) |
178 | { | 174 | { |
179 | dma_addr_t dma_handle; | 175 | dma_addr_t dma_handle; |
180 | struct uhci_qh *qh; | 176 | struct uhci_qh *qh; |
@@ -188,14 +184,11 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *d | |||
188 | qh->element = UHCI_PTR_TERM; | 184 | qh->element = UHCI_PTR_TERM; |
189 | qh->link = UHCI_PTR_TERM; | 185 | qh->link = UHCI_PTR_TERM; |
190 | 186 | ||
191 | qh->dev = dev; | ||
192 | qh->urbp = NULL; | 187 | qh->urbp = NULL; |
193 | 188 | ||
194 | INIT_LIST_HEAD(&qh->list); | 189 | INIT_LIST_HEAD(&qh->list); |
195 | INIT_LIST_HEAD(&qh->remove_list); | 190 | INIT_LIST_HEAD(&qh->remove_list); |
196 | 191 | ||
197 | usb_get_dev(dev); | ||
198 | |||
199 | return qh; | 192 | return qh; |
200 | } | 193 | } |
201 | 194 | ||
@@ -206,9 +199,6 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
206 | if (!list_empty(&qh->remove_list)) | 199 | if (!list_empty(&qh->remove_list)) |
207 | dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); | 200 | dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); |
208 | 201 | ||
209 | if (qh->dev) | ||
210 | usb_put_dev(qh->dev); | ||
211 | |||
212 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); | 202 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); |
213 | } | 203 | } |
214 | 204 | ||
@@ -597,7 +587,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
597 | /* | 587 | /* |
598 | * Build the TD for the control request setup packet | 588 | * Build the TD for the control request setup packet |
599 | */ | 589 | */ |
600 | td = uhci_alloc_td(uhci, urb->dev); | 590 | td = uhci_alloc_td(uhci); |
601 | if (!td) | 591 | if (!td) |
602 | return -ENOMEM; | 592 | return -ENOMEM; |
603 | 593 | ||
@@ -626,7 +616,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
626 | if (pktsze > maxsze) | 616 | if (pktsze > maxsze) |
627 | pktsze = maxsze; | 617 | pktsze = maxsze; |
628 | 618 | ||
629 | td = uhci_alloc_td(uhci, urb->dev); | 619 | td = uhci_alloc_td(uhci); |
630 | if (!td) | 620 | if (!td) |
631 | return -ENOMEM; | 621 | return -ENOMEM; |
632 | 622 | ||
@@ -644,7 +634,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
644 | /* | 634 | /* |
645 | * Build the final TD for control status | 635 | * Build the final TD for control status |
646 | */ | 636 | */ |
647 | td = uhci_alloc_td(uhci, urb->dev); | 637 | td = uhci_alloc_td(uhci); |
648 | if (!td) | 638 | if (!td) |
649 | return -ENOMEM; | 639 | return -ENOMEM; |
650 | 640 | ||
@@ -666,7 +656,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
666 | uhci_fill_td(td, status | TD_CTRL_IOC, | 656 | uhci_fill_td(td, status | TD_CTRL_IOC, |
667 | destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0); | 657 | destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0); |
668 | 658 | ||
669 | qh = uhci_alloc_qh(uhci, urb->dev); | 659 | qh = uhci_alloc_qh(uhci); |
670 | if (!qh) | 660 | if (!qh) |
671 | return -ENOMEM; | 661 | return -ENOMEM; |
672 | 662 | ||
@@ -865,7 +855,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb | |||
865 | status &= ~TD_CTRL_SPD; | 855 | status &= ~TD_CTRL_SPD; |
866 | } | 856 | } |
867 | 857 | ||
868 | td = uhci_alloc_td(uhci, urb->dev); | 858 | td = uhci_alloc_td(uhci); |
869 | if (!td) | 859 | if (!td) |
870 | return -ENOMEM; | 860 | return -ENOMEM; |
871 | 861 | ||
@@ -891,7 +881,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb | |||
891 | */ | 881 | */ |
892 | if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && | 882 | if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && |
893 | !len && urb->transfer_buffer_length) { | 883 | !len && urb->transfer_buffer_length) { |
894 | td = uhci_alloc_td(uhci, urb->dev); | 884 | td = uhci_alloc_td(uhci); |
895 | if (!td) | 885 | if (!td) |
896 | return -ENOMEM; | 886 | return -ENOMEM; |
897 | 887 | ||
@@ -913,7 +903,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb | |||
913 | * flag setting. */ | 903 | * flag setting. */ |
914 | td->status |= cpu_to_le32(TD_CTRL_IOC); | 904 | td->status |= cpu_to_le32(TD_CTRL_IOC); |
915 | 905 | ||
916 | qh = uhci_alloc_qh(uhci, urb->dev); | 906 | qh = uhci_alloc_qh(uhci); |
917 | if (!qh) | 907 | if (!qh) |
918 | return -ENOMEM; | 908 | return -ENOMEM; |
919 | 909 | ||
@@ -1096,7 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
1096 | if (!urb->iso_frame_desc[i].length) | 1086 | if (!urb->iso_frame_desc[i].length) |
1097 | continue; | 1087 | continue; |
1098 | 1088 | ||
1099 | td = uhci_alloc_td(uhci, urb->dev); | 1089 | td = uhci_alloc_td(uhci); |
1100 | if (!td) | 1090 | if (!td) |
1101 | return -ENOMEM; | 1091 | return -ENOMEM; |
1102 | 1092 | ||
@@ -1497,6 +1487,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) | |||
1497 | rescan: | 1487 | rescan: |
1498 | uhci->need_rescan = 0; | 1488 | uhci->need_rescan = 0; |
1499 | 1489 | ||
1490 | uhci_clear_next_interrupt(uhci); | ||
1500 | uhci_get_current_frame_number(uhci); | 1491 | uhci_get_current_frame_number(uhci); |
1501 | 1492 | ||
1502 | if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) | 1493 | if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) |
@@ -1537,3 +1528,26 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) | |||
1537 | /* Wake up anyone waiting for an URB to complete */ | 1528 | /* Wake up anyone waiting for an URB to complete */ |
1538 | wake_up_all(&uhci->waitqh); | 1529 | wake_up_all(&uhci->waitqh); |
1539 | } | 1530 | } |
1531 | |||
1532 | static void check_fsbr(struct uhci_hcd *uhci) | ||
1533 | { | ||
1534 | struct urb_priv *up; | ||
1535 | |||
1536 | list_for_each_entry(up, &uhci->urb_list, urb_list) { | ||
1537 | struct urb *u = up->urb; | ||
1538 | |||
1539 | spin_lock(&u->lock); | ||
1540 | |||
1541 | /* Check if the FSBR timed out */ | ||
1542 | if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) | ||
1543 | uhci_fsbr_timeout(uhci, u); | ||
1544 | |||
1545 | spin_unlock(&u->lock); | ||
1546 | } | ||
1547 | |||
1548 | /* Really disable FSBR */ | ||
1549 | if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { | ||
1550 | uhci->fsbrtimeout = 0; | ||
1551 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | ||
1552 | } | ||
1553 | } | ||
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index d28e7eab6f98..fd59f6bdd67f 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
@@ -151,6 +151,18 @@ config USB_WACOM | |||
151 | To compile this driver as a module, choose M here: the | 151 | To compile this driver as a module, choose M here: the |
152 | module will be called wacom. | 152 | module will be called wacom. |
153 | 153 | ||
154 | config USB_ACECAD | ||
155 | tristate "Acecad Flair tablet support" | ||
156 | depends on USB && INPUT | ||
157 | help | ||
158 | Say Y here if you want to use the USB version of the Acecad Flair | ||
159 | tablet. Make sure to say Y to "Mouse support" | ||
160 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
161 | (CONFIG_INPUT_EVDEV) as well. | ||
162 | |||
163 | To compile this driver as a module, choose M here: the | ||
164 | module will be called acecad. | ||
165 | |||
154 | config USB_KBTAB | 166 | config USB_KBTAB |
155 | tristate "KB Gear JamStudio tablet support" | 167 | tristate "KB Gear JamStudio tablet support" |
156 | depends on USB && INPUT | 168 | depends on USB && INPUT |
@@ -190,6 +202,18 @@ config USB_MTOUCH | |||
190 | To compile this driver as a module, choose M here: the | 202 | To compile this driver as a module, choose M here: the |
191 | module will be called mtouchusb. | 203 | module will be called mtouchusb. |
192 | 204 | ||
205 | config USB_ITMTOUCH | ||
206 | tristate "ITM Touch USB Touchscreen Driver" | ||
207 | depends on USB && INPUT | ||
208 | ---help--- | ||
209 | Say Y here if you want to use a ITM Touch USB | ||
210 | Touchscreen controller. | ||
211 | |||
212 | This touchscreen is used in LG 1510SF monitors. | ||
213 | |||
214 | To compile this driver as a module, choose M here: the | ||
215 | module will be called itmtouch. | ||
216 | |||
193 | config USB_EGALAX | 217 | config USB_EGALAX |
194 | tristate "eGalax TouchKit USB Touchscreen Driver" | 218 | tristate "eGalax TouchKit USB Touchscreen Driver" |
195 | depends on USB && INPUT | 219 | depends on USB && INPUT |
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 6bcedd16b0a1..831b2b0f1f05 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile | |||
@@ -33,7 +33,9 @@ obj-$(CONFIG_USB_KBD) += usbkbd.o | |||
33 | obj-$(CONFIG_USB_KBTAB) += kbtab.o | 33 | obj-$(CONFIG_USB_KBTAB) += kbtab.o |
34 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o | 34 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o |
35 | obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o | 35 | obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o |
36 | obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o | ||
36 | obj-$(CONFIG_USB_EGALAX) += touchkitusb.o | 37 | obj-$(CONFIG_USB_EGALAX) += touchkitusb.o |
37 | obj-$(CONFIG_USB_POWERMATE) += powermate.o | 38 | obj-$(CONFIG_USB_POWERMATE) += powermate.o |
38 | obj-$(CONFIG_USB_WACOM) += wacom.o | 39 | obj-$(CONFIG_USB_WACOM) += wacom.o |
40 | obj-$(CONFIG_USB_ACECAD) += acecad.o | ||
39 | obj-$(CONFIG_USB_XPAD) += xpad.o | 41 | obj-$(CONFIG_USB_XPAD) += xpad.o |
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c new file mode 100644 index 000000000000..ebcf7c955800 --- /dev/null +++ b/drivers/usb/input/acecad.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2001-2005 Edouard TISSERANT <edouard.tisserant@wanadoo.fr> | ||
3 | * Copyright (c) 2004-2005 Stephane VOLTZ <svoltz@numericable.fr> | ||
4 | * | ||
5 | * USB Acecad "Acecad Flair" tablet support | ||
6 | * | ||
7 | * Changelog: | ||
8 | * v3.2 - Added sysfs support | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/input.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/usb.h> | ||
34 | |||
35 | /* | ||
36 | * Version Information | ||
37 | */ | ||
38 | #define DRIVER_VERSION "v3.2" | ||
39 | #define DRIVER_DESC "USB Acecad Flair tablet driver" | ||
40 | #define DRIVER_LICENSE "GPL" | ||
41 | #define DRIVER_AUTHOR "Edouard TISSERANT <edouard.tisserant@wanadoo.fr>" | ||
42 | |||
43 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
44 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
45 | MODULE_LICENSE(DRIVER_LICENSE); | ||
46 | |||
47 | #define USB_VENDOR_ID_ACECAD 0x0460 | ||
48 | #define USB_DEVICE_ID_FLAIR 0x0004 | ||
49 | #define USB_DEVICE_ID_302 0x0008 | ||
50 | |||
51 | struct usb_acecad { | ||
52 | char name[128]; | ||
53 | char phys[64]; | ||
54 | struct usb_device *usbdev; | ||
55 | struct input_dev dev; | ||
56 | struct urb *irq; | ||
57 | |||
58 | signed char *data; | ||
59 | dma_addr_t data_dma; | ||
60 | }; | ||
61 | |||
62 | static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs) | ||
63 | { | ||
64 | struct usb_acecad *acecad = urb->context; | ||
65 | unsigned char *data = acecad->data; | ||
66 | struct input_dev *dev = &acecad->dev; | ||
67 | int prox, status; | ||
68 | |||
69 | switch (urb->status) { | ||
70 | case 0: | ||
71 | /* success */ | ||
72 | break; | ||
73 | case -ECONNRESET: | ||
74 | case -ENOENT: | ||
75 | case -ESHUTDOWN: | ||
76 | /* this urb is terminated, clean up */ | ||
77 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
78 | return; | ||
79 | default: | ||
80 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
81 | goto resubmit; | ||
82 | } | ||
83 | |||
84 | prox = (data[0] & 0x04) >> 2; | ||
85 | input_report_key(dev, BTN_TOOL_PEN, prox); | ||
86 | |||
87 | if (prox) { | ||
88 | int x = data[1] | (data[2] << 8); | ||
89 | int y = data[3] | (data[4] << 8); | ||
90 | /*Pressure should compute the same way for flair and 302*/ | ||
91 | int pressure = data[5] | ((int)data[6] << 8); | ||
92 | int touch = data[0] & 0x01; | ||
93 | int stylus = (data[0] & 0x10) >> 4; | ||
94 | int stylus2 = (data[0] & 0x20) >> 5; | ||
95 | input_report_abs(dev, ABS_X, x); | ||
96 | input_report_abs(dev, ABS_Y, y); | ||
97 | input_report_abs(dev, ABS_PRESSURE, pressure); | ||
98 | input_report_key(dev, BTN_TOUCH, touch); | ||
99 | input_report_key(dev, BTN_STYLUS, stylus); | ||
100 | input_report_key(dev, BTN_STYLUS2, stylus2); | ||
101 | } | ||
102 | |||
103 | /* event termination */ | ||
104 | input_sync(dev); | ||
105 | |||
106 | resubmit: | ||
107 | status = usb_submit_urb (urb, GFP_ATOMIC); | ||
108 | if (status) | ||
109 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
110 | acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status); | ||
111 | } | ||
112 | |||
113 | static int usb_acecad_open(struct input_dev *dev) | ||
114 | { | ||
115 | struct usb_acecad *acecad = dev->private; | ||
116 | |||
117 | acecad->irq->dev = acecad->usbdev; | ||
118 | if (usb_submit_urb(acecad->irq, GFP_KERNEL)) | ||
119 | return -EIO; | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static void usb_acecad_close(struct input_dev *dev) | ||
125 | { | ||
126 | struct usb_acecad *acecad = dev->private; | ||
127 | |||
128 | usb_kill_urb(acecad->irq); | ||
129 | } | ||
130 | |||
131 | static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
132 | { | ||
133 | struct usb_device *dev = interface_to_usbdev(intf); | ||
134 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
135 | struct usb_endpoint_descriptor *endpoint; | ||
136 | struct usb_acecad *acecad; | ||
137 | int pipe, maxp; | ||
138 | char path[64]; | ||
139 | |||
140 | if (interface->desc.bNumEndpoints != 1) | ||
141 | return -ENODEV; | ||
142 | |||
143 | endpoint = &interface->endpoint[0].desc; | ||
144 | |||
145 | if (!(endpoint->bEndpointAddress & 0x80)) | ||
146 | return -ENODEV; | ||
147 | |||
148 | if ((endpoint->bmAttributes & 3) != 3) | ||
149 | return -ENODEV; | ||
150 | |||
151 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
152 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
153 | |||
154 | acecad = kcalloc(1, sizeof(struct usb_acecad), GFP_KERNEL); | ||
155 | if (!acecad) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma); | ||
159 | if (!acecad->data) | ||
160 | goto fail1; | ||
161 | |||
162 | acecad->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
163 | if (!acecad->irq) | ||
164 | goto fail2; | ||
165 | |||
166 | if (dev->manufacturer) | ||
167 | strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name)); | ||
168 | |||
169 | if (dev->product) { | ||
170 | if (dev->manufacturer) | ||
171 | strlcat(acecad->name, " ", sizeof(acecad->name)); | ||
172 | strlcat(acecad->name, dev->product, sizeof(acecad->name)); | ||
173 | } | ||
174 | |||
175 | usb_make_path(dev, path, sizeof(path)); | ||
176 | snprintf(acecad->phys, sizeof(acecad->phys), "%s/input0", path); | ||
177 | |||
178 | acecad->usbdev = dev; | ||
179 | |||
180 | acecad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
181 | acecad->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); | ||
182 | acecad->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
183 | acecad->dev.keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2); | ||
184 | |||
185 | switch (id->driver_info) { | ||
186 | case 0: | ||
187 | acecad->dev.absmax[ABS_X] = 5000; | ||
188 | acecad->dev.absmax[ABS_Y] = 3750; | ||
189 | acecad->dev.absmax[ABS_PRESSURE] = 512; | ||
190 | if (!strlen(acecad->name)) | ||
191 | snprintf(acecad->name, sizeof(acecad->name), | ||
192 | "USB Acecad Flair Tablet %04x:%04x", | ||
193 | dev->descriptor.idVendor, dev->descriptor.idProduct); | ||
194 | break; | ||
195 | case 1: | ||
196 | acecad->dev.absmax[ABS_X] = 3000; | ||
197 | acecad->dev.absmax[ABS_Y] = 2250; | ||
198 | acecad->dev.absmax[ABS_PRESSURE] = 1024; | ||
199 | if (!strlen(acecad->name)) | ||
200 | snprintf(acecad->name, sizeof(acecad->name), | ||
201 | "USB Acecad 302 Tablet %04x:%04x", | ||
202 | dev->descriptor.idVendor, dev->descriptor.idProduct); | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | acecad->dev.absfuzz[ABS_X] = 4; | ||
207 | acecad->dev.absfuzz[ABS_Y] = 4; | ||
208 | |||
209 | acecad->dev.private = acecad; | ||
210 | acecad->dev.open = usb_acecad_open; | ||
211 | acecad->dev.close = usb_acecad_close; | ||
212 | |||
213 | acecad->dev.name = acecad->name; | ||
214 | acecad->dev.phys = acecad->phys; | ||
215 | acecad->dev.id.bustype = BUS_USB; | ||
216 | acecad->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
217 | acecad->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); | ||
218 | acecad->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
219 | acecad->dev.dev = &intf->dev; | ||
220 | |||
221 | usb_fill_int_urb(acecad->irq, dev, pipe, | ||
222 | acecad->data, maxp > 8 ? 8 : maxp, | ||
223 | usb_acecad_irq, acecad, endpoint->bInterval); | ||
224 | acecad->irq->transfer_dma = acecad->data_dma; | ||
225 | acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
226 | |||
227 | input_register_device(&acecad->dev); | ||
228 | |||
229 | printk(KERN_INFO "input: %s with packet size %d on %s\n", | ||
230 | acecad->name, maxp, path); | ||
231 | |||
232 | usb_set_intfdata(intf, acecad); | ||
233 | |||
234 | return 0; | ||
235 | |||
236 | fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); | ||
237 | fail1: kfree(acecad); | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | |||
241 | static void usb_acecad_disconnect(struct usb_interface *intf) | ||
242 | { | ||
243 | struct usb_acecad *acecad = usb_get_intfdata(intf); | ||
244 | |||
245 | usb_set_intfdata(intf, NULL); | ||
246 | if (acecad) { | ||
247 | usb_kill_urb(acecad->irq); | ||
248 | input_unregister_device(&acecad->dev); | ||
249 | usb_free_urb(acecad->irq); | ||
250 | usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); | ||
251 | kfree(acecad); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | static struct usb_device_id usb_acecad_id_table [] = { | ||
256 | { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 }, | ||
257 | { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302), .driver_info = 1 }, | ||
258 | { } | ||
259 | }; | ||
260 | |||
261 | MODULE_DEVICE_TABLE(usb, usb_acecad_id_table); | ||
262 | |||
263 | static struct usb_driver usb_acecad_driver = { | ||
264 | .owner = THIS_MODULE, | ||
265 | .name = "usb_acecad", | ||
266 | .probe = usb_acecad_probe, | ||
267 | .disconnect = usb_acecad_disconnect, | ||
268 | .id_table = usb_acecad_id_table, | ||
269 | }; | ||
270 | |||
271 | static int __init usb_acecad_init(void) | ||
272 | { | ||
273 | int result = usb_register(&usb_acecad_driver); | ||
274 | if (result == 0) | ||
275 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
276 | return result; | ||
277 | } | ||
278 | |||
279 | static void __exit usb_acecad_exit(void) | ||
280 | { | ||
281 | usb_deregister(&usb_acecad_driver); | ||
282 | } | ||
283 | |||
284 | module_init(usb_acecad_init); | ||
285 | module_exit(usb_acecad_exit); | ||
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index e991f7ed7330..6bb0f25e8e93 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Native support for the Aiptek HyperPen USB Tablets | 2 | * Native support for the Aiptek HyperPen USB Tablets |
3 | * (4000U/5000U/6000U/8000U/12000U) | 3 | * (4000U/5000U/6000U/8000U/12000U) |
4 | * | 4 | * |
5 | * Copyright (c) 2001 Chris Atenasio <chris@crud.net> | 5 | * Copyright (c) 2001 Chris Atenasio <chris@crud.net> |
6 | * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> | 6 | * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> |
7 | * | 7 | * |
@@ -31,7 +31,7 @@ | |||
31 | * - Added support for the sysfs interface, deprecating the | 31 | * - Added support for the sysfs interface, deprecating the |
32 | * procfs interface for 2.5.x kernel. Also added support for | 32 | * procfs interface for 2.5.x kernel. Also added support for |
33 | * Wheel command. Bryan W. Headley July-15-2003. | 33 | * Wheel command. Bryan W. Headley July-15-2003. |
34 | * v1.2 - Reworked jitter timer as a kernel thread. | 34 | * v1.2 - Reworked jitter timer as a kernel thread. |
35 | * Bryan W. Headley November-28-2003/Jan-10-2004. | 35 | * Bryan W. Headley November-28-2003/Jan-10-2004. |
36 | * v1.3 - Repaired issue of kernel thread going nuts on single-processor | 36 | * v1.3 - Repaired issue of kernel thread going nuts on single-processor |
37 | * machines, introduced programmableDelay as a command line | 37 | * machines, introduced programmableDelay as a command line |
@@ -49,10 +49,10 @@ | |||
49 | * NOTE: | 49 | * NOTE: |
50 | * This kernel driver is augmented by the "Aiptek" XFree86 input | 50 | * This kernel driver is augmented by the "Aiptek" XFree86 input |
51 | * driver for your X server, as well as the Gaiptek GUI Front-end | 51 | * driver for your X server, as well as the Gaiptek GUI Front-end |
52 | * "Tablet Manager". | 52 | * "Tablet Manager". |
53 | * These three products are highly interactive with one another, | 53 | * These three products are highly interactive with one another, |
54 | * so therefore it's easier to document them all as one subsystem. | 54 | * so therefore it's easier to document them all as one subsystem. |
55 | * Please visit the project's "home page", located at, | 55 | * Please visit the project's "home page", located at, |
56 | * http://aiptektablet.sourceforge.net. | 56 | * http://aiptektablet.sourceforge.net. |
57 | * | 57 | * |
58 | * This program is free software; you can redistribute it and/or modify | 58 | * This program is free software; you can redistribute it and/or modify |
@@ -156,7 +156,7 @@ | |||
156 | * Command/Data Description Return Bytes Return Value | 156 | * Command/Data Description Return Bytes Return Value |
157 | * 0x10/0x00 SwitchToMouse 0 | 157 | * 0x10/0x00 SwitchToMouse 0 |
158 | * 0x10/0x01 SwitchToTablet 0 | 158 | * 0x10/0x01 SwitchToTablet 0 |
159 | * 0x18/0x04 SetResolution 0 | 159 | * 0x18/0x04 SetResolution 0 |
160 | * 0x12/0xFF AutoGainOn 0 | 160 | * 0x12/0xFF AutoGainOn 0 |
161 | * 0x17/0x00 FilterOn 0 | 161 | * 0x17/0x00 FilterOn 0 |
162 | * 0x01/0x00 GetXExtension 2 MaxX | 162 | * 0x01/0x00 GetXExtension 2 MaxX |
@@ -247,7 +247,7 @@ | |||
247 | #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 | 247 | #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 |
248 | #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 | 248 | #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 |
249 | 249 | ||
250 | /* Time to wait (in ms) to help mask hand jittering | 250 | /* Time to wait (in ms) to help mask hand jittering |
251 | * when pressing the stylus buttons. | 251 | * when pressing the stylus buttons. |
252 | */ | 252 | */ |
253 | #define AIPTEK_JITTER_DELAY_DEFAULT 50 | 253 | #define AIPTEK_JITTER_DELAY_DEFAULT 50 |
@@ -324,7 +324,6 @@ struct aiptek { | |||
324 | struct aiptek_settings curSetting; /* tablet's current programmable */ | 324 | struct aiptek_settings curSetting; /* tablet's current programmable */ |
325 | struct aiptek_settings newSetting; /* ... and new param settings */ | 325 | struct aiptek_settings newSetting; /* ... and new param settings */ |
326 | unsigned int ifnum; /* interface number for IO */ | 326 | unsigned int ifnum; /* interface number for IO */ |
327 | int openCount; /* module use counter */ | ||
328 | int diagnostic; /* tablet diagnostic codes */ | 327 | int diagnostic; /* tablet diagnostic codes */ |
329 | unsigned long eventCount; /* event count */ | 328 | unsigned long eventCount; /* event count */ |
330 | int inDelay; /* jitter: in jitter delay? */ | 329 | int inDelay; /* jitter: in jitter delay? */ |
@@ -791,7 +790,7 @@ exit: | |||
791 | * specific Aiptek model numbers, because there has been overlaps, | 790 | * specific Aiptek model numbers, because there has been overlaps, |
792 | * use, and reuse of id's in existing models. Certain models have | 791 | * use, and reuse of id's in existing models. Certain models have |
793 | * been known to use more than one ID, indicative perhaps of | 792 | * been known to use more than one ID, indicative perhaps of |
794 | * manufacturing revisions. In any event, we consider these | 793 | * manufacturing revisions. In any event, we consider these |
795 | * IDs to not be model-specific nor unique. | 794 | * IDs to not be model-specific nor unique. |
796 | */ | 795 | */ |
797 | static const struct usb_device_id aiptek_ids[] = { | 796 | static const struct usb_device_id aiptek_ids[] = { |
@@ -814,15 +813,9 @@ static int aiptek_open(struct input_dev *inputdev) | |||
814 | { | 813 | { |
815 | struct aiptek *aiptek = inputdev->private; | 814 | struct aiptek *aiptek = inputdev->private; |
816 | 815 | ||
817 | if (aiptek->openCount++ > 0) { | ||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | aiptek->urb->dev = aiptek->usbdev; | 816 | aiptek->urb->dev = aiptek->usbdev; |
822 | if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) { | 817 | if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) |
823 | aiptek->openCount--; | ||
824 | return -EIO; | 818 | return -EIO; |
825 | } | ||
826 | 819 | ||
827 | return 0; | 820 | return 0; |
828 | } | 821 | } |
@@ -834,13 +827,11 @@ static void aiptek_close(struct input_dev *inputdev) | |||
834 | { | 827 | { |
835 | struct aiptek *aiptek = inputdev->private; | 828 | struct aiptek *aiptek = inputdev->private; |
836 | 829 | ||
837 | if (--aiptek->openCount == 0) { | 830 | usb_kill_urb(aiptek->urb); |
838 | usb_kill_urb(aiptek->urb); | ||
839 | } | ||
840 | } | 831 | } |
841 | 832 | ||
842 | /*********************************************************************** | 833 | /*********************************************************************** |
843 | * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, | 834 | * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, |
844 | * where they were known as usb_set_report and usb_get_report. | 835 | * where they were known as usb_set_report and usb_get_report. |
845 | */ | 836 | */ |
846 | static int | 837 | static int |
@@ -2252,7 +2243,6 @@ static void aiptek_disconnect(struct usb_interface *intf) | |||
2252 | AIPTEK_PACKET_LENGTH, | 2243 | AIPTEK_PACKET_LENGTH, |
2253 | aiptek->data, aiptek->data_dma); | 2244 | aiptek->data, aiptek->data_dma); |
2254 | kfree(aiptek); | 2245 | kfree(aiptek); |
2255 | aiptek = NULL; | ||
2256 | } | 2246 | } |
2257 | } | 2247 | } |
2258 | 2248 | ||
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 860df26323b1..654ac454744d 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c | |||
@@ -1,15 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * USB ATI Remote support | 2 | * USB ATI Remote support |
3 | * | 3 | * |
4 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> | 4 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> |
5 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev | 5 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev |
6 | * | 6 | * |
7 | * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including | 7 | * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including |
8 | * porting to the 2.6 kernel interfaces, along with other modification | 8 | * porting to the 2.6 kernel interfaces, along with other modification |
9 | * to better match the style of the existing usb/input drivers. However, the | 9 | * to better match the style of the existing usb/input drivers. However, the |
10 | * protocol and hardware handling is essentially unchanged from 2.1.1. | 10 | * protocol and hardware handling is essentially unchanged from 2.1.1. |
11 | * | 11 | * |
12 | * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by | 12 | * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by |
13 | * Vojtech Pavlik. | 13 | * Vojtech Pavlik. |
14 | * | 14 | * |
15 | * Changes: | 15 | * Changes: |
@@ -23,64 +23,64 @@ | |||
23 | * Added support for the "Lola" remote contributed by: | 23 | * Added support for the "Lola" remote contributed by: |
24 | * Seth Cohn <sethcohn@yahoo.com> | 24 | * Seth Cohn <sethcohn@yahoo.com> |
25 | * | 25 | * |
26 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | 26 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
27 | * | 27 | * |
28 | * This program is free software; you can redistribute it and/or modify | 28 | * This program is free software; you can redistribute it and/or modify |
29 | * it under the terms of the GNU General Public License as published by | 29 | * it under the terms of the GNU General Public License as published by |
30 | * the Free Software Foundation; either version 2 of the License, or | 30 | * the Free Software Foundation; either version 2 of the License, or |
31 | * (at your option) any later version. | 31 | * (at your option) any later version. |
32 | * | 32 | * |
33 | * This program is distributed in the hope that it will be useful, | 33 | * This program is distributed in the hope that it will be useful, |
34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
36 | * GNU General Public License for more details. | 36 | * GNU General Public License for more details. |
37 | * | 37 | * |
38 | * You should have received a copy of the GNU General Public License | 38 | * You should have received a copy of the GNU General Public License |
39 | * along with this program; if not, write to the Free Software | 39 | * along with this program; if not, write to the Free Software |
40 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 40 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
41 | * | 41 | * |
42 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | 42 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
43 | * | 43 | * |
44 | * Hardware & software notes | 44 | * Hardware & software notes |
45 | * | 45 | * |
46 | * These remote controls are distributed by ATI as part of their | 46 | * These remote controls are distributed by ATI as part of their |
47 | * "All-In-Wonder" video card packages. The receiver self-identifies as a | 47 | * "All-In-Wonder" video card packages. The receiver self-identifies as a |
48 | * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". | 48 | * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". |
49 | * | 49 | * |
50 | * The "Lola" remote is available from X10. See: | 50 | * The "Lola" remote is available from X10. See: |
51 | * http://www.x10.com/products/lola_sg1.htm | 51 | * http://www.x10.com/products/lola_sg1.htm |
52 | * The Lola is similar to the ATI remote but has no mouse support, and slightly | 52 | * The Lola is similar to the ATI remote but has no mouse support, and slightly |
53 | * different keys. | 53 | * different keys. |
54 | * | 54 | * |
55 | * It is possible to use multiple receivers and remotes on multiple computers | 55 | * It is possible to use multiple receivers and remotes on multiple computers |
56 | * simultaneously by configuring them to use specific channels. | 56 | * simultaneously by configuring them to use specific channels. |
57 | * | 57 | * |
58 | * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. | 58 | * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. |
59 | * Actually, it may even support more, at least in some revisions of the | 59 | * Actually, it may even support more, at least in some revisions of the |
60 | * hardware. | 60 | * hardware. |
61 | * | 61 | * |
62 | * Each remote can be configured to transmit on one channel as follows: | 62 | * Each remote can be configured to transmit on one channel as follows: |
63 | * - Press and hold the "hand icon" button. | 63 | * - Press and hold the "hand icon" button. |
64 | * - When the red LED starts to blink, let go of the "hand icon" button. | 64 | * - When the red LED starts to blink, let go of the "hand icon" button. |
65 | * - When it stops blinking, input the channel code as two digits, from 01 | 65 | * - When it stops blinking, input the channel code as two digits, from 01 |
66 | * to 16, and press the hand icon again. | 66 | * to 16, and press the hand icon again. |
67 | * | 67 | * |
68 | * The timing can be a little tricky. Try loading the module with debug=1 | 68 | * The timing can be a little tricky. Try loading the module with debug=1 |
69 | * to have the kernel print out messages about the remote control number | 69 | * to have the kernel print out messages about the remote control number |
70 | * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. | 70 | * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. |
71 | * | 71 | * |
72 | * The driver has a "channel_mask" parameter. This bitmask specifies which | 72 | * The driver has a "channel_mask" parameter. This bitmask specifies which |
73 | * channels will be ignored by the module. To mask out channels, just add | 73 | * channels will be ignored by the module. To mask out channels, just add |
74 | * all the 2^channel_number values together. | 74 | * all the 2^channel_number values together. |
75 | * | 75 | * |
76 | * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote | 76 | * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote |
77 | * ignore signals coming from remote controls transmitting on channel 4, but | 77 | * ignore signals coming from remote controls transmitting on channel 4, but |
78 | * accept all other channels. | 78 | * accept all other channels. |
79 | * | 79 | * |
80 | * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be | 80 | * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be |
81 | * ignored. | 81 | * ignored. |
82 | * | 82 | * |
83 | * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this | 83 | * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this |
84 | * parameter are unused. | 84 | * parameter are unused. |
85 | * | 85 | * |
86 | */ | 86 | */ |
@@ -99,13 +99,13 @@ | |||
99 | /* | 99 | /* |
100 | * Module and Version Information, Module Parameters | 100 | * Module and Version Information, Module Parameters |
101 | */ | 101 | */ |
102 | 102 | ||
103 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 | 103 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 |
104 | #define ATI_REMOTE_PRODUCT_ID 0x004 | 104 | #define ATI_REMOTE_PRODUCT_ID 0x004 |
105 | #define LOLA_REMOTE_PRODUCT_ID 0x002 | 105 | #define LOLA_REMOTE_PRODUCT_ID 0x002 |
106 | #define MEDION_REMOTE_PRODUCT_ID 0x006 | 106 | #define MEDION_REMOTE_PRODUCT_ID 0x006 |
107 | 107 | ||
108 | #define DRIVER_VERSION "2.2.1" | 108 | #define DRIVER_VERSION "2.2.1" |
109 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" | 109 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" |
110 | #define DRIVER_DESC "ATI/X10 RF USB Remote Control" | 110 | #define DRIVER_DESC "ATI/X10 RF USB Remote Control" |
111 | 111 | ||
@@ -113,18 +113,18 @@ | |||
113 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ | 113 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ |
114 | #define ATI_INPUTNUM 1 /* Which input device to register as */ | 114 | #define ATI_INPUTNUM 1 /* Which input device to register as */ |
115 | 115 | ||
116 | static unsigned long channel_mask = 0; | 116 | static unsigned long channel_mask; |
117 | module_param(channel_mask, ulong, 0444); | 117 | module_param(channel_mask, ulong, 0444); |
118 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); | 118 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); |
119 | 119 | ||
120 | static int debug = 0; | 120 | static int debug; |
121 | module_param(debug, int, 0444); | 121 | module_param(debug, int, 0444); |
122 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); | 122 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); |
123 | 123 | ||
124 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) | 124 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) |
125 | #undef err | 125 | #undef err |
126 | #define err(format, arg...) printk(KERN_ERR format , ## arg) | 126 | #define err(format, arg...) printk(KERN_ERR format , ## arg) |
127 | 127 | ||
128 | static struct usb_device_id ati_remote_table[] = { | 128 | static struct usb_device_id ati_remote_table[] = { |
129 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, | 129 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, |
130 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, | 130 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, |
@@ -148,7 +148,7 @@ static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; | |||
148 | /* Acceleration curve for directional control pad */ | 148 | /* Acceleration curve for directional control pad */ |
149 | static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | 149 | static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; |
150 | 150 | ||
151 | /* Duplicate event filtering time. | 151 | /* Duplicate event filtering time. |
152 | * Sequential, identical KIND_FILTERED inputs with less than | 152 | * Sequential, identical KIND_FILTERED inputs with less than |
153 | * FILTER_TIME jiffies between them are considered as repeat | 153 | * FILTER_TIME jiffies between them are considered as repeat |
154 | * events. The hardware generates 5 events for the first keypress | 154 | * events. The hardware generates 5 events for the first keypress |
@@ -161,10 +161,10 @@ static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | |||
161 | static DECLARE_MUTEX(disconnect_sem); | 161 | static DECLARE_MUTEX(disconnect_sem); |
162 | 162 | ||
163 | struct ati_remote { | 163 | struct ati_remote { |
164 | struct input_dev idev; | 164 | struct input_dev idev; |
165 | struct usb_device *udev; | 165 | struct usb_device *udev; |
166 | struct usb_interface *interface; | 166 | struct usb_interface *interface; |
167 | 167 | ||
168 | struct urb *irq_urb; | 168 | struct urb *irq_urb; |
169 | struct urb *out_urb; | 169 | struct urb *out_urb; |
170 | struct usb_endpoint_descriptor *endpoint_in; | 170 | struct usb_endpoint_descriptor *endpoint_in; |
@@ -174,13 +174,11 @@ struct ati_remote { | |||
174 | dma_addr_t inbuf_dma; | 174 | dma_addr_t inbuf_dma; |
175 | dma_addr_t outbuf_dma; | 175 | dma_addr_t outbuf_dma; |
176 | 176 | ||
177 | int open; /* open counter */ | ||
178 | |||
179 | unsigned char old_data[2]; /* Detect duplicate events */ | 177 | unsigned char old_data[2]; /* Detect duplicate events */ |
180 | unsigned long old_jiffies; | 178 | unsigned long old_jiffies; |
181 | unsigned long acc_jiffies; /* handle acceleration */ | 179 | unsigned long acc_jiffies; /* handle acceleration */ |
182 | unsigned int repeat_count; | 180 | unsigned int repeat_count; |
183 | 181 | ||
184 | char name[NAME_BUFSIZE]; | 182 | char name[NAME_BUFSIZE]; |
185 | char phys[NAME_BUFSIZE]; | 183 | char phys[NAME_BUFSIZE]; |
186 | 184 | ||
@@ -206,14 +204,14 @@ static struct | |||
206 | int type; | 204 | int type; |
207 | unsigned int code; | 205 | unsigned int code; |
208 | int value; | 206 | int value; |
209 | } ati_remote_tbl[] = | 207 | } ati_remote_tbl[] = |
210 | { | 208 | { |
211 | /* Directional control pad axes */ | 209 | /* Directional control pad axes */ |
212 | {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ | 210 | {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ |
213 | {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ | 211 | {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ |
214 | {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ | 212 | {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ |
215 | {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ | 213 | {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ |
216 | /* Directional control pad diagonals */ | 214 | /* Directional control pad diagonals */ |
217 | {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ | 215 | {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ |
218 | {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ | 216 | {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ |
219 | {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ | 217 | {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ |
@@ -225,7 +223,7 @@ static struct | |||
225 | {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ | 223 | {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ |
226 | {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ | 224 | {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ |
227 | 225 | ||
228 | /* Artificial "doubleclick" events are generated by the hardware. | 226 | /* Artificial "doubleclick" events are generated by the hardware. |
229 | * They are mapped to the "side" and "extra" mouse buttons here. */ | 227 | * They are mapped to the "side" and "extra" mouse buttons here. */ |
230 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ | 228 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ |
231 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ | 229 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ |
@@ -273,15 +271,15 @@ static struct | |||
273 | {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ | 271 | {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ |
274 | {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ | 272 | {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ |
275 | {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ | 273 | {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ |
276 | {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ | 274 | {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ |
277 | {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ | 275 | {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ |
278 | {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ | 276 | {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ |
279 | {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ | 277 | {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ |
280 | {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ | 278 | {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ |
281 | {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ | 279 | {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ |
282 | {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ | 280 | {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ |
283 | {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ | 281 | {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ |
284 | 282 | ||
285 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} | 283 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} |
286 | }; | 284 | }; |
287 | 285 | ||
@@ -315,7 +313,7 @@ static void ati_remote_dump(unsigned char *data, unsigned int len) | |||
315 | if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) | 313 | if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) |
316 | warn("Weird byte 0x%02x", data[0]); | 314 | warn("Weird byte 0x%02x", data[0]); |
317 | else if (len == 4) | 315 | else if (len == 4) |
318 | warn("Weird key %02x %02x %02x %02x", | 316 | warn("Weird key %02x %02x %02x %02x", |
319 | data[0], data[1], data[2], data[3]); | 317 | data[0], data[1], data[2], data[3]); |
320 | else | 318 | else |
321 | warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", | 319 | warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", |
@@ -328,25 +326,16 @@ static void ati_remote_dump(unsigned char *data, unsigned int len) | |||
328 | static int ati_remote_open(struct input_dev *inputdev) | 326 | static int ati_remote_open(struct input_dev *inputdev) |
329 | { | 327 | { |
330 | struct ati_remote *ati_remote = inputdev->private; | 328 | struct ati_remote *ati_remote = inputdev->private; |
331 | int retval = 0; | ||
332 | |||
333 | down(&disconnect_sem); | ||
334 | |||
335 | if (ati_remote->open++) | ||
336 | goto exit; | ||
337 | 329 | ||
338 | /* On first open, submit the read urb which was set up previously. */ | 330 | /* On first open, submit the read urb which was set up previously. */ |
339 | ati_remote->irq_urb->dev = ati_remote->udev; | 331 | ati_remote->irq_urb->dev = ati_remote->udev; |
340 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { | 332 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { |
341 | dev_err(&ati_remote->interface->dev, | 333 | dev_err(&ati_remote->interface->dev, |
342 | "%s: usb_submit_urb failed!\n", __FUNCTION__); | 334 | "%s: usb_submit_urb failed!\n", __FUNCTION__); |
343 | ati_remote->open--; | 335 | return -EIO; |
344 | retval = -EIO; | ||
345 | } | 336 | } |
346 | 337 | ||
347 | exit: | 338 | return 0; |
348 | up(&disconnect_sem); | ||
349 | return retval; | ||
350 | } | 339 | } |
351 | 340 | ||
352 | /* | 341 | /* |
@@ -355,9 +344,8 @@ exit: | |||
355 | static void ati_remote_close(struct input_dev *inputdev) | 344 | static void ati_remote_close(struct input_dev *inputdev) |
356 | { | 345 | { |
357 | struct ati_remote *ati_remote = inputdev->private; | 346 | struct ati_remote *ati_remote = inputdev->private; |
358 | 347 | ||
359 | if (!--ati_remote->open) | 348 | usb_kill_urb(ati_remote->irq_urb); |
360 | usb_kill_urb(ati_remote->irq_urb); | ||
361 | } | 349 | } |
362 | 350 | ||
363 | /* | 351 | /* |
@@ -366,13 +354,13 @@ static void ati_remote_close(struct input_dev *inputdev) | |||
366 | static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) | 354 | static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) |
367 | { | 355 | { |
368 | struct ati_remote *ati_remote = urb->context; | 356 | struct ati_remote *ati_remote = urb->context; |
369 | 357 | ||
370 | if (urb->status) { | 358 | if (urb->status) { |
371 | dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", | 359 | dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", |
372 | __FUNCTION__, urb->status); | 360 | __FUNCTION__, urb->status); |
373 | return; | 361 | return; |
374 | } | 362 | } |
375 | 363 | ||
376 | ati_remote->send_flags |= SEND_FLAG_COMPLETE; | 364 | ati_remote->send_flags |= SEND_FLAG_COMPLETE; |
377 | wmb(); | 365 | wmb(); |
378 | wake_up(&ati_remote->wait); | 366 | wake_up(&ati_remote->wait); |
@@ -380,16 +368,16 @@ static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) | |||
380 | 368 | ||
381 | /* | 369 | /* |
382 | * ati_remote_sendpacket | 370 | * ati_remote_sendpacket |
383 | * | 371 | * |
384 | * Used to send device initialization strings | 372 | * Used to send device initialization strings |
385 | */ | 373 | */ |
386 | static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) | 374 | static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) |
387 | { | 375 | { |
388 | int retval = 0; | 376 | int retval = 0; |
389 | 377 | ||
390 | /* Set up out_urb */ | 378 | /* Set up out_urb */ |
391 | memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); | 379 | memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); |
392 | ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); | 380 | ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); |
393 | 381 | ||
394 | ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; | 382 | ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; |
395 | ati_remote->out_urb->dev = ati_remote->udev; | 383 | ati_remote->out_urb->dev = ati_remote->udev; |
@@ -397,17 +385,17 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne | |||
397 | 385 | ||
398 | retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); | 386 | retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); |
399 | if (retval) { | 387 | if (retval) { |
400 | dev_dbg(&ati_remote->interface->dev, | 388 | dev_dbg(&ati_remote->interface->dev, |
401 | "sendpacket: usb_submit_urb failed: %d\n", retval); | 389 | "sendpacket: usb_submit_urb failed: %d\n", retval); |
402 | return retval; | 390 | return retval; |
403 | } | 391 | } |
404 | 392 | ||
405 | wait_event_timeout(ati_remote->wait, | 393 | wait_event_timeout(ati_remote->wait, |
406 | ((ati_remote->out_urb->status != -EINPROGRESS) || | 394 | ((ati_remote->out_urb->status != -EINPROGRESS) || |
407 | (ati_remote->send_flags & SEND_FLAG_COMPLETE)), | 395 | (ati_remote->send_flags & SEND_FLAG_COMPLETE)), |
408 | HZ); | 396 | HZ); |
409 | usb_kill_urb(ati_remote->out_urb); | 397 | usb_kill_urb(ati_remote->out_urb); |
410 | 398 | ||
411 | return retval; | 399 | return retval; |
412 | } | 400 | } |
413 | 401 | ||
@@ -419,15 +407,15 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | |||
419 | int i; | 407 | int i; |
420 | 408 | ||
421 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { | 409 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { |
422 | /* | 410 | /* |
423 | * Decide if the table entry matches the remote input. | 411 | * Decide if the table entry matches the remote input. |
424 | */ | 412 | */ |
425 | if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && | 413 | if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && |
426 | ((((ati_remote_tbl[i].data1 >> 4) - | 414 | ((((ati_remote_tbl[i].data1 >> 4) - |
427 | (d1 >> 4) + rem) & 0x0f) == 0x0f) && | 415 | (d1 >> 4) + rem) & 0x0f) == 0x0f) && |
428 | (ati_remote_tbl[i].data2 == d2)) | 416 | (ati_remote_tbl[i].data2 == d2)) |
429 | return i; | 417 | return i; |
430 | 418 | ||
431 | } | 419 | } |
432 | return -1; | 420 | return -1; |
433 | } | 421 | } |
@@ -435,16 +423,16 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | |||
435 | /* | 423 | /* |
436 | * ati_remote_report_input | 424 | * ati_remote_report_input |
437 | */ | 425 | */ |
438 | static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | 426 | static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) |
439 | { | 427 | { |
440 | struct ati_remote *ati_remote = urb->context; | 428 | struct ati_remote *ati_remote = urb->context; |
441 | unsigned char *data= ati_remote->inbuf; | 429 | unsigned char *data= ati_remote->inbuf; |
442 | struct input_dev *dev = &ati_remote->idev; | 430 | struct input_dev *dev = &ati_remote->idev; |
443 | int index, acc; | 431 | int index, acc; |
444 | int remote_num; | 432 | int remote_num; |
445 | 433 | ||
446 | /* Deal with strange looking inputs */ | 434 | /* Deal with strange looking inputs */ |
447 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || | 435 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || |
448 | ((data[3] & 0x0f) != 0x00) ) { | 436 | ((data[3] & 0x0f) != 0x00) ) { |
449 | ati_remote_dump(data, urb->actual_length); | 437 | ati_remote_dump(data, urb->actual_length); |
450 | return; | 438 | return; |
@@ -453,7 +441,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
453 | /* Mask unwanted remote channels. */ | 441 | /* Mask unwanted remote channels. */ |
454 | /* note: remote_num is 0-based, channel 1 on remote == 0 here */ | 442 | /* note: remote_num is 0-based, channel 1 on remote == 0 here */ |
455 | remote_num = (data[3] >> 4) & 0x0f; | 443 | remote_num = (data[3] >> 4) & 0x0f; |
456 | if (channel_mask & (1 << (remote_num + 1))) { | 444 | if (channel_mask & (1 << (remote_num + 1))) { |
457 | dbginfo(&ati_remote->interface->dev, | 445 | dbginfo(&ati_remote->interface->dev, |
458 | "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", | 446 | "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", |
459 | remote_num, data[1], data[2], channel_mask); | 447 | remote_num, data[1], data[2], channel_mask); |
@@ -463,37 +451,36 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
463 | /* Look up event code index in translation table */ | 451 | /* Look up event code index in translation table */ |
464 | index = ati_remote_event_lookup(remote_num, data[1], data[2]); | 452 | index = ati_remote_event_lookup(remote_num, data[1], data[2]); |
465 | if (index < 0) { | 453 | if (index < 0) { |
466 | dev_warn(&ati_remote->interface->dev, | 454 | dev_warn(&ati_remote->interface->dev, |
467 | "Unknown input from channel 0x%02x: data %02x,%02x\n", | 455 | "Unknown input from channel 0x%02x: data %02x,%02x\n", |
468 | remote_num, data[1], data[2]); | 456 | remote_num, data[1], data[2]); |
469 | return; | 457 | return; |
470 | } | 458 | } |
471 | dbginfo(&ati_remote->interface->dev, | 459 | dbginfo(&ati_remote->interface->dev, |
472 | "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", | 460 | "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", |
473 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); | 461 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); |
474 | 462 | ||
475 | if (ati_remote_tbl[index].kind == KIND_LITERAL) { | 463 | if (ati_remote_tbl[index].kind == KIND_LITERAL) { |
476 | input_regs(dev, regs); | 464 | input_regs(dev, regs); |
477 | input_event(dev, ati_remote_tbl[index].type, | 465 | input_event(dev, ati_remote_tbl[index].type, |
478 | ati_remote_tbl[index].code, | 466 | ati_remote_tbl[index].code, |
479 | ati_remote_tbl[index].value); | 467 | ati_remote_tbl[index].value); |
480 | input_sync(dev); | 468 | input_sync(dev); |
481 | 469 | ||
482 | ati_remote->old_jiffies = jiffies; | 470 | ati_remote->old_jiffies = jiffies; |
483 | return; | 471 | return; |
484 | } | 472 | } |
485 | 473 | ||
486 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { | 474 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { |
487 | /* Filter duplicate events which happen "too close" together. */ | 475 | /* Filter duplicate events which happen "too close" together. */ |
488 | if ((ati_remote->old_data[0] == data[1]) && | 476 | if ((ati_remote->old_data[0] == data[1]) && |
489 | (ati_remote->old_data[1] == data[2]) && | 477 | (ati_remote->old_data[1] == data[2]) && |
490 | ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { | 478 | ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { |
491 | ati_remote->repeat_count++; | 479 | ati_remote->repeat_count++; |
492 | } | 480 | } else { |
493 | else { | ||
494 | ati_remote->repeat_count = 0; | 481 | ati_remote->repeat_count = 0; |
495 | } | 482 | } |
496 | 483 | ||
497 | ati_remote->old_data[0] = data[1]; | 484 | ati_remote->old_data[0] = data[1]; |
498 | ati_remote->old_data[1] = data[2]; | 485 | ati_remote->old_data[1] = data[2]; |
499 | ati_remote->old_jiffies = jiffies; | 486 | ati_remote->old_jiffies = jiffies; |
@@ -501,7 +488,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
501 | if ((ati_remote->repeat_count > 0) | 488 | if ((ati_remote->repeat_count > 0) |
502 | && (ati_remote->repeat_count < 5)) | 489 | && (ati_remote->repeat_count < 5)) |
503 | return; | 490 | return; |
504 | 491 | ||
505 | 492 | ||
506 | input_regs(dev, regs); | 493 | input_regs(dev, regs); |
507 | input_event(dev, ati_remote_tbl[index].type, | 494 | input_event(dev, ati_remote_tbl[index].type, |
@@ -511,13 +498,13 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
511 | input_sync(dev); | 498 | input_sync(dev); |
512 | 499 | ||
513 | return; | 500 | return; |
514 | } | 501 | } |
515 | 502 | ||
516 | /* | 503 | /* |
517 | * Other event kinds are from the directional control pad, and have an | 504 | * Other event kinds are from the directional control pad, and have an |
518 | * acceleration factor applied to them. Without this acceleration, the | 505 | * acceleration factor applied to them. Without this acceleration, the |
519 | * control pad is mostly unusable. | 506 | * control pad is mostly unusable. |
520 | * | 507 | * |
521 | * If elapsed time since last event is > 1/4 second, user "stopped", | 508 | * If elapsed time since last event is > 1/4 second, user "stopped", |
522 | * so reset acceleration. Otherwise, user is probably holding the control | 509 | * so reset acceleration. Otherwise, user is probably holding the control |
523 | * pad down, so we increase acceleration, ramping up over two seconds to | 510 | * pad down, so we increase acceleration, ramping up over two seconds to |
@@ -559,7 +546,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
559 | input_report_rel(dev, REL_Y, acc); | 546 | input_report_rel(dev, REL_Y, acc); |
560 | break; | 547 | break; |
561 | default: | 548 | default: |
562 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", | 549 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", |
563 | ati_remote_tbl[index].kind); | 550 | ati_remote_tbl[index].kind); |
564 | } | 551 | } |
565 | input_sync(dev); | 552 | input_sync(dev); |
@@ -586,12 +573,12 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) | |||
586 | case -ESHUTDOWN: | 573 | case -ESHUTDOWN: |
587 | dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", | 574 | dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", |
588 | __FUNCTION__); | 575 | __FUNCTION__); |
589 | return; | 576 | return; |
590 | default: /* error */ | 577 | default: /* error */ |
591 | dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", | 578 | dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", |
592 | __FUNCTION__, urb->status); | 579 | __FUNCTION__, urb->status); |
593 | } | 580 | } |
594 | 581 | ||
595 | retval = usb_submit_urb(urb, SLAB_ATOMIC); | 582 | retval = usb_submit_urb(urb, SLAB_ATOMIC); |
596 | if (retval) | 583 | if (retval) |
597 | dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", | 584 | dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", |
@@ -603,8 +590,6 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) | |||
603 | */ | 590 | */ |
604 | static void ati_remote_delete(struct ati_remote *ati_remote) | 591 | static void ati_remote_delete(struct ati_remote *ati_remote) |
605 | { | 592 | { |
606 | if (!ati_remote) return; | ||
607 | |||
608 | if (ati_remote->irq_urb) | 593 | if (ati_remote->irq_urb) |
609 | usb_kill_urb(ati_remote->irq_urb); | 594 | usb_kill_urb(ati_remote->irq_urb); |
610 | 595 | ||
@@ -614,16 +599,16 @@ static void ati_remote_delete(struct ati_remote *ati_remote) | |||
614 | input_unregister_device(&ati_remote->idev); | 599 | input_unregister_device(&ati_remote->idev); |
615 | 600 | ||
616 | if (ati_remote->inbuf) | 601 | if (ati_remote->inbuf) |
617 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | 602 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, |
618 | ati_remote->inbuf, ati_remote->inbuf_dma); | 603 | ati_remote->inbuf, ati_remote->inbuf_dma); |
619 | 604 | ||
620 | if (ati_remote->outbuf) | 605 | if (ati_remote->outbuf) |
621 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | 606 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, |
622 | ati_remote->outbuf, ati_remote->outbuf_dma); | 607 | ati_remote->outbuf, ati_remote->outbuf_dma); |
623 | 608 | ||
624 | if (ati_remote->irq_urb) | 609 | if (ati_remote->irq_urb) |
625 | usb_free_urb(ati_remote->irq_urb); | 610 | usb_free_urb(ati_remote->irq_urb); |
626 | 611 | ||
627 | if (ati_remote->out_urb) | 612 | if (ati_remote->out_urb) |
628 | usb_free_urb(ati_remote->out_urb); | 613 | usb_free_urb(ati_remote->out_urb); |
629 | 614 | ||
@@ -636,51 +621,52 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) | |||
636 | int i; | 621 | int i; |
637 | 622 | ||
638 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 623 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); |
639 | idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | | 624 | idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | |
640 | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); | 625 | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); |
641 | idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | 626 | idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); |
642 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) | 627 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) |
643 | if (ati_remote_tbl[i].type == EV_KEY) | 628 | if (ati_remote_tbl[i].type == EV_KEY) |
644 | set_bit(ati_remote_tbl[i].code, idev->keybit); | 629 | set_bit(ati_remote_tbl[i].code, idev->keybit); |
645 | 630 | ||
646 | idev->private = ati_remote; | 631 | idev->private = ati_remote; |
647 | idev->open = ati_remote_open; | 632 | idev->open = ati_remote_open; |
648 | idev->close = ati_remote_close; | 633 | idev->close = ati_remote_close; |
649 | 634 | ||
650 | idev->name = ati_remote->name; | 635 | idev->name = ati_remote->name; |
651 | idev->phys = ati_remote->phys; | 636 | idev->phys = ati_remote->phys; |
652 | 637 | ||
653 | idev->id.bustype = BUS_USB; | 638 | idev->id.bustype = BUS_USB; |
654 | idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); | 639 | idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); |
655 | idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); | 640 | idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); |
656 | idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); | 641 | idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); |
642 | idev->dev = &(ati_remote->udev->dev); | ||
657 | } | 643 | } |
658 | 644 | ||
659 | static int ati_remote_initialize(struct ati_remote *ati_remote) | 645 | static int ati_remote_initialize(struct ati_remote *ati_remote) |
660 | { | 646 | { |
661 | struct usb_device *udev = ati_remote->udev; | 647 | struct usb_device *udev = ati_remote->udev; |
662 | int pipe, maxp; | 648 | int pipe, maxp; |
663 | 649 | ||
664 | init_waitqueue_head(&ati_remote->wait); | 650 | init_waitqueue_head(&ati_remote->wait); |
665 | 651 | ||
666 | /* Set up irq_urb */ | 652 | /* Set up irq_urb */ |
667 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); | 653 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); |
668 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 654 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
669 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | 655 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; |
670 | 656 | ||
671 | usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, | 657 | usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, |
672 | maxp, ati_remote_irq_in, ati_remote, | 658 | maxp, ati_remote_irq_in, ati_remote, |
673 | ati_remote->endpoint_in->bInterval); | 659 | ati_remote->endpoint_in->bInterval); |
674 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; | 660 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; |
675 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 661 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
676 | 662 | ||
677 | /* Set up out_urb */ | 663 | /* Set up out_urb */ |
678 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); | 664 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); |
679 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 665 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
680 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | 666 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; |
681 | 667 | ||
682 | usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, | 668 | usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, |
683 | maxp, ati_remote_irq_out, ati_remote, | 669 | maxp, ati_remote_irq_out, ati_remote, |
684 | ati_remote->endpoint_out->bInterval); | 670 | ati_remote->endpoint_out->bInterval); |
685 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; | 671 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; |
686 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 672 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
@@ -688,11 +674,11 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) | |||
688 | /* send initialization strings */ | 674 | /* send initialization strings */ |
689 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || | 675 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || |
690 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { | 676 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { |
691 | dev_err(&ati_remote->interface->dev, | 677 | dev_err(&ati_remote->interface->dev, |
692 | "Initializing ati_remote hardware failed.\n"); | 678 | "Initializing ati_remote hardware failed.\n"); |
693 | return 1; | 679 | return 1; |
694 | } | 680 | } |
695 | 681 | ||
696 | return 0; | 682 | return 0; |
697 | } | 683 | } |
698 | 684 | ||
@@ -769,7 +755,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
769 | 755 | ||
770 | if (!strlen(ati_remote->name)) | 756 | if (!strlen(ati_remote->name)) |
771 | sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", | 757 | sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", |
772 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), | 758 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), |
773 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); | 759 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); |
774 | 760 | ||
775 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ | 761 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ |
@@ -781,11 +767,11 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
781 | ati_remote_input_init(ati_remote); | 767 | ati_remote_input_init(ati_remote); |
782 | input_register_device(&ati_remote->idev); | 768 | input_register_device(&ati_remote->idev); |
783 | 769 | ||
784 | dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", | 770 | dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", |
785 | ati_remote->name, path); | 771 | ati_remote->name, path); |
786 | 772 | ||
787 | usb_set_intfdata(interface, ati_remote); | 773 | usb_set_intfdata(interface, ati_remote); |
788 | 774 | ||
789 | error: | 775 | error: |
790 | if (retval) | 776 | if (retval) |
791 | ati_remote_delete(ati_remote); | 777 | ati_remote_delete(ati_remote); |
@@ -800,18 +786,14 @@ static void ati_remote_disconnect(struct usb_interface *interface) | |||
800 | { | 786 | { |
801 | struct ati_remote *ati_remote; | 787 | struct ati_remote *ati_remote; |
802 | 788 | ||
803 | down(&disconnect_sem); | ||
804 | |||
805 | ati_remote = usb_get_intfdata(interface); | 789 | ati_remote = usb_get_intfdata(interface); |
806 | usb_set_intfdata(interface, NULL); | 790 | usb_set_intfdata(interface, NULL); |
807 | if (!ati_remote) { | 791 | if (!ati_remote) { |
808 | warn("%s - null device?\n", __FUNCTION__); | 792 | warn("%s - null device?\n", __FUNCTION__); |
809 | return; | 793 | return; |
810 | } | 794 | } |
811 | |||
812 | ati_remote_delete(ati_remote); | ||
813 | 795 | ||
814 | up(&disconnect_sem); | 796 | ati_remote_delete(ati_remote); |
815 | } | 797 | } |
816 | 798 | ||
817 | /* | 799 | /* |
@@ -820,7 +802,7 @@ static void ati_remote_disconnect(struct usb_interface *interface) | |||
820 | static int __init ati_remote_init(void) | 802 | static int __init ati_remote_init(void) |
821 | { | 803 | { |
822 | int result; | 804 | int result; |
823 | 805 | ||
824 | result = usb_register(&ati_remote_driver); | 806 | result = usb_register(&ati_remote_driver); |
825 | if (result) | 807 | if (result) |
826 | err("usb_register error #%d\n", result); | 808 | err("usb_register error #%d\n", result); |
@@ -838,8 +820,8 @@ static void __exit ati_remote_exit(void) | |||
838 | usb_deregister(&ati_remote_driver); | 820 | usb_deregister(&ati_remote_driver); |
839 | } | 821 | } |
840 | 822 | ||
841 | /* | 823 | /* |
842 | * module specification | 824 | * module specification |
843 | */ | 825 | */ |
844 | 826 | ||
845 | module_init(ati_remote_init); | 827 | module_init(ati_remote_init); |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 740dec1f521d..100b49bd1d3e 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -232,7 +232,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign | |||
232 | report->size += parser->global.report_size * parser->global.report_count; | 232 | report->size += parser->global.report_size * parser->global.report_count; |
233 | 233 | ||
234 | if (!parser->local.usage_index) /* Ignore padding fields */ | 234 | if (!parser->local.usage_index) /* Ignore padding fields */ |
235 | return 0; | 235 | return 0; |
236 | 236 | ||
237 | usages = max_t(int, parser->local.usage_index, parser->global.report_count); | 237 | usages = max_t(int, parser->local.usage_index, parser->global.report_count); |
238 | 238 | ||
@@ -765,7 +765,7 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n) | |||
765 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) | 765 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) |
766 | { | 766 | { |
767 | report += (offset >> 5) << 2; offset &= 31; | 767 | report += (offset >> 5) << 2; offset &= 31; |
768 | return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1); | 768 | return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1); |
769 | } | 769 | } |
770 | 770 | ||
771 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) | 771 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) |
@@ -1233,6 +1233,13 @@ int hid_wait_io(struct hid_device *hid) | |||
1233 | return 0; | 1233 | return 0; |
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) | ||
1237 | { | ||
1238 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
1239 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, | ||
1240 | ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
1241 | } | ||
1242 | |||
1236 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, | 1243 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, |
1237 | unsigned char type, void *buf, int size) | 1244 | unsigned char type, void *buf, int size) |
1238 | { | 1245 | { |
@@ -1301,10 +1308,6 @@ void hid_init_reports(struct hid_device *hid) | |||
1301 | 1308 | ||
1302 | if (err) | 1309 | if (err) |
1303 | warn("timeout initializing reports\n"); | 1310 | warn("timeout initializing reports\n"); |
1304 | |||
1305 | usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0), | ||
1306 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, | ||
1307 | hid->ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
1308 | } | 1311 | } |
1309 | 1312 | ||
1310 | #define USB_VENDOR_ID_WACOM 0x056a | 1313 | #define USB_VENDOR_ID_WACOM 0x056a |
@@ -1318,6 +1321,10 @@ void hid_init_reports(struct hid_device *hid) | |||
1318 | #define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 | 1321 | #define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 |
1319 | #define USB_DEVICE_ID_WACOM_CINTIQ 0x003F | 1322 | #define USB_DEVICE_ID_WACOM_CINTIQ 0x003F |
1320 | 1323 | ||
1324 | #define USB_VENDOR_ID_ACECAD 0x0460 | ||
1325 | #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 | ||
1326 | #define USB_DEVICE_ID_ACECAD_302 0x0008 | ||
1327 | |||
1321 | #define USB_VENDOR_ID_KBGEAR 0x084e | 1328 | #define USB_VENDOR_ID_KBGEAR 0x084e |
1322 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 | 1329 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 |
1323 | 1330 | ||
@@ -1502,6 +1509,9 @@ static struct hid_blacklist { | |||
1502 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1509 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1503 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1510 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1504 | 1511 | ||
1512 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, | ||
1513 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, | ||
1514 | |||
1505 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, | 1515 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, |
1506 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, | 1516 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, |
1507 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, | 1517 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, |
@@ -1590,6 +1600,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1590 | return NULL; | 1600 | return NULL; |
1591 | } | 1601 | } |
1592 | 1602 | ||
1603 | hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); | ||
1604 | |||
1593 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { | 1605 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { |
1594 | dbg("reading report descriptor failed"); | 1606 | dbg("reading report descriptor failed"); |
1595 | kfree(rdesc); | 1607 | kfree(rdesc); |
@@ -1635,7 +1647,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1635 | /* Change the polling interval of mice. */ | 1647 | /* Change the polling interval of mice. */ |
1636 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) | 1648 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) |
1637 | interval = hid_mousepoll_interval; | 1649 | interval = hid_mousepoll_interval; |
1638 | 1650 | ||
1639 | if (endpoint->bEndpointAddress & USB_DIR_IN) { | 1651 | if (endpoint->bEndpointAddress & USB_DIR_IN) { |
1640 | if (hid->urbin) | 1652 | if (hid->urbin) |
1641 | continue; | 1653 | continue; |
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h index 2b91705740a7..52437e5e2e78 100644 --- a/drivers/usb/input/hid-debug.h +++ b/drivers/usb/input/hid-debug.h | |||
@@ -67,7 +67,7 @@ static const struct hid_usage_entry hid_usage_table[] = { | |||
67 | {0, 0x44, "Vbry"}, | 67 | {0, 0x44, "Vbry"}, |
68 | {0, 0x45, "Vbrz"}, | 68 | {0, 0x45, "Vbrz"}, |
69 | {0, 0x46, "Vno"}, | 69 | {0, 0x46, "Vno"}, |
70 | {0, 0x80, "SystemControl"}, | 70 | {0, 0x80, "SystemControl"}, |
71 | {0, 0x81, "SystemPowerDown"}, | 71 | {0, 0x81, "SystemPowerDown"}, |
72 | {0, 0x82, "SystemSleep"}, | 72 | {0, 0x82, "SystemSleep"}, |
73 | {0, 0x83, "SystemWakeUp"}, | 73 | {0, 0x83, "SystemWakeUp"}, |
@@ -347,7 +347,7 @@ __inline__ static void tab(int n) { | |||
347 | 347 | ||
348 | static void hid_dump_field(struct hid_field *field, int n) { | 348 | static void hid_dump_field(struct hid_field *field, int n) { |
349 | int j; | 349 | int j; |
350 | 350 | ||
351 | if (field->physical) { | 351 | if (field->physical) { |
352 | tab(n); | 352 | tab(n); |
353 | printk("Physical("); | 353 | printk("Physical("); |
@@ -408,7 +408,7 @@ static void hid_dump_field(struct hid_field *field, int n) { | |||
408 | printk("%s", units[sys][i]); | 408 | printk("%s", units[sys][i]); |
409 | if(nibble != 1) { | 409 | if(nibble != 1) { |
410 | /* This is a _signed_ nibble(!) */ | 410 | /* This is a _signed_ nibble(!) */ |
411 | 411 | ||
412 | int val = nibble & 0x7; | 412 | int val = nibble & 0x7; |
413 | if(nibble & 0x08) | 413 | if(nibble & 0x08) |
414 | val = -((0x7 & ~val) +1); | 414 | val = -((0x7 & ~val) +1); |
@@ -443,7 +443,7 @@ static void __attribute__((unused)) hid_dump_device(struct hid_device *device) { | |||
443 | struct list_head *list; | 443 | struct list_head *list; |
444 | unsigned i,k; | 444 | unsigned i,k; |
445 | static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; | 445 | static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; |
446 | 446 | ||
447 | for (i = 0; i < HID_REPORT_TYPES; i++) { | 447 | for (i = 0; i < HID_REPORT_TYPES; i++) { |
448 | report_enum = device->report_enum + i; | 448 | report_enum = device->report_enum + i; |
449 | list = report_enum->report_list.next; | 449 | list = report_enum->report_list.next; |
@@ -664,8 +664,8 @@ static char *keys[KEY_MAX + 1] = { | |||
664 | static char *relatives[REL_MAX + 1] = { | 664 | static char *relatives[REL_MAX + 1] = { |
665 | [REL_X] = "X", [REL_Y] = "Y", | 665 | [REL_X] = "X", [REL_Y] = "Y", |
666 | [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", | 666 | [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", |
667 | [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", | 667 | [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", |
668 | [REL_MISC] = "Misc", | 668 | [REL_MISC] = "Misc", |
669 | }; | 669 | }; |
670 | 670 | ||
671 | static char *absolutes[ABS_MAX + 1] = { | 671 | static char *absolutes[ABS_MAX + 1] = { |
@@ -690,9 +690,9 @@ static char *misc[MSC_MAX + 1] = { | |||
690 | }; | 690 | }; |
691 | 691 | ||
692 | static char *leds[LED_MAX + 1] = { | 692 | static char *leds[LED_MAX + 1] = { |
693 | [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", | 693 | [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", |
694 | [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", | 694 | [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", |
695 | [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", | 695 | [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", |
696 | [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", | 696 | [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", |
697 | [LED_MISC] = "Misc", | 697 | [LED_MISC] = "Misc", |
698 | }; | 698 | }; |
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 5553c3553e9d..9ac1e9095334 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c | |||
@@ -164,7 +164,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
164 | case HID_GD_X: case HID_GD_Y: case HID_GD_Z: | 164 | case HID_GD_X: case HID_GD_Y: case HID_GD_Z: |
165 | case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: | 165 | case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: |
166 | case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: | 166 | case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: |
167 | if (field->flags & HID_MAIN_ITEM_RELATIVE) | 167 | if (field->flags & HID_MAIN_ITEM_RELATIVE) |
168 | map_rel(usage->hid & 0xf); | 168 | map_rel(usage->hid & 0xf); |
169 | else | 169 | else |
170 | map_abs(usage->hid & 0xf); | 170 | map_abs(usage->hid & 0xf); |
@@ -297,7 +297,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
297 | case HID_UP_MSVENDOR: | 297 | case HID_UP_MSVENDOR: |
298 | 298 | ||
299 | goto ignore; | 299 | goto ignore; |
300 | 300 | ||
301 | case HID_UP_PID: | 301 | case HID_UP_PID: |
302 | 302 | ||
303 | set_bit(EV_FF, input->evbit); | 303 | set_bit(EV_FF, input->evbit); |
@@ -349,7 +349,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
349 | goto ignore; | 349 | goto ignore; |
350 | 350 | ||
351 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && | 351 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && |
352 | (usage->type == EV_REL) && (usage->code == REL_WHEEL)) | 352 | (usage->type == EV_REL) && (usage->code == REL_WHEEL)) |
353 | set_bit(REL_HWHEEL, bit); | 353 | set_bit(REL_HWHEEL, bit); |
354 | 354 | ||
355 | if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) | 355 | if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) |
@@ -365,11 +365,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
365 | a = field->logical_minimum = 0; | 365 | a = field->logical_minimum = 0; |
366 | b = field->logical_maximum = 255; | 366 | b = field->logical_maximum = 255; |
367 | } | 367 | } |
368 | 368 | ||
369 | if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) | 369 | if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) |
370 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); | 370 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); |
371 | else input_set_abs_params(input, usage->code, a, b, 0, 0); | 371 | else input_set_abs_params(input, usage->code, a, b, 0, 0); |
372 | 372 | ||
373 | } | 373 | } |
374 | 374 | ||
375 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 375 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
@@ -420,7 +420,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
420 | return; | 420 | return; |
421 | } | 421 | } |
422 | 422 | ||
423 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 423 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
424 | int hat_dir = usage->hat_dir; | 424 | int hat_dir = usage->hat_dir; |
425 | if (!hat_dir) | 425 | if (!hat_dir) |
426 | hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; | 426 | hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; |
@@ -551,7 +551,7 @@ int hidinput_connect(struct hid_device *hid) | |||
551 | for (i = 0; i < hid->maxcollection; i++) | 551 | for (i = 0; i < hid->maxcollection; i++) |
552 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION || | 552 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION || |
553 | hid->collection[i].type == HID_COLLECTION_PHYSICAL) | 553 | hid->collection[i].type == HID_COLLECTION_PHYSICAL) |
554 | if (IS_INPUT_APPLICATION(hid->collection[i].usage)) | 554 | if (IS_INPUT_APPLICATION(hid->collection[i].usage)) |
555 | break; | 555 | break; |
556 | 556 | ||
557 | if (i == hid->maxcollection) | 557 | if (i == hid->maxcollection) |
@@ -592,7 +592,7 @@ int hidinput_connect(struct hid_device *hid) | |||
592 | for (j = 0; j < report->field[i]->maxusage; j++) | 592 | for (j = 0; j < report->field[i]->maxusage; j++) |
593 | hidinput_configure_usage(hidinput, report->field[i], | 593 | hidinput_configure_usage(hidinput, report->field[i], |
594 | report->field[i]->usage + j); | 594 | report->field[i]->usage + j); |
595 | 595 | ||
596 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) { | 596 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) { |
597 | /* This will leave hidinput NULL, so that it | 597 | /* This will leave hidinput NULL, so that it |
598 | * allocates another one if we have more inputs on | 598 | * allocates another one if we have more inputs on |
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c index 0d7404bab92f..0c4c77aa31ea 100644 --- a/drivers/usb/input/hid-lgff.c +++ b/drivers/usb/input/hid-lgff.c | |||
@@ -94,7 +94,7 @@ struct lgff_device { | |||
94 | isn't really necessary */ | 94 | isn't really necessary */ |
95 | 95 | ||
96 | unsigned long flags[1]; /* Contains various information about the | 96 | unsigned long flags[1]; /* Contains various information about the |
97 | state of the driver for this device */ | 97 | state of the driver for this device */ |
98 | 98 | ||
99 | struct timer_list timer; | 99 | struct timer_list timer; |
100 | }; | 100 | }; |
@@ -234,7 +234,7 @@ static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) | |||
234 | kfree(ret); | 234 | kfree(ret); |
235 | return NULL; | 235 | return NULL; |
236 | } | 236 | } |
237 | memset(ret->field[0]->value, 0, sizeof(s32[8])); | 237 | memset(ret->field[0]->value, 0, sizeof(s32[8])); |
238 | 238 | ||
239 | return ret; | 239 | return ret; |
240 | } | 240 | } |
@@ -295,11 +295,11 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, | |||
295 | unsigned long flags; | 295 | unsigned long flags; |
296 | 296 | ||
297 | if (type != EV_FF) return -EINVAL; | 297 | if (type != EV_FF) return -EINVAL; |
298 | if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; | 298 | if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; |
299 | if (value < 0) return -EINVAL; | 299 | if (value < 0) return -EINVAL; |
300 | 300 | ||
301 | spin_lock_irqsave(&lgff->lock, flags); | 301 | spin_lock_irqsave(&lgff->lock, flags); |
302 | 302 | ||
303 | if (value > 0) { | 303 | if (value > 0) { |
304 | if (test_bit(EFFECT_STARTED, effect->flags)) { | 304 | if (test_bit(EFFECT_STARTED, effect->flags)) { |
305 | spin_unlock_irqrestore(&lgff->lock, flags); | 305 | spin_unlock_irqrestore(&lgff->lock, flags); |
@@ -345,7 +345,7 @@ static int hid_lgff_flush(struct input_dev *dev, struct file *file) | |||
345 | and perform ioctls on the same fd all at the same time */ | 345 | and perform ioctls on the same fd all at the same time */ |
346 | if ( current->pid == lgff->effects[i].owner | 346 | if ( current->pid == lgff->effects[i].owner |
347 | && test_bit(EFFECT_USED, lgff->effects[i].flags)) { | 347 | && test_bit(EFFECT_USED, lgff->effects[i].flags)) { |
348 | 348 | ||
349 | if (hid_lgff_erase(dev, i)) | 349 | if (hid_lgff_erase(dev, i)) |
350 | warn("erase effect %d failed", i); | 350 | warn("erase effect %d failed", i); |
351 | } | 351 | } |
@@ -378,7 +378,7 @@ static int hid_lgff_upload_effect(struct input_dev* input, | |||
378 | struct lgff_effect new; | 378 | struct lgff_effect new; |
379 | int id; | 379 | int id; |
380 | unsigned long flags; | 380 | unsigned long flags; |
381 | 381 | ||
382 | dbg("ioctl rumble"); | 382 | dbg("ioctl rumble"); |
383 | 383 | ||
384 | if (!test_bit(effect->type, input->ffbit)) return -EINVAL; | 384 | if (!test_bit(effect->type, input->ffbit)) return -EINVAL; |
@@ -441,7 +441,7 @@ static void hid_lgff_timer(unsigned long timer_data) | |||
441 | 441 | ||
442 | spin_lock_irqsave(&lgff->lock, flags); | 442 | spin_lock_irqsave(&lgff->lock, flags); |
443 | 443 | ||
444 | for (i=0; i<LGFF_EFFECTS; ++i) { | 444 | for (i=0; i<LGFF_EFFECTS; ++i) { |
445 | struct lgff_effect* effect = lgff->effects +i; | 445 | struct lgff_effect* effect = lgff->effects +i; |
446 | 446 | ||
447 | if (test_bit(EFFECT_PLAYING, effect->flags)) { | 447 | if (test_bit(EFFECT_PLAYING, effect->flags)) { |
@@ -491,7 +491,7 @@ static void hid_lgff_timer(unsigned long timer_data) | |||
491 | set_bit(EFFECT_PLAYING, lgff->effects[i].flags); | 491 | set_bit(EFFECT_PLAYING, lgff->effects[i].flags); |
492 | } | 492 | } |
493 | } | 493 | } |
494 | } | 494 | } |
495 | 495 | ||
496 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | 496 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff |
497 | 497 | ||
@@ -524,5 +524,5 @@ static void hid_lgff_timer(unsigned long timer_data) | |||
524 | add_timer(&lgff->timer); | 524 | add_timer(&lgff->timer); |
525 | } | 525 | } |
526 | 526 | ||
527 | spin_unlock_irqrestore(&lgff->lock, flags); | 527 | spin_unlock_irqrestore(&lgff->lock, flags); |
528 | } | 528 | } |
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 6d9329c698d9..c1b6b69bc4a4 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
@@ -118,7 +118,7 @@ struct hid_item { | |||
118 | #define HID_MAIN_ITEM_CONSTANT 0x001 | 118 | #define HID_MAIN_ITEM_CONSTANT 0x001 |
119 | #define HID_MAIN_ITEM_VARIABLE 0x002 | 119 | #define HID_MAIN_ITEM_VARIABLE 0x002 |
120 | #define HID_MAIN_ITEM_RELATIVE 0x004 | 120 | #define HID_MAIN_ITEM_RELATIVE 0x004 |
121 | #define HID_MAIN_ITEM_WRAP 0x008 | 121 | #define HID_MAIN_ITEM_WRAP 0x008 |
122 | #define HID_MAIN_ITEM_NONLINEAR 0x010 | 122 | #define HID_MAIN_ITEM_NONLINEAR 0x010 |
123 | #define HID_MAIN_ITEM_NO_PREFERRED 0x020 | 123 | #define HID_MAIN_ITEM_NO_PREFERRED 0x020 |
124 | #define HID_MAIN_ITEM_NULL_STATE 0x040 | 124 | #define HID_MAIN_ITEM_NULL_STATE 0x040 |
@@ -172,14 +172,14 @@ struct hid_item { | |||
172 | #define HID_USAGE_PAGE 0xffff0000 | 172 | #define HID_USAGE_PAGE 0xffff0000 |
173 | 173 | ||
174 | #define HID_UP_UNDEFINED 0x00000000 | 174 | #define HID_UP_UNDEFINED 0x00000000 |
175 | #define HID_UP_GENDESK 0x00010000 | 175 | #define HID_UP_GENDESK 0x00010000 |
176 | #define HID_UP_KEYBOARD 0x00070000 | 176 | #define HID_UP_KEYBOARD 0x00070000 |
177 | #define HID_UP_LED 0x00080000 | 177 | #define HID_UP_LED 0x00080000 |
178 | #define HID_UP_BUTTON 0x00090000 | 178 | #define HID_UP_BUTTON 0x00090000 |
179 | #define HID_UP_ORDINAL 0x000a0000 | 179 | #define HID_UP_ORDINAL 0x000a0000 |
180 | #define HID_UP_CONSUMER 0x000c0000 | 180 | #define HID_UP_CONSUMER 0x000c0000 |
181 | #define HID_UP_DIGITIZER 0x000d0000 | 181 | #define HID_UP_DIGITIZER 0x000d0000 |
182 | #define HID_UP_PID 0x000f0000 | 182 | #define HID_UP_PID 0x000f0000 |
183 | #define HID_UP_HPVENDOR 0xff7f0000 | 183 | #define HID_UP_HPVENDOR 0xff7f0000 |
184 | #define HID_UP_MSVENDOR 0xff000000 | 184 | #define HID_UP_MSVENDOR 0xff000000 |
185 | 185 | ||
@@ -406,7 +406,7 @@ struct hid_device { /* device report descriptor */ | |||
406 | dma_addr_t outbuf_dma; /* Output buffer dma */ | 406 | dma_addr_t outbuf_dma; /* Output buffer dma */ |
407 | spinlock_t outlock; /* Output fifo spinlock */ | 407 | spinlock_t outlock; /* Output fifo spinlock */ |
408 | 408 | ||
409 | unsigned claimed; /* Claimed by hidinput, hiddev? */ | 409 | unsigned claimed; /* Claimed by hidinput, hiddev? */ |
410 | unsigned quirks; /* Various quirks the device can pull on us */ | 410 | unsigned quirks; /* Various quirks the device can pull on us */ |
411 | 411 | ||
412 | struct list_head inputs; /* The list of inputs */ | 412 | struct list_head inputs; /* The list of inputs */ |
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 96b7c9067951..4c13331b5f41 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c | |||
@@ -95,7 +95,7 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | |||
95 | return NULL; | 95 | return NULL; |
96 | rinfo->report_id = ((struct hid_report *) list)->id; | 96 | rinfo->report_id = ((struct hid_report *) list)->id; |
97 | break; | 97 | break; |
98 | 98 | ||
99 | case HID_REPORT_ID_NEXT: | 99 | case HID_REPORT_ID_NEXT: |
100 | list = (struct list_head *) | 100 | list = (struct list_head *) |
101 | report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; | 101 | report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; |
@@ -106,7 +106,7 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | |||
106 | return NULL; | 106 | return NULL; |
107 | rinfo->report_id = ((struct hid_report *) list)->id; | 107 | rinfo->report_id = ((struct hid_report *) list)->id; |
108 | break; | 108 | break; |
109 | 109 | ||
110 | default: | 110 | default: |
111 | return NULL; | 111 | return NULL; |
112 | } | 112 | } |
@@ -158,7 +158,7 @@ static void hiddev_send_event(struct hid_device *hid, | |||
158 | if (uref->field_index != HID_FIELD_INDEX_NONE || | 158 | if (uref->field_index != HID_FIELD_INDEX_NONE || |
159 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | 159 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { |
160 | list->buffer[list->head] = *uref; | 160 | list->buffer[list->head] = *uref; |
161 | list->head = (list->head + 1) & | 161 | list->head = (list->head + 1) & |
162 | (HIDDEV_BUFFER_SIZE - 1); | 162 | (HIDDEV_BUFFER_SIZE - 1); |
163 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | 163 | kill_fasync(&list->fasync, SIGIO, POLL_IN); |
164 | } | 164 | } |
@@ -179,9 +179,9 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | |||
179 | unsigned type = field->report_type; | 179 | unsigned type = field->report_type; |
180 | struct hiddev_usage_ref uref; | 180 | struct hiddev_usage_ref uref; |
181 | 181 | ||
182 | uref.report_type = | 182 | uref.report_type = |
183 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | 183 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : |
184 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | 184 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : |
185 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | 185 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); |
186 | uref.report_id = field->report->id; | 186 | uref.report_id = field->report->id; |
187 | uref.field_index = field->index; | 187 | uref.field_index = field->index; |
@@ -199,9 +199,9 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) | |||
199 | struct hiddev_usage_ref uref; | 199 | struct hiddev_usage_ref uref; |
200 | 200 | ||
201 | memset(&uref, 0, sizeof(uref)); | 201 | memset(&uref, 0, sizeof(uref)); |
202 | uref.report_type = | 202 | uref.report_type = |
203 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | 203 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : |
204 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | 204 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : |
205 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | 205 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); |
206 | uref.report_id = report->id; | 206 | uref.report_id = report->id; |
207 | uref.field_index = HID_FIELD_INDEX_NONE; | 207 | uref.field_index = HID_FIELD_INDEX_NONE; |
@@ -236,7 +236,7 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
236 | *listptr = (*listptr)->next; | 236 | *listptr = (*listptr)->next; |
237 | 237 | ||
238 | if (!--list->hiddev->open) { | 238 | if (!--list->hiddev->open) { |
239 | if (list->hiddev->exist) | 239 | if (list->hiddev->exist) |
240 | hid_close(list->hiddev->hid); | 240 | hid_close(list->hiddev->hid); |
241 | else | 241 | else |
242 | kfree(list->hiddev); | 242 | kfree(list->hiddev); |
@@ -303,7 +303,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
303 | if (list->head == list->tail) { | 303 | if (list->head == list->tail) { |
304 | add_wait_queue(&list->hiddev->wait, &wait); | 304 | add_wait_queue(&list->hiddev->wait, &wait); |
305 | set_current_state(TASK_INTERRUPTIBLE); | 305 | set_current_state(TASK_INTERRUPTIBLE); |
306 | 306 | ||
307 | while (list->head == list->tail) { | 307 | while (list->head == list->tail) { |
308 | if (file->f_flags & O_NONBLOCK) { | 308 | if (file->f_flags & O_NONBLOCK) { |
309 | retval = -EAGAIN; | 309 | retval = -EAGAIN; |
@@ -317,7 +317,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
317 | retval = -EIO; | 317 | retval = -EIO; |
318 | break; | 318 | break; |
319 | } | 319 | } |
320 | 320 | ||
321 | schedule(); | 321 | schedule(); |
322 | } | 322 | } |
323 | 323 | ||
@@ -329,7 +329,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
329 | return retval; | 329 | return retval; |
330 | 330 | ||
331 | 331 | ||
332 | while (list->head != list->tail && | 332 | while (list->head != list->tail && |
333 | retval + event_size <= count) { | 333 | retval + event_size <= count) { |
334 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { | 334 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { |
335 | if (list->buffer[list->tail].field_index != | 335 | if (list->buffer[list->tail].field_index != |
@@ -405,10 +405,10 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
405 | return -EINVAL; | 405 | return -EINVAL; |
406 | 406 | ||
407 | for (i = 0; i < hid->maxcollection; i++) | 407 | for (i = 0; i < hid->maxcollection; i++) |
408 | if (hid->collection[i].type == | 408 | if (hid->collection[i].type == |
409 | HID_COLLECTION_APPLICATION && arg-- == 0) | 409 | HID_COLLECTION_APPLICATION && arg-- == 0) |
410 | break; | 410 | break; |
411 | 411 | ||
412 | if (i == hid->maxcollection) | 412 | if (i == hid->maxcollection) |
413 | return -EINVAL; | 413 | return -EINVAL; |
414 | 414 | ||
@@ -562,7 +562,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
562 | if (!uref_multi) | 562 | if (!uref_multi) |
563 | return -ENOMEM; | 563 | return -ENOMEM; |
564 | uref = &uref_multi->uref; | 564 | uref = &uref_multi->uref; |
565 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | 565 | if (copy_from_user(uref, user_arg, sizeof(*uref))) |
566 | goto fault; | 566 | goto fault; |
567 | 567 | ||
568 | rinfo.report_type = uref->report_type; | 568 | rinfo.report_type = uref->report_type; |
@@ -595,7 +595,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
595 | return -ENOMEM; | 595 | return -ENOMEM; |
596 | uref = &uref_multi->uref; | 596 | uref = &uref_multi->uref; |
597 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { | 597 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { |
598 | if (copy_from_user(uref_multi, user_arg, | 598 | if (copy_from_user(uref_multi, user_arg, |
599 | sizeof(*uref_multi))) | 599 | sizeof(*uref_multi))) |
600 | goto fault; | 600 | goto fault; |
601 | } else { | 601 | } else { |
@@ -603,7 +603,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
603 | goto fault; | 603 | goto fault; |
604 | } | 604 | } |
605 | 605 | ||
606 | if (cmd != HIDIOCGUSAGE && | 606 | if (cmd != HIDIOCGUSAGE && |
607 | cmd != HIDIOCGUSAGES && | 607 | cmd != HIDIOCGUSAGES && |
608 | uref->report_type == HID_REPORT_TYPE_INPUT) | 608 | uref->report_type == HID_REPORT_TYPE_INPUT) |
609 | goto inval; | 609 | goto inval; |
@@ -651,16 +651,16 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
651 | return field->usage[uref->usage_index].collection_index; | 651 | return field->usage[uref->usage_index].collection_index; |
652 | case HIDIOCGUSAGES: | 652 | case HIDIOCGUSAGES: |
653 | for (i = 0; i < uref_multi->num_values; i++) | 653 | for (i = 0; i < uref_multi->num_values; i++) |
654 | uref_multi->values[i] = | 654 | uref_multi->values[i] = |
655 | field->value[uref->usage_index + i]; | 655 | field->value[uref->usage_index + i]; |
656 | if (copy_to_user(user_arg, uref_multi, | 656 | if (copy_to_user(user_arg, uref_multi, |
657 | sizeof(*uref_multi))) | 657 | sizeof(*uref_multi))) |
658 | goto fault; | 658 | goto fault; |
659 | goto goodreturn; | 659 | goto goodreturn; |
660 | case HIDIOCSUSAGES: | 660 | case HIDIOCSUSAGES: |
661 | for (i = 0; i < uref_multi->num_values; i++) | 661 | for (i = 0; i < uref_multi->num_values; i++) |
662 | field->value[uref->usage_index + i] = | 662 | field->value[uref->usage_index + i] = |
663 | uref_multi->values[i]; | 663 | uref_multi->values[i]; |
664 | goto goodreturn; | 664 | goto goodreturn; |
665 | } | 665 | } |
666 | 666 | ||
@@ -670,7 +670,7 @@ goodreturn: | |||
670 | fault: | 670 | fault: |
671 | kfree(uref_multi); | 671 | kfree(uref_multi); |
672 | return -EFAULT; | 672 | return -EFAULT; |
673 | inval: | 673 | inval: |
674 | kfree(uref_multi); | 674 | kfree(uref_multi); |
675 | return -EINVAL; | 675 | return -EINVAL; |
676 | 676 | ||
@@ -734,7 +734,7 @@ static struct usb_class_driver hiddev_class = { | |||
734 | .name = "usb/hid/hiddev%d", | 734 | .name = "usb/hid/hiddev%d", |
735 | .fops = &hiddev_fops, | 735 | .fops = &hiddev_fops, |
736 | .mode = S_IFCHR | S_IRUGO | S_IWUSR, | 736 | .mode = S_IFCHR | S_IRUGO | S_IWUSR, |
737 | .minor_base = HIDDEV_MINOR_BASE, | 737 | .minor_base = HIDDEV_MINOR_BASE, |
738 | }; | 738 | }; |
739 | 739 | ||
740 | /* | 740 | /* |
@@ -747,7 +747,7 @@ int hiddev_connect(struct hid_device *hid) | |||
747 | int retval; | 747 | int retval; |
748 | 748 | ||
749 | for (i = 0; i < hid->maxcollection; i++) | 749 | for (i = 0; i < hid->maxcollection; i++) |
750 | if (hid->collection[i].type == | 750 | if (hid->collection[i].type == |
751 | HID_COLLECTION_APPLICATION && | 751 | HID_COLLECTION_APPLICATION && |
752 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) | 752 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) |
753 | break; | 753 | break; |
@@ -755,11 +755,11 @@ int hiddev_connect(struct hid_device *hid) | |||
755 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) | 755 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) |
756 | return -1; | 756 | return -1; |
757 | 757 | ||
758 | if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) | 758 | if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) |
759 | return -1; | 759 | return -1; |
760 | memset(hiddev, 0, sizeof(struct hiddev)); | 760 | memset(hiddev, 0, sizeof(struct hiddev)); |
761 | 761 | ||
762 | retval = usb_register_dev(hid->intf, &hiddev_class); | 762 | retval = usb_register_dev(hid->intf, &hiddev_class); |
763 | if (retval) { | 763 | if (retval) { |
764 | err("Not able to get a minor for this device."); | 764 | err("Not able to get a minor for this device."); |
765 | kfree(hiddev); | 765 | kfree(hiddev); |
@@ -768,12 +768,12 @@ int hiddev_connect(struct hid_device *hid) | |||
768 | 768 | ||
769 | init_waitqueue_head(&hiddev->wait); | 769 | init_waitqueue_head(&hiddev->wait); |
770 | 770 | ||
771 | hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | 771 | hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; |
772 | 772 | ||
773 | hiddev->hid = hid; | 773 | hiddev->hid = hid; |
774 | hiddev->exist = 1; | 774 | hiddev->exist = 1; |
775 | 775 | ||
776 | hid->minor = hid->intf->minor; | 776 | hid->minor = hid->intf->minor; |
777 | hid->hiddev = hiddev; | 777 | hid->hiddev = hiddev; |
778 | 778 | ||
779 | return 0; | 779 | return 0; |
@@ -818,7 +818,7 @@ void hiddev_disconnect(struct hid_device *hid) | |||
818 | /* We never attach in this manner, and rely on HID to connect us. This | 818 | /* We never attach in this manner, and rely on HID to connect us. This |
819 | * is why there is no disconnect routine defined in the usb_driver either. | 819 | * is why there is no disconnect routine defined in the usb_driver either. |
820 | */ | 820 | */ |
821 | static int hiddev_usbd_probe(struct usb_interface *intf, | 821 | static int hiddev_usbd_probe(struct usb_interface *intf, |
822 | const struct usb_device_id *hiddev_info) | 822 | const struct usb_device_id *hiddev_info) |
823 | { | 823 | { |
824 | return -ENODEV; | 824 | return -ENODEV; |
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c new file mode 100644 index 000000000000..47dec6a1b344 --- /dev/null +++ b/drivers/usb/input/itmtouch.c | |||
@@ -0,0 +1,268 @@ | |||
1 | /****************************************************************************** | ||
2 | * itmtouch.c -- Driver for ITM touchscreen panel | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of the | ||
7 | * License, or (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | * | ||
18 | * Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>. | ||
19 | * | ||
20 | * Kudos to ITM for providing me with the datasheet for the panel, | ||
21 | * even though it was a day later than I had finished writing this | ||
22 | * driver. | ||
23 | * | ||
24 | * It has meant that I've been able to correct my interpretation of the | ||
25 | * protocol packets however. | ||
26 | * | ||
27 | * CC -- 2003/9/29 | ||
28 | * | ||
29 | * History | ||
30 | * 1.0 & 1.1 2003 (CC) vojtech@suse.cz | ||
31 | * Original version for 2.4.x kernels | ||
32 | * | ||
33 | * 1.2 02/03/2005 (HCE) hc@mivu.no | ||
34 | * Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints. | ||
35 | * Unfortunately no calibration support at this time. | ||
36 | * | ||
37 | * 1.2.1 09/03/2005 (HCE) hc@mivu.no | ||
38 | * Code cleanup and adjusting syntax to start matching kernel standards | ||
39 | * | ||
40 | *****************************************************************************/ | ||
41 | |||
42 | #include <linux/config.h> | ||
43 | |||
44 | #ifdef CONFIG_USB_DEBUG | ||
45 | #define DEBUG | ||
46 | #else | ||
47 | #undef DEBUG | ||
48 | #endif | ||
49 | |||
50 | #include <linux/kernel.h> | ||
51 | #include <linux/slab.h> | ||
52 | #include <linux/input.h> | ||
53 | #include <linux/module.h> | ||
54 | #include <linux/init.h> | ||
55 | #include <linux/usb.h> | ||
56 | |||
57 | /* only an 8 byte buffer necessary for a single packet */ | ||
58 | #define ITM_BUFSIZE 8 | ||
59 | #define PATH_SIZE 64 | ||
60 | |||
61 | #define USB_VENDOR_ID_ITMINC 0x0403 | ||
62 | #define USB_PRODUCT_ID_TOUCHPANEL 0xf9e9 | ||
63 | |||
64 | #define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>" | ||
65 | #define DRIVER_VERSION "v1.2.1" | ||
66 | #define DRIVER_DESC "USB ITM Inc Touch Panel Driver" | ||
67 | #define DRIVER_LICENSE "GPL" | ||
68 | |||
69 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
70 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
71 | MODULE_LICENSE( DRIVER_LICENSE ); | ||
72 | |||
73 | struct itmtouch_dev { | ||
74 | struct usb_device *usbdev; /* usb device */ | ||
75 | struct input_dev inputdev; /* input device */ | ||
76 | struct urb *readurb; /* urb */ | ||
77 | char rbuf[ITM_BUFSIZE]; /* data */ | ||
78 | int users; | ||
79 | char name[128]; | ||
80 | char phys[64]; | ||
81 | }; | ||
82 | |||
83 | static struct usb_device_id itmtouch_ids [] = { | ||
84 | { USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) }, | ||
85 | { } | ||
86 | }; | ||
87 | |||
88 | static void itmtouch_irq(struct urb *urb, struct pt_regs *regs) | ||
89 | { | ||
90 | struct itmtouch_dev * itmtouch = urb->context; | ||
91 | unsigned char *data = urb->transfer_buffer; | ||
92 | struct input_dev *dev = &itmtouch->inputdev; | ||
93 | int retval; | ||
94 | |||
95 | switch (urb->status) { | ||
96 | case 0: | ||
97 | /* success */ | ||
98 | break; | ||
99 | case -ETIMEDOUT: | ||
100 | /* this urb is timing out */ | ||
101 | dbg("%s - urb timed out - was the device unplugged?", | ||
102 | __FUNCTION__); | ||
103 | return; | ||
104 | case -ECONNRESET: | ||
105 | case -ENOENT: | ||
106 | case -ESHUTDOWN: | ||
107 | /* this urb is terminated, clean up */ | ||
108 | dbg("%s - urb shutting down with status: %d", | ||
109 | __FUNCTION__, urb->status); | ||
110 | return; | ||
111 | default: | ||
112 | dbg("%s - nonzero urb status received: %d", | ||
113 | __FUNCTION__, urb->status); | ||
114 | goto exit; | ||
115 | } | ||
116 | |||
117 | input_regs(dev, regs); | ||
118 | |||
119 | /* if pressure has been released, then don't report X/Y */ | ||
120 | if (data[7] & 0x20) { | ||
121 | input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F)); | ||
122 | input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F)); | ||
123 | } | ||
124 | |||
125 | input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F)); | ||
126 | input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20); | ||
127 | input_sync(dev); | ||
128 | |||
129 | exit: | ||
130 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
131 | if (retval) | ||
132 | printk(KERN_ERR "%s - usb_submit_urb failed with result: %d", | ||
133 | __FUNCTION__, retval); | ||
134 | } | ||
135 | |||
136 | static int itmtouch_open(struct input_dev *input) | ||
137 | { | ||
138 | struct itmtouch_dev *itmtouch = input->private; | ||
139 | |||
140 | itmtouch->readurb->dev = itmtouch->usbdev; | ||
141 | |||
142 | if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL)) | ||
143 | return -EIO; | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static void itmtouch_close(struct input_dev *input) | ||
149 | { | ||
150 | struct itmtouch_dev *itmtouch = input->private; | ||
151 | |||
152 | usb_kill_urb(itmtouch->readurb); | ||
153 | } | ||
154 | |||
155 | static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
156 | { | ||
157 | struct itmtouch_dev *itmtouch; | ||
158 | struct usb_host_interface *interface; | ||
159 | struct usb_endpoint_descriptor *endpoint; | ||
160 | struct usb_device *udev = interface_to_usbdev(intf); | ||
161 | unsigned int pipe; | ||
162 | unsigned int maxp; | ||
163 | char path[PATH_SIZE]; | ||
164 | |||
165 | interface = intf->cur_altsetting; | ||
166 | endpoint = &interface->endpoint[0].desc; | ||
167 | |||
168 | if (!(itmtouch = kcalloc(1, sizeof(struct itmtouch_dev), GFP_KERNEL))) { | ||
169 | err("%s - Out of memory.", __FUNCTION__); | ||
170 | return -ENOMEM; | ||
171 | } | ||
172 | |||
173 | itmtouch->usbdev = udev; | ||
174 | |||
175 | itmtouch->inputdev.private = itmtouch; | ||
176 | itmtouch->inputdev.open = itmtouch_open; | ||
177 | itmtouch->inputdev.close = itmtouch_close; | ||
178 | |||
179 | usb_make_path(udev, path, PATH_SIZE); | ||
180 | |||
181 | itmtouch->inputdev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
182 | itmtouch->inputdev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); | ||
183 | itmtouch->inputdev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
184 | |||
185 | itmtouch->inputdev.name = itmtouch->name; | ||
186 | itmtouch->inputdev.phys = itmtouch->phys; | ||
187 | itmtouch->inputdev.id.bustype = BUS_USB; | ||
188 | itmtouch->inputdev.id.vendor = udev->descriptor.idVendor; | ||
189 | itmtouch->inputdev.id.product = udev->descriptor.idProduct; | ||
190 | itmtouch->inputdev.id.version = udev->descriptor.bcdDevice; | ||
191 | itmtouch->inputdev.dev = &intf->dev; | ||
192 | |||
193 | if (!strlen(itmtouch->name)) | ||
194 | sprintf(itmtouch->name, "USB ITM touchscreen"); | ||
195 | |||
196 | /* device limits */ | ||
197 | /* as specified by the ITM datasheet, X and Y are 12bit, | ||
198 | * Z (pressure) is 8 bit. However, the fields are defined up | ||
199 | * to 14 bits for future possible expansion. | ||
200 | */ | ||
201 | input_set_abs_params(&itmtouch->inputdev, ABS_X, 0, 0x0FFF, 2, 0); | ||
202 | input_set_abs_params(&itmtouch->inputdev, ABS_Y, 0, 0x0FFF, 2, 0); | ||
203 | input_set_abs_params(&itmtouch->inputdev, ABS_PRESSURE, 0, 0xFF, 2, 0); | ||
204 | |||
205 | /* initialise the URB so we can read from the transport stream */ | ||
206 | pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress); | ||
207 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
208 | |||
209 | if (maxp > ITM_BUFSIZE) | ||
210 | maxp = ITM_BUFSIZE; | ||
211 | |||
212 | itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL); | ||
213 | |||
214 | if (!itmtouch->readurb) { | ||
215 | dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__); | ||
216 | kfree(itmtouch); | ||
217 | return -ENOMEM; | ||
218 | } | ||
219 | |||
220 | usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf, | ||
221 | maxp, itmtouch_irq, itmtouch, endpoint->bInterval); | ||
222 | |||
223 | input_register_device(&itmtouch->inputdev); | ||
224 | |||
225 | printk(KERN_INFO "itmtouch: %s registered on %s\n", itmtouch->name, path); | ||
226 | usb_set_intfdata(intf, itmtouch); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static void itmtouch_disconnect(struct usb_interface *intf) | ||
232 | { | ||
233 | struct itmtouch_dev *itmtouch = usb_get_intfdata(intf); | ||
234 | |||
235 | usb_set_intfdata(intf, NULL); | ||
236 | |||
237 | if (itmtouch) { | ||
238 | input_unregister_device(&itmtouch->inputdev); | ||
239 | usb_kill_urb(itmtouch->readurb); | ||
240 | usb_free_urb(itmtouch->readurb); | ||
241 | kfree(itmtouch); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | MODULE_DEVICE_TABLE(usb, itmtouch_ids); | ||
246 | |||
247 | static struct usb_driver itmtouch_driver = { | ||
248 | .owner = THIS_MODULE, | ||
249 | .name = "itmtouch", | ||
250 | .probe = itmtouch_probe, | ||
251 | .disconnect = itmtouch_disconnect, | ||
252 | .id_table = itmtouch_ids, | ||
253 | }; | ||
254 | |||
255 | static int __init itmtouch_init(void) | ||
256 | { | ||
257 | info(DRIVER_DESC " " DRIVER_VERSION); | ||
258 | info(DRIVER_AUTHOR); | ||
259 | return usb_register(&itmtouch_driver); | ||
260 | } | ||
261 | |||
262 | static void __exit itmtouch_exit(void) | ||
263 | { | ||
264 | usb_deregister(&itmtouch_driver); | ||
265 | } | ||
266 | |||
267 | module_init(itmtouch_init); | ||
268 | module_exit(itmtouch_exit); | ||
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index a68c5b4e7b37..d2f0f90a9bcd 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c | |||
@@ -36,7 +36,6 @@ struct kbtab { | |||
36 | struct input_dev dev; | 36 | struct input_dev dev; |
37 | struct usb_device *usbdev; | 37 | struct usb_device *usbdev; |
38 | struct urb *irq; | 38 | struct urb *irq; |
39 | int open; | ||
40 | int x, y; | 39 | int x, y; |
41 | int button; | 40 | int button; |
42 | int pressure; | 41 | int pressure; |
@@ -79,12 +78,12 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs) | |||
79 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ | 78 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ |
80 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | 79 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); |
81 | 80 | ||
82 | if( -1 == kb_pressure_click){ | 81 | if (-1 == kb_pressure_click) { |
83 | input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); | 82 | input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); |
84 | } else { | 83 | } else { |
85 | input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); | 84 | input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); |
86 | }; | 85 | }; |
87 | 86 | ||
88 | input_sync(dev); | 87 | input_sync(dev); |
89 | 88 | ||
90 | exit: | 89 | exit: |
@@ -105,14 +104,9 @@ static int kbtab_open(struct input_dev *dev) | |||
105 | { | 104 | { |
106 | struct kbtab *kbtab = dev->private; | 105 | struct kbtab *kbtab = dev->private; |
107 | 106 | ||
108 | if (kbtab->open++) | ||
109 | return 0; | ||
110 | |||
111 | kbtab->irq->dev = kbtab->usbdev; | 107 | kbtab->irq->dev = kbtab->usbdev; |
112 | if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) { | 108 | if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) |
113 | kbtab->open--; | ||
114 | return -EIO; | 109 | return -EIO; |
115 | } | ||
116 | 110 | ||
117 | return 0; | 111 | return 0; |
118 | } | 112 | } |
@@ -121,8 +115,7 @@ static void kbtab_close(struct input_dev *dev) | |||
121 | { | 115 | { |
122 | struct kbtab *kbtab = dev->private; | 116 | struct kbtab *kbtab = dev->private; |
123 | 117 | ||
124 | if (!--kbtab->open) | 118 | usb_kill_urb(kbtab->irq); |
125 | usb_kill_urb(kbtab->irq); | ||
126 | } | 119 | } |
127 | 120 | ||
128 | static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) | 121 | static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) |
@@ -161,7 +154,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
161 | kbtab->dev.absmax[ABS_X] = 0x2000; | 154 | kbtab->dev.absmax[ABS_X] = 0x2000; |
162 | kbtab->dev.absmax[ABS_Y] = 0x1750; | 155 | kbtab->dev.absmax[ABS_Y] = 0x1750; |
163 | kbtab->dev.absmax[ABS_PRESSURE] = 0xff; | 156 | kbtab->dev.absmax[ABS_PRESSURE] = 0xff; |
164 | 157 | ||
165 | kbtab->dev.absfuzz[ABS_X] = 4; | 158 | kbtab->dev.absfuzz[ABS_X] = 4; |
166 | kbtab->dev.absfuzz[ABS_Y] = 4; | 159 | kbtab->dev.absfuzz[ABS_Y] = 4; |
167 | 160 | ||
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index ab1a2a30ce7c..09b5cc7c66de 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c | |||
@@ -42,9 +42,9 @@ | |||
42 | #include <linux/config.h> | 42 | #include <linux/config.h> |
43 | 43 | ||
44 | #ifdef CONFIG_USB_DEBUG | 44 | #ifdef CONFIG_USB_DEBUG |
45 | #define DEBUG | 45 | #define DEBUG |
46 | #else | 46 | #else |
47 | #undef DEBUG | 47 | #undef DEBUG |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | #include <linux/kernel.h> | 50 | #include <linux/kernel.h> |
@@ -93,275 +93,255 @@ module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR); | |||
93 | MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); | 93 | MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); |
94 | 94 | ||
95 | struct mtouch_usb { | 95 | struct mtouch_usb { |
96 | unsigned char *data; | 96 | unsigned char *data; |
97 | dma_addr_t data_dma; | 97 | dma_addr_t data_dma; |
98 | struct urb *irq; | 98 | struct urb *irq; |
99 | struct usb_device *udev; | 99 | struct usb_device *udev; |
100 | struct input_dev input; | 100 | struct input_dev input; |
101 | int open; | 101 | char name[128]; |
102 | char name[128]; | 102 | char phys[64]; |
103 | char phys[64]; | ||
104 | }; | 103 | }; |
105 | 104 | ||
106 | static struct usb_device_id mtouchusb_devices [] = { | 105 | static struct usb_device_id mtouchusb_devices[] = { |
107 | { USB_DEVICE(0x0596, 0x0001) }, | 106 | { USB_DEVICE(0x0596, 0x0001) }, |
108 | { } | 107 | { } |
109 | }; | 108 | }; |
110 | 109 | ||
111 | static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) | 110 | static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) |
112 | { | 111 | { |
113 | struct mtouch_usb *mtouch = urb->context; | 112 | struct mtouch_usb *mtouch = urb->context; |
114 | int retval; | 113 | int retval; |
115 | 114 | ||
116 | switch (urb->status) { | 115 | switch (urb->status) { |
117 | case 0: | 116 | case 0: |
118 | /* success */ | 117 | /* success */ |
119 | break; | 118 | break; |
120 | case -ETIMEDOUT: | 119 | case -ETIMEDOUT: |
121 | /* this urb is timing out */ | 120 | /* this urb is timing out */ |
122 | dbg("%s - urb timed out - was the device unplugged?", | 121 | dbg("%s - urb timed out - was the device unplugged?", |
123 | __FUNCTION__); | 122 | __FUNCTION__); |
124 | return; | 123 | return; |
125 | case -ECONNRESET: | 124 | case -ECONNRESET: |
126 | case -ENOENT: | 125 | case -ENOENT: |
127 | case -ESHUTDOWN: | 126 | case -ESHUTDOWN: |
128 | /* this urb is terminated, clean up */ | 127 | /* this urb is terminated, clean up */ |
129 | dbg("%s - urb shutting down with status: %d", | 128 | dbg("%s - urb shutting down with status: %d", |
130 | __FUNCTION__, urb->status); | 129 | __FUNCTION__, urb->status); |
131 | return; | 130 | return; |
132 | default: | 131 | default: |
133 | dbg("%s - nonzero urb status received: %d", | 132 | dbg("%s - nonzero urb status received: %d", |
134 | __FUNCTION__, urb->status); | 133 | __FUNCTION__, urb->status); |
135 | goto exit; | 134 | goto exit; |
136 | } | 135 | } |
137 | 136 | ||
138 | input_regs(&mtouch->input, regs); | 137 | input_regs(&mtouch->input, regs); |
139 | input_report_key(&mtouch->input, BTN_TOUCH, | 138 | input_report_key(&mtouch->input, BTN_TOUCH, |
140 | MTOUCHUSB_GET_TOUCHED(mtouch->data)); | 139 | MTOUCHUSB_GET_TOUCHED(mtouch->data)); |
141 | input_report_abs(&mtouch->input, ABS_X, | 140 | input_report_abs(&mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data)); |
142 | MTOUCHUSB_GET_XC(mtouch->data)); | 141 | input_report_abs(&mtouch->input, ABS_Y, |
143 | input_report_abs(&mtouch->input, ABS_Y, | ||
144 | (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) | 142 | (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) |
145 | - MTOUCHUSB_GET_YC(mtouch->data)); | 143 | - MTOUCHUSB_GET_YC(mtouch->data)); |
146 | input_sync(&mtouch->input); | 144 | input_sync(&mtouch->input); |
147 | 145 | ||
148 | exit: | 146 | exit: |
149 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 147 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
150 | if (retval) | 148 | if (retval) |
151 | err ("%s - usb_submit_urb failed with result: %d", | 149 | err("%s - usb_submit_urb failed with result: %d", |
152 | __FUNCTION__, retval); | 150 | __FUNCTION__, retval); |
153 | } | 151 | } |
154 | 152 | ||
155 | static int mtouchusb_open (struct input_dev *input) | 153 | static int mtouchusb_open(struct input_dev *input) |
156 | { | 154 | { |
157 | struct mtouch_usb *mtouch = input->private; | 155 | struct mtouch_usb *mtouch = input->private; |
158 | 156 | ||
159 | if (mtouch->open++) | 157 | mtouch->irq->dev = mtouch->udev; |
160 | return 0; | ||
161 | 158 | ||
162 | mtouch->irq->dev = mtouch->udev; | 159 | if (usb_submit_urb(mtouch->irq, GFP_ATOMIC)) |
160 | return -EIO; | ||
163 | 161 | ||
164 | if (usb_submit_urb (mtouch->irq, GFP_ATOMIC)) { | 162 | return 0; |
165 | mtouch->open--; | ||
166 | return -EIO; | ||
167 | } | ||
168 | |||
169 | return 0; | ||
170 | } | 163 | } |
171 | 164 | ||
172 | static void mtouchusb_close (struct input_dev *input) | 165 | static void mtouchusb_close(struct input_dev *input) |
173 | { | 166 | { |
174 | struct mtouch_usb *mtouch = input->private; | 167 | struct mtouch_usb *mtouch = input->private; |
175 | 168 | ||
176 | if (!--mtouch->open) | 169 | usb_kill_urb(mtouch->irq); |
177 | usb_kill_urb (mtouch->irq); | ||
178 | } | 170 | } |
179 | 171 | ||
180 | static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) | 172 | static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) |
181 | { | 173 | { |
182 | dbg("%s - called", __FUNCTION__); | 174 | dbg("%s - called", __FUNCTION__); |
183 | 175 | ||
184 | mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, | 176 | mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, |
185 | SLAB_ATOMIC, &mtouch->data_dma); | 177 | SLAB_ATOMIC, &mtouch->data_dma); |
186 | 178 | ||
187 | if (!mtouch->data) | 179 | if (!mtouch->data) |
188 | return -1; | 180 | return -1; |
189 | 181 | ||
190 | return 0; | 182 | return 0; |
191 | } | 183 | } |
192 | 184 | ||
193 | static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) | 185 | static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) |
194 | { | 186 | { |
195 | dbg("%s - called", __FUNCTION__); | 187 | dbg("%s - called", __FUNCTION__); |
196 | 188 | ||
197 | if (mtouch->data) | 189 | if (mtouch->data) |
198 | usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, | 190 | usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, |
199 | mtouch->data, mtouch->data_dma); | 191 | mtouch->data, mtouch->data_dma); |
200 | } | 192 | } |
201 | 193 | ||
202 | static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) | 194 | static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) |
203 | { | 195 | { |
204 | struct mtouch_usb *mtouch; | 196 | struct mtouch_usb *mtouch; |
205 | struct usb_host_interface *interface; | 197 | struct usb_host_interface *interface; |
206 | struct usb_endpoint_descriptor *endpoint; | 198 | struct usb_endpoint_descriptor *endpoint; |
207 | struct usb_device *udev = interface_to_usbdev (intf); | 199 | struct usb_device *udev = interface_to_usbdev(intf); |
208 | char path[64]; | 200 | char path[64]; |
209 | int nRet; | 201 | int nRet; |
210 | 202 | ||
211 | dbg("%s - called", __FUNCTION__); | 203 | dbg("%s - called", __FUNCTION__); |
212 | 204 | ||
213 | dbg("%s - setting interface", __FUNCTION__); | 205 | dbg("%s - setting interface", __FUNCTION__); |
214 | interface = intf->cur_altsetting; | 206 | interface = intf->cur_altsetting; |
215 | 207 | ||
216 | dbg("%s - setting endpoint", __FUNCTION__); | 208 | dbg("%s - setting endpoint", __FUNCTION__); |
217 | endpoint = &interface->endpoint[0].desc; | 209 | endpoint = &interface->endpoint[0].desc; |
218 | 210 | ||
219 | if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) { | 211 | if (!(mtouch = kmalloc(sizeof(struct mtouch_usb), GFP_KERNEL))) { |
220 | err("%s - Out of memory.", __FUNCTION__); | 212 | err("%s - Out of memory.", __FUNCTION__); |
221 | return -ENOMEM; | 213 | return -ENOMEM; |
222 | } | 214 | } |
223 | 215 | ||
224 | memset(mtouch, 0, sizeof(struct mtouch_usb)); | 216 | memset(mtouch, 0, sizeof(struct mtouch_usb)); |
225 | mtouch->udev = udev; | 217 | mtouch->udev = udev; |
226 | 218 | ||
227 | dbg("%s - allocating buffers", __FUNCTION__); | 219 | dbg("%s - allocating buffers", __FUNCTION__); |
228 | if (mtouchusb_alloc_buffers(udev, mtouch)) { | 220 | if (mtouchusb_alloc_buffers(udev, mtouch)) { |
229 | mtouchusb_free_buffers(udev, mtouch); | 221 | mtouchusb_free_buffers(udev, mtouch); |
230 | kfree(mtouch); | 222 | kfree(mtouch); |
231 | return -ENOMEM; | 223 | return -ENOMEM; |
232 | } | 224 | } |
233 | 225 | ||
234 | mtouch->input.private = mtouch; | 226 | mtouch->input.private = mtouch; |
235 | mtouch->input.open = mtouchusb_open; | 227 | mtouch->input.open = mtouchusb_open; |
236 | mtouch->input.close = mtouchusb_close; | 228 | mtouch->input.close = mtouchusb_close; |
237 | 229 | ||
238 | usb_make_path(udev, path, 64); | 230 | usb_make_path(udev, path, 64); |
239 | sprintf(mtouch->phys, "%s/input0", path); | 231 | sprintf(mtouch->phys, "%s/input0", path); |
240 | 232 | ||
241 | mtouch->input.name = mtouch->name; | 233 | mtouch->input.name = mtouch->name; |
242 | mtouch->input.phys = mtouch->phys; | 234 | mtouch->input.phys = mtouch->phys; |
243 | mtouch->input.id.bustype = BUS_USB; | 235 | mtouch->input.id.bustype = BUS_USB; |
244 | mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | 236 | mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); |
245 | mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); | 237 | mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); |
246 | mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); | 238 | mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); |
247 | mtouch->input.dev = &intf->dev; | 239 | mtouch->input.dev = &intf->dev; |
248 | 240 | ||
249 | mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 241 | mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
250 | mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); | 242 | mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); |
251 | mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | 243 | mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); |
252 | 244 | ||
253 | /* Used to Scale Compensated Data and Flip Y */ | 245 | /* Used to Scale Compensated Data and Flip Y */ |
254 | mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; | 246 | mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; |
255 | mtouch->input.absmax[ABS_X] = raw_coordinates ? \ | 247 | mtouch->input.absmax[ABS_X] = raw_coordinates ? |
256 | MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; | 248 | MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; |
257 | mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; | 249 | mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; |
258 | mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; | 250 | mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; |
259 | mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; | 251 | mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; |
260 | mtouch->input.absmax[ABS_Y] = raw_coordinates ? \ | 252 | mtouch->input.absmax[ABS_Y] = raw_coordinates ? |
261 | MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; | 253 | MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; |
262 | mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; | 254 | mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; |
263 | mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; | 255 | mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; |
264 | 256 | ||
265 | if (udev->manufacturer) | 257 | if (udev->manufacturer) |
266 | strcat(mtouch->name, udev->manufacturer); | 258 | strcat(mtouch->name, udev->manufacturer); |
267 | if (udev->product) | 259 | if (udev->product) |
268 | sprintf(mtouch->name, "%s %s", mtouch->name, udev->product); | 260 | sprintf(mtouch->name, "%s %s", mtouch->name, udev->product); |
269 | 261 | ||
270 | if (!strlen(mtouch->name)) | 262 | if (!strlen(mtouch->name)) |
271 | sprintf(mtouch->name, "USB Touchscreen %04x:%04x", | 263 | sprintf(mtouch->name, "USB Touchscreen %04x:%04x", |
272 | mtouch->input.id.vendor, mtouch->input.id.product); | 264 | mtouch->input.id.vendor, mtouch->input.id.product); |
273 | 265 | ||
274 | nRet = usb_control_msg(mtouch->udev, | 266 | nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), |
275 | usb_rcvctrlpipe(udev, 0), | 267 | MTOUCHUSB_RESET, |
276 | MTOUCHUSB_RESET, | 268 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
277 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 269 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); |
278 | 1, | 270 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", |
279 | 0, | 271 | __FUNCTION__, nRet); |
280 | NULL, | 272 | |
281 | 0, | 273 | dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); |
282 | USB_CTRL_SET_TIMEOUT); | 274 | mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); |
283 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", | 275 | if (!mtouch->irq) { |
284 | __FUNCTION__, nRet); | 276 | dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); |
285 | 277 | mtouchusb_free_buffers(udev, mtouch); | |
286 | dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); | 278 | kfree(mtouch); |
287 | mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); | 279 | return -ENOMEM; |
288 | if (!mtouch->irq) { | 280 | } |
289 | dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); | 281 | |
290 | mtouchusb_free_buffers(udev, mtouch); | 282 | dbg("%s - usb_fill_int_urb", __FUNCTION__); |
291 | kfree(mtouch); | 283 | usb_fill_int_urb(mtouch->irq, mtouch->udev, |
292 | return -ENOMEM; | 284 | usb_rcvintpipe(mtouch->udev, 0x81), |
293 | } | 285 | mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE, |
294 | 286 | mtouchusb_irq, mtouch, endpoint->bInterval); | |
295 | dbg("%s - usb_fill_int_urb", __FUNCTION__); | 287 | |
296 | usb_fill_int_urb(mtouch->irq, | 288 | dbg("%s - input_register_device", __FUNCTION__); |
297 | mtouch->udev, | 289 | input_register_device(&mtouch->input); |
298 | usb_rcvintpipe(mtouch->udev, 0x81), | 290 | |
299 | mtouch->data, | 291 | nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), |
300 | MTOUCHUSB_REPORT_DATA_SIZE, | 292 | MTOUCHUSB_ASYNC_REPORT, |
301 | mtouchusb_irq, | 293 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
302 | mtouch, | 294 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); |
303 | endpoint->bInterval); | 295 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", |
304 | 296 | __FUNCTION__, nRet); | |
305 | dbg("%s - input_register_device", __FUNCTION__); | 297 | |
306 | input_register_device(&mtouch->input); | 298 | printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); |
307 | 299 | usb_set_intfdata(intf, mtouch); | |
308 | nRet = usb_control_msg(mtouch->udev, | 300 | |
309 | usb_rcvctrlpipe(udev, 0), | 301 | return 0; |
310 | MTOUCHUSB_ASYNC_REPORT, | ||
311 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
312 | 1, | ||
313 | 1, | ||
314 | NULL, | ||
315 | 0, | ||
316 | USB_CTRL_SET_TIMEOUT); | ||
317 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", | ||
318 | __FUNCTION__, nRet); | ||
319 | |||
320 | printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); | ||
321 | usb_set_intfdata(intf, mtouch); | ||
322 | |||
323 | return 0; | ||
324 | } | 302 | } |
325 | 303 | ||
326 | static void mtouchusb_disconnect(struct usb_interface *intf) | 304 | static void mtouchusb_disconnect(struct usb_interface *intf) |
327 | { | 305 | { |
328 | struct mtouch_usb *mtouch = usb_get_intfdata (intf); | 306 | struct mtouch_usb *mtouch = usb_get_intfdata(intf); |
329 | 307 | ||
330 | dbg("%s - called", __FUNCTION__); | 308 | dbg("%s - called", __FUNCTION__); |
331 | usb_set_intfdata(intf, NULL); | 309 | usb_set_intfdata(intf, NULL); |
332 | if (mtouch) { | 310 | if (mtouch) { |
333 | dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); | 311 | dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); |
334 | usb_kill_urb(mtouch->irq); | 312 | usb_kill_urb(mtouch->irq); |
335 | input_unregister_device(&mtouch->input); | 313 | input_unregister_device(&mtouch->input); |
336 | usb_free_urb(mtouch->irq); | 314 | usb_free_urb(mtouch->irq); |
337 | mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); | 315 | mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); |
338 | kfree(mtouch); | 316 | kfree(mtouch); |
339 | } | 317 | } |
340 | } | 318 | } |
341 | 319 | ||
342 | MODULE_DEVICE_TABLE (usb, mtouchusb_devices); | 320 | MODULE_DEVICE_TABLE(usb, mtouchusb_devices); |
343 | 321 | ||
344 | static struct usb_driver mtouchusb_driver = { | 322 | static struct usb_driver mtouchusb_driver = { |
345 | .owner = THIS_MODULE, | 323 | .owner = THIS_MODULE, |
346 | .name = "mtouchusb", | 324 | .name = "mtouchusb", |
347 | .probe = mtouchusb_probe, | 325 | .probe = mtouchusb_probe, |
348 | .disconnect = mtouchusb_disconnect, | 326 | .disconnect = mtouchusb_disconnect, |
349 | .id_table = mtouchusb_devices, | 327 | .id_table = mtouchusb_devices, |
350 | }; | 328 | }; |
351 | 329 | ||
352 | static int __init mtouchusb_init(void) { | 330 | static int __init mtouchusb_init(void) |
353 | dbg("%s - called", __FUNCTION__); | 331 | { |
354 | return usb_register(&mtouchusb_driver); | 332 | dbg("%s - called", __FUNCTION__); |
333 | return usb_register(&mtouchusb_driver); | ||
355 | } | 334 | } |
356 | 335 | ||
357 | static void __exit mtouchusb_cleanup(void) { | 336 | static void __exit mtouchusb_cleanup(void) |
358 | dbg("%s - called", __FUNCTION__); | 337 | { |
359 | usb_deregister(&mtouchusb_driver); | 338 | dbg("%s - called", __FUNCTION__); |
339 | usb_deregister(&mtouchusb_driver); | ||
360 | } | 340 | } |
361 | 341 | ||
362 | module_init(mtouchusb_init); | 342 | module_init(mtouchusb_init); |
363 | module_exit(mtouchusb_cleanup); | 343 | module_exit(mtouchusb_cleanup); |
364 | 344 | ||
365 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 345 | MODULE_AUTHOR(DRIVER_AUTHOR); |
366 | MODULE_DESCRIPTION( DRIVER_DESC ); | 346 | MODULE_DESCRIPTION(DRIVER_DESC); |
367 | MODULE_LICENSE("GPL"); | 347 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index 7fa2f9b9fb69..3975b309d55f 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * back to the host when polled by the USB controller. | 10 | * back to the host when polled by the USB controller. |
11 | * | 11 | * |
12 | * Testing with the knob I have has shown that it measures approximately 94 "clicks" | 12 | * Testing with the knob I have has shown that it measures approximately 94 "clicks" |
13 | * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was | 13 | * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was |
14 | * a variable speed cordless electric drill) has shown that the device can measure | 14 | * a variable speed cordless electric drill) has shown that the device can measure |
15 | * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from | 15 | * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from |
16 | * the host. If it counts more than 7 clicks before it is polled, it will wrap back | 16 | * the host. If it counts more than 7 clicks before it is polled, it will wrap back |
@@ -120,9 +120,9 @@ exit: | |||
120 | /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ | 120 | /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ |
121 | static void powermate_sync_state(struct powermate_device *pm) | 121 | static void powermate_sync_state(struct powermate_device *pm) |
122 | { | 122 | { |
123 | if (pm->requires_update == 0) | 123 | if (pm->requires_update == 0) |
124 | return; /* no updates are required */ | 124 | return; /* no updates are required */ |
125 | if (pm->config->status == -EINPROGRESS) | 125 | if (pm->config->status == -EINPROGRESS) |
126 | return; /* an update is already in progress; it'll issue this update when it completes */ | 126 | return; /* an update is already in progress; it'll issue this update when it completes */ |
127 | 127 | ||
128 | if (pm->requires_update & UPDATE_PULSE_ASLEEP){ | 128 | if (pm->requires_update & UPDATE_PULSE_ASLEEP){ |
@@ -142,7 +142,7 @@ static void powermate_sync_state(struct powermate_device *pm) | |||
142 | 2: multiply the speed | 142 | 2: multiply the speed |
143 | the argument only has an effect for operations 0 and 2, and ranges between | 143 | the argument only has an effect for operations 0 and 2, and ranges between |
144 | 1 (least effect) to 255 (maximum effect). | 144 | 1 (least effect) to 255 (maximum effect). |
145 | 145 | ||
146 | thus, several states are equivalent and are coalesced into one state. | 146 | thus, several states are equivalent and are coalesced into one state. |
147 | 147 | ||
148 | we map this onto a range from 0 to 510, with: | 148 | we map this onto a range from 0 to 510, with: |
@@ -151,7 +151,7 @@ static void powermate_sync_state(struct powermate_device *pm) | |||
151 | 256 -- 510 -- use multiple (510 = fastest). | 151 | 256 -- 510 -- use multiple (510 = fastest). |
152 | 152 | ||
153 | Only values of 'arg' quite close to 255 are particularly useful/spectacular. | 153 | Only values of 'arg' quite close to 255 are particularly useful/spectacular. |
154 | */ | 154 | */ |
155 | if (pm->pulse_speed < 255){ | 155 | if (pm->pulse_speed < 255){ |
156 | op = 0; // divide | 156 | op = 0; // divide |
157 | arg = 255 - pm->pulse_speed; | 157 | arg = 255 - pm->pulse_speed; |
@@ -199,14 +199,14 @@ static void powermate_config_complete(struct urb *urb, struct pt_regs *regs) | |||
199 | 199 | ||
200 | if (urb->status) | 200 | if (urb->status) |
201 | printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); | 201 | printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); |
202 | 202 | ||
203 | spin_lock_irqsave(&pm->lock, flags); | 203 | spin_lock_irqsave(&pm->lock, flags); |
204 | powermate_sync_state(pm); | 204 | powermate_sync_state(pm); |
205 | spin_unlock_irqrestore(&pm->lock, flags); | 205 | spin_unlock_irqrestore(&pm->lock, flags); |
206 | } | 206 | } |
207 | 207 | ||
208 | /* Set the LED up as described and begin the sync with the hardware if required */ | 208 | /* Set the LED up as described and begin the sync with the hardware if required */ |
209 | static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, | 209 | static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, |
210 | int pulse_table, int pulse_asleep, int pulse_awake) | 210 | int pulse_table, int pulse_asleep, int pulse_awake) |
211 | { | 211 | { |
212 | unsigned long flags; | 212 | unsigned long flags; |
@@ -229,7 +229,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne | |||
229 | /* mark state updates which are required */ | 229 | /* mark state updates which are required */ |
230 | if (static_brightness != pm->static_brightness){ | 230 | if (static_brightness != pm->static_brightness){ |
231 | pm->static_brightness = static_brightness; | 231 | pm->static_brightness = static_brightness; |
232 | pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; | 232 | pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; |
233 | } | 233 | } |
234 | if (pulse_asleep != pm->pulse_asleep){ | 234 | if (pulse_asleep != pm->pulse_asleep){ |
235 | pm->pulse_asleep = pulse_asleep; | 235 | pm->pulse_asleep = pulse_asleep; |
@@ -246,7 +246,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne | |||
246 | } | 246 | } |
247 | 247 | ||
248 | powermate_sync_state(pm); | 248 | powermate_sync_state(pm); |
249 | 249 | ||
250 | spin_unlock_irqrestore(&pm->lock, flags); | 250 | spin_unlock_irqrestore(&pm->lock, flags); |
251 | } | 251 | } |
252 | 252 | ||
@@ -257,19 +257,19 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig | |||
257 | struct powermate_device *pm = dev->private; | 257 | struct powermate_device *pm = dev->private; |
258 | 258 | ||
259 | if (type == EV_MSC && code == MSC_PULSELED){ | 259 | if (type == EV_MSC && code == MSC_PULSELED){ |
260 | /* | 260 | /* |
261 | bits 0- 7: 8 bits: LED brightness | 261 | bits 0- 7: 8 bits: LED brightness |
262 | bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. | 262 | bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. |
263 | bits 17-18: 2 bits: pulse table (0, 1, 2 valid) | 263 | bits 17-18: 2 bits: pulse table (0, 1, 2 valid) |
264 | bit 19: 1 bit : pulse whilst asleep? | 264 | bit 19: 1 bit : pulse whilst asleep? |
265 | bit 20: 1 bit : pulse constantly? | 265 | bit 20: 1 bit : pulse constantly? |
266 | */ | 266 | */ |
267 | int static_brightness = command & 0xFF; // bits 0-7 | 267 | int static_brightness = command & 0xFF; // bits 0-7 |
268 | int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 | 268 | int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 |
269 | int pulse_table = (command >> 17) & 0x3; // bits 17-18 | 269 | int pulse_table = (command >> 17) & 0x3; // bits 17-18 |
270 | int pulse_asleep = (command >> 19) & 0x1; // bit 19 | 270 | int pulse_asleep = (command >> 19) & 0x1; // bit 19 |
271 | int pulse_awake = (command >> 20) & 0x1; // bit 20 | 271 | int pulse_awake = (command >> 20) & 0x1; // bit 20 |
272 | 272 | ||
273 | powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); | 273 | powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); |
274 | } | 274 | } |
275 | 275 | ||
@@ -378,7 +378,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i | |||
378 | switch (le16_to_cpu(udev->descriptor.idProduct)) { | 378 | switch (le16_to_cpu(udev->descriptor.idProduct)) { |
379 | case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; | 379 | case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; |
380 | case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; | 380 | case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; |
381 | default: | 381 | default: |
382 | pm->input.name = pm_name_soundknob; | 382 | pm->input.name = pm_name_soundknob; |
383 | printk(KERN_WARNING "powermate: unknown product id %04x\n", | 383 | printk(KERN_WARNING "powermate: unknown product id %04x\n", |
384 | le16_to_cpu(udev->descriptor.idProduct)); | 384 | le16_to_cpu(udev->descriptor.idProduct)); |
@@ -402,11 +402,11 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i | |||
402 | usb_make_path(udev, path, 64); | 402 | usb_make_path(udev, path, 64); |
403 | snprintf(pm->phys, 64, "%s/input0", path); | 403 | snprintf(pm->phys, 64, "%s/input0", path); |
404 | printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys); | 404 | printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys); |
405 | 405 | ||
406 | /* force an update of everything */ | 406 | /* force an update of everything */ |
407 | pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; | 407 | pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; |
408 | powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters | 408 | powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters |
409 | 409 | ||
410 | usb_set_intfdata(intf, pm); | 410 | usb_set_intfdata(intf, pm); |
411 | return 0; | 411 | return 0; |
412 | } | 412 | } |
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index a71f1bbd0a17..386595ee21c0 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c | |||
@@ -69,7 +69,6 @@ struct touchkit_usb { | |||
69 | struct urb *irq; | 69 | struct urb *irq; |
70 | struct usb_device *udev; | 70 | struct usb_device *udev; |
71 | struct input_dev input; | 71 | struct input_dev input; |
72 | int open; | ||
73 | char name[128]; | 72 | char name[128]; |
74 | char phys[64]; | 73 | char phys[64]; |
75 | }; | 74 | }; |
@@ -134,15 +133,10 @@ static int touchkit_open(struct input_dev *input) | |||
134 | { | 133 | { |
135 | struct touchkit_usb *touchkit = input->private; | 134 | struct touchkit_usb *touchkit = input->private; |
136 | 135 | ||
137 | if (touchkit->open++) | ||
138 | return 0; | ||
139 | |||
140 | touchkit->irq->dev = touchkit->udev; | 136 | touchkit->irq->dev = touchkit->udev; |
141 | 137 | ||
142 | if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) { | 138 | if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) |
143 | touchkit->open--; | ||
144 | return -EIO; | 139 | return -EIO; |
145 | } | ||
146 | 140 | ||
147 | return 0; | 141 | return 0; |
148 | } | 142 | } |
@@ -151,8 +145,7 @@ static void touchkit_close(struct input_dev *input) | |||
151 | { | 145 | { |
152 | struct touchkit_usb *touchkit = input->private; | 146 | struct touchkit_usb *touchkit = input->private; |
153 | 147 | ||
154 | if (!--touchkit->open) | 148 | usb_kill_urb(touchkit->irq); |
155 | usb_kill_urb(touchkit->irq); | ||
156 | } | 149 | } |
157 | 150 | ||
158 | static int touchkit_alloc_buffers(struct usb_device *udev, | 151 | static int touchkit_alloc_buffers(struct usb_device *udev, |
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index 7038fb9d1ced..f35db1974c42 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c | |||
@@ -9,18 +9,18 @@ | |||
9 | /* | 9 | /* |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
14 | * | 14 | * |
15 | * This program is distributed in the hope that it will be useful, | 15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
19 | * | 19 | * |
20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 | * | 23 | * |
24 | * Should you need to contact me, the author, you can do so either by | 24 | * Should you need to contact me, the author, you can do so either by |
25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
@@ -72,7 +72,6 @@ struct usb_kbd { | |||
72 | unsigned char newleds; | 72 | unsigned char newleds; |
73 | char name[128]; | 73 | char name[128]; |
74 | char phys[64]; | 74 | char phys[64]; |
75 | int open; | ||
76 | 75 | ||
77 | unsigned char *new; | 76 | unsigned char *new; |
78 | struct usb_ctrlrequest *cr; | 77 | struct usb_ctrlrequest *cr; |
@@ -166,7 +165,7 @@ static void usb_kbd_led(struct urb *urb, struct pt_regs *regs) | |||
166 | 165 | ||
167 | if (urb->status) | 166 | if (urb->status) |
168 | warn("led urb status %d received", urb->status); | 167 | warn("led urb status %d received", urb->status); |
169 | 168 | ||
170 | if (*(kbd->leds) == kbd->newleds) | 169 | if (*(kbd->leds) == kbd->newleds) |
171 | return; | 170 | return; |
172 | 171 | ||
@@ -180,14 +179,9 @@ static int usb_kbd_open(struct input_dev *dev) | |||
180 | { | 179 | { |
181 | struct usb_kbd *kbd = dev->private; | 180 | struct usb_kbd *kbd = dev->private; |
182 | 181 | ||
183 | if (kbd->open++) | ||
184 | return 0; | ||
185 | |||
186 | kbd->irq->dev = kbd->usbdev; | 182 | kbd->irq->dev = kbd->usbdev; |
187 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) { | 183 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) |
188 | kbd->open--; | ||
189 | return -EIO; | 184 | return -EIO; |
190 | } | ||
191 | 185 | ||
192 | return 0; | 186 | return 0; |
193 | } | 187 | } |
@@ -196,8 +190,7 @@ static void usb_kbd_close(struct input_dev *dev) | |||
196 | { | 190 | { |
197 | struct usb_kbd *kbd = dev->private; | 191 | struct usb_kbd *kbd = dev->private; |
198 | 192 | ||
199 | if (!--kbd->open) | 193 | usb_kill_urb(kbd->irq); |
200 | usb_kill_urb(kbd->irq); | ||
201 | } | 194 | } |
202 | 195 | ||
203 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) | 196 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) |
@@ -230,7 +223,7 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) | |||
230 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); | 223 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); |
231 | } | 224 | } |
232 | 225 | ||
233 | static int usb_kbd_probe(struct usb_interface *iface, | 226 | static int usb_kbd_probe(struct usb_interface *iface, |
234 | const struct usb_device_id *id) | 227 | const struct usb_device_id *id) |
235 | { | 228 | { |
236 | struct usb_device * dev = interface_to_usbdev(iface); | 229 | struct usb_device * dev = interface_to_usbdev(iface); |
@@ -272,7 +265,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
272 | for (i = 0; i < 255; i++) | 265 | for (i = 0; i < 255; i++) |
273 | set_bit(usb_kbd_keycode[i], kbd->dev.keybit); | 266 | set_bit(usb_kbd_keycode[i], kbd->dev.keybit); |
274 | clear_bit(0, kbd->dev.keybit); | 267 | clear_bit(0, kbd->dev.keybit); |
275 | 268 | ||
276 | kbd->dev.private = kbd; | 269 | kbd->dev.private = kbd; |
277 | kbd->dev.event = usb_kbd_event; | 270 | kbd->dev.event = usb_kbd_event; |
278 | kbd->dev.open = usb_kbd_open; | 271 | kbd->dev.open = usb_kbd_open; |
@@ -294,7 +287,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
294 | sprintf(kbd->phys, "%s/input0", path); | 287 | sprintf(kbd->phys, "%s/input0", path); |
295 | 288 | ||
296 | kbd->dev.name = kbd->name; | 289 | kbd->dev.name = kbd->name; |
297 | kbd->dev.phys = kbd->phys; | 290 | kbd->dev.phys = kbd->phys; |
298 | kbd->dev.id.bustype = BUS_USB; | 291 | kbd->dev.id.bustype = BUS_USB; |
299 | kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | 292 | kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); |
300 | kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); | 293 | kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); |
@@ -329,7 +322,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
329 | static void usb_kbd_disconnect(struct usb_interface *intf) | 322 | static void usb_kbd_disconnect(struct usb_interface *intf) |
330 | { | 323 | { |
331 | struct usb_kbd *kbd = usb_get_intfdata (intf); | 324 | struct usb_kbd *kbd = usb_get_intfdata (intf); |
332 | 325 | ||
333 | usb_set_intfdata(intf, NULL); | 326 | usb_set_intfdata(intf, NULL); |
334 | if (kbd) { | 327 | if (kbd) { |
335 | usb_kill_urb(kbd->irq); | 328 | usb_kill_urb(kbd->irq); |
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index 01155bbddd43..1ec41b5effe6 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c | |||
@@ -9,18 +9,18 @@ | |||
9 | /* | 9 | /* |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
14 | * | 14 | * |
15 | * This program is distributed in the hope that it will be useful, | 15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
19 | * | 19 | * |
20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 | * | 23 | * |
24 | * Should you need to contact me, the author, you can do so either by | 24 | * Should you need to contact me, the author, you can do so either by |
25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
@@ -51,7 +51,6 @@ struct usb_mouse { | |||
51 | struct usb_device *usbdev; | 51 | struct usb_device *usbdev; |
52 | struct input_dev dev; | 52 | struct input_dev dev; |
53 | struct urb *irq; | 53 | struct urb *irq; |
54 | int open; | ||
55 | 54 | ||
56 | signed char *data; | 55 | signed char *data; |
57 | dma_addr_t data_dma; | 56 | dma_addr_t data_dma; |
@@ -101,14 +100,9 @@ static int usb_mouse_open(struct input_dev *dev) | |||
101 | { | 100 | { |
102 | struct usb_mouse *mouse = dev->private; | 101 | struct usb_mouse *mouse = dev->private; |
103 | 102 | ||
104 | if (mouse->open++) | ||
105 | return 0; | ||
106 | |||
107 | mouse->irq->dev = mouse->usbdev; | 103 | mouse->irq->dev = mouse->usbdev; |
108 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) { | 104 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) |
109 | mouse->open--; | ||
110 | return -EIO; | 105 | return -EIO; |
111 | } | ||
112 | 106 | ||
113 | return 0; | 107 | return 0; |
114 | } | 108 | } |
@@ -117,8 +111,7 @@ static void usb_mouse_close(struct input_dev *dev) | |||
117 | { | 111 | { |
118 | struct usb_mouse *mouse = dev->private; | 112 | struct usb_mouse *mouse = dev->private; |
119 | 113 | ||
120 | if (!--mouse->open) | 114 | usb_kill_urb(mouse->irq); |
121 | usb_kill_urb(mouse->irq); | ||
122 | } | 115 | } |
123 | 116 | ||
124 | static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) | 117 | static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) |
@@ -132,19 +125,19 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ | |||
132 | 125 | ||
133 | interface = intf->cur_altsetting; | 126 | interface = intf->cur_altsetting; |
134 | 127 | ||
135 | if (interface->desc.bNumEndpoints != 1) | 128 | if (interface->desc.bNumEndpoints != 1) |
136 | return -ENODEV; | 129 | return -ENODEV; |
137 | 130 | ||
138 | endpoint = &interface->endpoint[0].desc; | 131 | endpoint = &interface->endpoint[0].desc; |
139 | if (!(endpoint->bEndpointAddress & 0x80)) | 132 | if (!(endpoint->bEndpointAddress & 0x80)) |
140 | return -ENODEV; | 133 | return -ENODEV; |
141 | if ((endpoint->bmAttributes & 3) != 3) | 134 | if ((endpoint->bmAttributes & 3) != 3) |
142 | return -ENODEV; | 135 | return -ENODEV; |
143 | 136 | ||
144 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | 137 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); |
145 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | 138 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); |
146 | 139 | ||
147 | if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) | 140 | if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) |
148 | return -ENOMEM; | 141 | return -ENOMEM; |
149 | memset(mouse, 0, sizeof(struct usb_mouse)); | 142 | memset(mouse, 0, sizeof(struct usb_mouse)); |
150 | 143 | ||
@@ -209,7 +202,7 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ | |||
209 | static void usb_mouse_disconnect(struct usb_interface *intf) | 202 | static void usb_mouse_disconnect(struct usb_interface *intf) |
210 | { | 203 | { |
211 | struct usb_mouse *mouse = usb_get_intfdata (intf); | 204 | struct usb_mouse *mouse = usb_get_intfdata (intf); |
212 | 205 | ||
213 | usb_set_intfdata(intf, NULL); | 206 | usb_set_intfdata(intf, NULL); |
214 | if (mouse) { | 207 | if (mouse) { |
215 | usb_kill_urb(mouse->irq); | 208 | usb_kill_urb(mouse->irq); |
@@ -238,7 +231,7 @@ static struct usb_driver usb_mouse_driver = { | |||
238 | static int __init usb_mouse_init(void) | 231 | static int __init usb_mouse_init(void) |
239 | { | 232 | { |
240 | int retval = usb_register(&usb_mouse_driver); | 233 | int retval = usb_register(&usb_mouse_driver); |
241 | if (retval == 0) | 234 | if (retval == 0) |
242 | info(DRIVER_VERSION ":" DRIVER_DESC); | 235 | info(DRIVER_VERSION ":" DRIVER_DESC); |
243 | return retval; | 236 | return retval; |
244 | } | 237 | } |
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index fec04dda088e..f6b34af66b3d 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> | 9 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> |
10 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> | 10 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> |
11 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> | 11 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> |
12 | * Copyright (c) 2002-2004 Ping Cheng <pingc@wacom.com> | 12 | * Copyright (c) 2002-2005 Ping Cheng <pingc@wacom.com> |
13 | * | 13 | * |
14 | * ChangeLog: | 14 | * ChangeLog: |
15 | * v0.1 (vp) - Initial release | 15 | * v0.1 (vp) - Initial release |
@@ -18,7 +18,7 @@ | |||
18 | * v0.4 (sm) - Support for more Intuos models, menustrip | 18 | * v0.4 (sm) - Support for more Intuos models, menustrip |
19 | * relative mode, proximity. | 19 | * relative mode, proximity. |
20 | * v0.5 (vp) - Big cleanup, nifty features removed, | 20 | * v0.5 (vp) - Big cleanup, nifty features removed, |
21 | * they belong in userspace | 21 | * they belong in userspace |
22 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, | 22 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, |
23 | * use input_report_key instead of report_btn and | 23 | * use input_report_key instead of report_btn and |
24 | * other cleanups | 24 | * other cleanups |
@@ -51,6 +51,9 @@ | |||
51 | * - Cleanups here and there | 51 | * - Cleanups here and there |
52 | * v1.30.1 (pi) - Added Graphire3 support | 52 | * v1.30.1 (pi) - Added Graphire3 support |
53 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... | 53 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... |
54 | * v1.43 (pc) - Added support for Cintiq 21UX | ||
55 | - Fixed a Graphire bug | ||
56 | - Merged wacom_intuos3_irq into wacom_intuos_irq | ||
54 | */ | 57 | */ |
55 | 58 | ||
56 | /* | 59 | /* |
@@ -72,7 +75,7 @@ | |||
72 | /* | 75 | /* |
73 | * Version Information | 76 | * Version Information |
74 | */ | 77 | */ |
75 | #define DRIVER_VERSION "v1.40" | 78 | #define DRIVER_VERSION "v1.43" |
76 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | 79 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
77 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | 80 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" |
78 | #define DRIVER_LICENSE "GPL" | 81 | #define DRIVER_LICENSE "GPL" |
@@ -83,6 +86,16 @@ MODULE_LICENSE(DRIVER_LICENSE); | |||
83 | 86 | ||
84 | #define USB_VENDOR_ID_WACOM 0x056a | 87 | #define USB_VENDOR_ID_WACOM 0x056a |
85 | 88 | ||
89 | enum { | ||
90 | PENPARTNER = 0, | ||
91 | GRAPHIRE, | ||
92 | PL, | ||
93 | INTUOS, | ||
94 | INTUOS3, | ||
95 | CINTIQ, | ||
96 | MAX_TYPE | ||
97 | }; | ||
98 | |||
86 | struct wacom_features { | 99 | struct wacom_features { |
87 | char *name; | 100 | char *name; |
88 | int pktlen; | 101 | int pktlen; |
@@ -102,7 +115,6 @@ struct wacom { | |||
102 | struct urb *irq; | 115 | struct urb *irq; |
103 | struct wacom_features *features; | 116 | struct wacom_features *features; |
104 | int tool[2]; | 117 | int tool[2]; |
105 | int open; | ||
106 | __u32 serial[2]; | 118 | __u32 serial[2]; |
107 | char phys[32]; | 119 | char phys[32]; |
108 | }; | 120 | }; |
@@ -149,7 +161,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
149 | prox = data[1] & 0x40; | 161 | prox = data[1] & 0x40; |
150 | 162 | ||
151 | input_regs(dev, regs); | 163 | input_regs(dev, regs); |
152 | 164 | ||
153 | if (prox) { | 165 | if (prox) { |
154 | 166 | ||
155 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | 167 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); |
@@ -166,8 +178,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
166 | if (!wacom->tool[0]) { | 178 | if (!wacom->tool[0]) { |
167 | /* Going into proximity select tool */ | 179 | /* Going into proximity select tool */ |
168 | wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 180 | wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
169 | } | 181 | } else { |
170 | else { | ||
171 | /* was entered with stylus2 pressed */ | 182 | /* was entered with stylus2 pressed */ |
172 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) { | 183 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) { |
173 | /* report out proximity for previous tool */ | 184 | /* report out proximity for previous tool */ |
@@ -182,16 +193,15 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
182 | wacom->tool[1] = BTN_TOOL_PEN; | 193 | wacom->tool[1] = BTN_TOOL_PEN; |
183 | } | 194 | } |
184 | input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */ | 195 | input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */ |
185 | input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 7) | ((__u32)(data[1] & 0x03) << 14)); | 196 | input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); |
186 | input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 7) | ((__u32)(data[4] & 0x03) << 14)); | 197 | input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); |
187 | input_report_abs(dev, ABS_PRESSURE, pressure); | 198 | input_report_abs(dev, ABS_PRESSURE, pressure); |
188 | 199 | ||
189 | input_report_key(dev, BTN_TOUCH, data[4] & 0x08); | 200 | input_report_key(dev, BTN_TOUCH, data[4] & 0x08); |
190 | input_report_key(dev, BTN_STYLUS, data[4] & 0x10); | 201 | input_report_key(dev, BTN_STYLUS, data[4] & 0x10); |
191 | /* Only allow the stylus2 button to be reported for the pen tool. */ | 202 | /* Only allow the stylus2 button to be reported for the pen tool. */ |
192 | input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); | 203 | input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); |
193 | } | 204 | } else { |
194 | else { | ||
195 | /* report proximity-out of a (valid) tool */ | 205 | /* report proximity-out of a (valid) tool */ |
196 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | 206 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { |
197 | /* Unknown tool selected default to pen tool */ | 207 | /* Unknown tool selected default to pen tool */ |
@@ -203,7 +213,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
203 | wacom->tool[0] = prox; /* Save proximity state */ | 213 | wacom->tool[0] = prox; /* Save proximity state */ |
204 | input_sync(dev); | 214 | input_sync(dev); |
205 | 215 | ||
206 | exit: | 216 | exit: |
207 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 217 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
208 | if (retval) | 218 | if (retval) |
209 | err ("%s - usb_submit_urb failed with result %d", | 219 | err ("%s - usb_submit_urb failed with result %d", |
@@ -232,20 +242,16 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) | |||
232 | goto exit; | 242 | goto exit; |
233 | } | 243 | } |
234 | 244 | ||
235 | if (data[0] != 2) | 245 | if (data[0] != 2) { |
236 | { | ||
237 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | 246 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); |
238 | goto exit; | 247 | goto exit; |
239 | } | 248 | } |
240 | 249 | ||
241 | input_regs(dev, regs); | 250 | input_regs(dev, regs); |
242 | if (data[1] & 0x04) | 251 | if (data[1] & 0x04) { |
243 | { | ||
244 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20); | 252 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20); |
245 | input_report_key(dev, BTN_TOUCH, data[1] & 0x08); | 253 | input_report_key(dev, BTN_TOUCH, data[1] & 0x08); |
246 | } | 254 | } else { |
247 | else | ||
248 | { | ||
249 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); | 255 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); |
250 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | 256 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); |
251 | } | 257 | } |
@@ -257,7 +263,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) | |||
257 | 263 | ||
258 | input_sync(dev); | 264 | input_sync(dev); |
259 | 265 | ||
260 | exit: | 266 | exit: |
261 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 267 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
262 | if (retval) | 268 | if (retval) |
263 | err ("%s - usb_submit_urb failed with result %d", | 269 | err ("%s - usb_submit_urb failed with result %d", |
@@ -300,7 +306,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) | |||
300 | input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); | 306 | input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); |
301 | input_sync(dev); | 307 | input_sync(dev); |
302 | 308 | ||
303 | exit: | 309 | exit: |
304 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 310 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
305 | if (retval) | 311 | if (retval) |
306 | err ("%s - usb_submit_urb failed with result %d", | 312 | err ("%s - usb_submit_urb failed with result %d", |
@@ -340,47 +346,47 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
340 | 346 | ||
341 | input_regs(dev, regs); | 347 | input_regs(dev, regs); |
342 | 348 | ||
343 | switch ((data[1] >> 5) & 3) { | 349 | if (data[1] & 0x10) { /* in prox */ |
344 | 350 | ||
345 | case 0: /* Pen */ | 351 | switch ((data[1] >> 5) & 3) { |
346 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80); | ||
347 | break; | ||
348 | 352 | ||
349 | case 1: /* Rubber */ | 353 | case 0: /* Pen */ |
350 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80); | 354 | wacom->tool[0] = BTN_TOOL_PEN; |
351 | break; | 355 | break; |
352 | |||
353 | case 2: /* Mouse with wheel */ | ||
354 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); | ||
355 | input_report_rel(dev, REL_WHEEL, (signed char) data[6]); | ||
356 | /* fall through */ | ||
357 | 356 | ||
358 | case 3: /* Mouse without wheel */ | 357 | case 1: /* Rubber */ |
359 | input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24); | 358 | wacom->tool[0] = BTN_TOOL_RUBBER; |
360 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | 359 | break; |
361 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | ||
362 | input_report_abs(dev, ABS_DISTANCE, data[7]); | ||
363 | 360 | ||
364 | input_report_abs(dev, ABS_X, x); | 361 | case 2: /* Mouse with wheel */ |
365 | input_report_abs(dev, ABS_Y, y); | 362 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); |
363 | input_report_rel(dev, REL_WHEEL, (signed char) data[6]); | ||
364 | /* fall through */ | ||
366 | 365 | ||
367 | input_sync(dev); | 366 | case 3: /* Mouse without wheel */ |
368 | goto exit; | 367 | wacom->tool[0] = BTN_TOOL_MOUSE; |
368 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | ||
369 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | ||
370 | input_report_abs(dev, ABS_DISTANCE, data[7]); | ||
371 | break; | ||
372 | } | ||
369 | } | 373 | } |
370 | 374 | ||
371 | if (data[1] & 0x80) { | 375 | if (data[1] & 0x80) { |
372 | input_report_abs(dev, ABS_X, x); | 376 | input_report_abs(dev, ABS_X, x); |
373 | input_report_abs(dev, ABS_Y, y); | 377 | input_report_abs(dev, ABS_Y, y); |
374 | } | 378 | } |
379 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { | ||
380 | input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); | ||
381 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | ||
382 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); | ||
383 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); | ||
384 | } | ||
375 | 385 | ||
376 | input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); | 386 | input_report_key(dev, wacom->tool[0], data[1] & 0x10); |
377 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | ||
378 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); | ||
379 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); | ||
380 | |||
381 | input_sync(dev); | 387 | input_sync(dev); |
382 | 388 | ||
383 | exit: | 389 | exit: |
384 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 390 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
385 | if (retval) | 391 | if (retval) |
386 | err ("%s - usb_submit_urb failed with result %d", | 392 | err ("%s - usb_submit_urb failed with result %d", |
@@ -398,14 +404,13 @@ static int wacom_intuos_inout(struct urb *urb) | |||
398 | idx = data[1] & 0x01; | 404 | idx = data[1] & 0x01; |
399 | 405 | ||
400 | /* Enter report */ | 406 | /* Enter report */ |
401 | if ((data[1] & 0xfc) == 0xc0) | 407 | if ((data[1] & 0xfc) == 0xc0) { |
402 | { | ||
403 | /* serial number of the tool */ | 408 | /* serial number of the tool */ |
404 | wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) + | 409 | wacom->serial[idx] = ((data[3] & 0x0f) << 28) + |
405 | ((__u32)data[4] << 20) + ((__u32)data[5] << 12) + | 410 | (data[4] << 20) + (data[5] << 12) + |
406 | ((__u32)data[6] << 4) + (data[7] >> 4); | 411 | (data[6] << 4) + (data[7] >> 4); |
407 | 412 | ||
408 | switch (((__u32)data[2] << 4) | (data[3] >> 4)) { | 413 | switch ((data[2] << 4) | (data[3] >> 4)) { |
409 | case 0x812: /* Inking pen */ | 414 | case 0x812: /* Inking pen */ |
410 | case 0x801: /* Intuos3 Inking pen */ | 415 | case 0x801: /* Intuos3 Inking pen */ |
411 | case 0x012: | 416 | case 0x012: |
@@ -449,7 +454,7 @@ static int wacom_intuos_inout(struct urb *urb) | |||
449 | case 0x112: | 454 | case 0x112: |
450 | case 0x913: /* Intuos3 Airbrush */ | 455 | case 0x913: /* Intuos3 Airbrush */ |
451 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | 456 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; |
452 | break; /* Airbrush */ | 457 | break; |
453 | default: /* Unknown tool */ | 458 | default: /* Unknown tool */ |
454 | wacom->tool[idx] = BTN_TOOL_PEN; | 459 | wacom->tool[idx] = BTN_TOOL_PEN; |
455 | } | 460 | } |
@@ -478,9 +483,8 @@ static void wacom_intuos_general(struct urb *urb) | |||
478 | unsigned int t; | 483 | unsigned int t; |
479 | 484 | ||
480 | /* general pen packet */ | 485 | /* general pen packet */ |
481 | if ((data[1] & 0xb8) == 0xa0) | 486 | if ((data[1] & 0xb8) == 0xa0) { |
482 | { | 487 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
483 | t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); | ||
484 | input_report_abs(dev, ABS_PRESSURE, t); | 488 | input_report_abs(dev, ABS_PRESSURE, t); |
485 | input_report_abs(dev, ABS_TILT_X, | 489 | input_report_abs(dev, ABS_TILT_X, |
486 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 490 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); |
@@ -491,10 +495,9 @@ static void wacom_intuos_general(struct urb *urb) | |||
491 | } | 495 | } |
492 | 496 | ||
493 | /* airbrush second packet */ | 497 | /* airbrush second packet */ |
494 | if ((data[1] & 0xbc) == 0xb4) | 498 | if ((data[1] & 0xbc) == 0xb4) { |
495 | { | ||
496 | input_report_abs(dev, ABS_WHEEL, | 499 | input_report_abs(dev, ABS_WHEEL, |
497 | ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); | 500 | (data[6] << 2) | ((data[7] >> 6) & 3)); |
498 | input_report_abs(dev, ABS_TILT_X, | 501 | input_report_abs(dev, ABS_TILT_X, |
499 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 502 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); |
500 | input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); | 503 | input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); |
@@ -526,7 +529,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | |||
526 | goto exit; | 529 | goto exit; |
527 | } | 530 | } |
528 | 531 | ||
529 | if (data[0] != 2 && data[0] != 5 && data[0] != 6) { | 532 | if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { |
530 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | 533 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); |
531 | goto exit; | 534 | goto exit; |
532 | } | 535 | } |
@@ -536,107 +539,10 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | |||
536 | /* tool number */ | 539 | /* tool number */ |
537 | idx = data[1] & 0x01; | 540 | idx = data[1] & 0x01; |
538 | 541 | ||
539 | /* process in/out prox events */ | ||
540 | if (wacom_intuos_inout(urb)) goto exit; | ||
541 | |||
542 | input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); | ||
543 | input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); | ||
544 | input_report_abs(dev, ABS_DISTANCE, data[9]); | ||
545 | |||
546 | /* process general packets */ | ||
547 | wacom_intuos_general(urb); | ||
548 | |||
549 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */ | ||
550 | |||
551 | if (data[1] & 0x02) { /* Rotation packet */ | ||
552 | |||
553 | t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); | ||
554 | input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2); | ||
555 | |||
556 | } else { | ||
557 | |||
558 | if ((data[1] & 0x10) == 0) { /* 4D mouse packets */ | ||
559 | |||
560 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
561 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
562 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
563 | |||
564 | input_report_key(dev, BTN_SIDE, data[8] & 0x20); | ||
565 | input_report_key(dev, BTN_EXTRA, data[8] & 0x10); | ||
566 | t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); | ||
567 | input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | ||
568 | |||
569 | } else { | ||
570 | if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */ | ||
571 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); | ||
572 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); | ||
573 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); | ||
574 | input_report_rel(dev, REL_WHEEL, | ||
575 | (-(__u32)(data[8] & 0x01) + (__u32)((data[8] & 0x02) >> 1))); | ||
576 | } | ||
577 | else { /* Lens cursor packets */ | ||
578 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
579 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
580 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
581 | input_report_key(dev, BTN_SIDE, data[8] & 0x10); | ||
582 | input_report_key(dev, BTN_EXTRA, data[8] & 0x08); | ||
583 | } | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | input_report_key(dev, wacom->tool[idx], 1); | ||
589 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
590 | input_sync(dev); | ||
591 | |||
592 | exit: | ||
593 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
594 | if (retval) | ||
595 | err ("%s - usb_submit_urb failed with result %d", | ||
596 | __FUNCTION__, retval); | ||
597 | } | ||
598 | |||
599 | static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs) | ||
600 | { | ||
601 | struct wacom *wacom = urb->context; | ||
602 | unsigned char *data = wacom->data; | ||
603 | struct input_dev *dev = &wacom->dev; | ||
604 | unsigned int t; | ||
605 | int idx, retval; | ||
606 | |||
607 | switch (urb->status) { | ||
608 | case 0: | ||
609 | /* success */ | ||
610 | break; | ||
611 | case -ECONNRESET: | ||
612 | case -ENOENT: | ||
613 | case -ESHUTDOWN: | ||
614 | /* this urb is terminated, clean up */ | ||
615 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
616 | return; | ||
617 | default: | ||
618 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
619 | goto exit; | ||
620 | } | ||
621 | |||
622 | /* check for valid report */ | ||
623 | if (data[0] != 2 && data[0] != 5 && data[0] != 12) | ||
624 | { | ||
625 | printk(KERN_INFO "wacom_intuos3_irq: received unknown report #%d\n", data[0]); | ||
626 | goto exit; | ||
627 | } | ||
628 | |||
629 | input_regs(dev, regs); | ||
630 | |||
631 | /* tool index is always 0 here since there is no dual input tool */ | ||
632 | idx = data[1] & 0x01; | ||
633 | |||
634 | /* pad packets. Works as a second tool and is always in prox */ | 542 | /* pad packets. Works as a second tool and is always in prox */ |
635 | if (data[0] == 12) | 543 | if (data[0] == 12) { |
636 | { | ||
637 | /* initiate the pad as a device */ | 544 | /* initiate the pad as a device */ |
638 | if (wacom->tool[1] != BTN_TOOL_FINGER) | 545 | if (wacom->tool[1] != BTN_TOOL_FINGER) { |
639 | { | ||
640 | wacom->tool[1] = BTN_TOOL_FINGER; | 546 | wacom->tool[1] = BTN_TOOL_FINGER; |
641 | input_report_key(dev, wacom->tool[1], 1); | 547 | input_report_key(dev, wacom->tool[1], 1); |
642 | } | 548 | } |
@@ -656,37 +562,78 @@ static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs) | |||
656 | } | 562 | } |
657 | 563 | ||
658 | /* process in/out prox events */ | 564 | /* process in/out prox events */ |
659 | if (wacom_intuos_inout(urb)) goto exit; | 565 | if (wacom_intuos_inout(urb)) |
566 | goto exit; | ||
660 | 567 | ||
661 | input_report_abs(dev, ABS_X, ((__u32)data[2] << 9) | ((__u32)data[3] << 1) | ((data[9] >> 1) & 1)); | 568 | /* Cintiq doesn't send data when RDY bit isn't set */ |
662 | input_report_abs(dev, ABS_Y, ((__u32)data[4] << 9) | ((__u32)data[5] << 1) | (data[9] & 1)); | 569 | if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) |
663 | input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | 570 | return; |
571 | |||
572 | if (wacom->features->type >= INTUOS3) { | ||
573 | input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); | ||
574 | input_report_abs(dev, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); | ||
575 | input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | ||
576 | } else { | ||
577 | input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); | ||
578 | input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); | ||
579 | input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); | ||
580 | } | ||
664 | 581 | ||
665 | /* process general packets */ | 582 | /* process general packets */ |
666 | wacom_intuos_general(urb); | 583 | wacom_intuos_general(urb); |
667 | 584 | ||
668 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) | 585 | /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */ |
669 | { | 586 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { |
670 | /* Marker pen rotation packet. Reported as wheel due to valuator limitation */ | 587 | |
671 | if (data[1] & 0x02) | 588 | if (data[1] & 0x02) { |
672 | { | 589 | /* Rotation packet */ |
673 | t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); | 590 | if (wacom->features->type >= INTUOS3) { |
674 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | 591 | /* I3 marker pen rotation reported as wheel |
675 | ((t-1) / 2 + 450)) : (450 - t / 2) ; | 592 | * due to valuator limitation |
676 | input_report_abs(dev, ABS_WHEEL, t); | 593 | */ |
677 | } | 594 | t = (data[6] << 3) | ((data[7] >> 5) & 7); |
595 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | ||
596 | ((t-1) / 2 + 450)) : (450 - t / 2) ; | ||
597 | input_report_abs(dev, ABS_WHEEL, t); | ||
598 | } else { | ||
599 | /* 4D mouse rotation packet */ | ||
600 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | ||
601 | input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? | ||
602 | ((t - 1) / 2) : -t / 2); | ||
603 | } | ||
678 | 604 | ||
679 | /* 2D mouse packets */ | 605 | } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) { |
680 | if (wacom->tool[idx] == BTN_TOOL_MOUSE) | 606 | /* 4D mouse packet */ |
681 | { | 607 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); |
608 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
609 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
610 | |||
611 | input_report_key(dev, BTN_SIDE, data[8] & 0x20); | ||
612 | input_report_key(dev, BTN_EXTRA, data[8] & 0x10); | ||
613 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | ||
614 | input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | ||
615 | |||
616 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | ||
617 | /* 2D mouse packet */ | ||
682 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); | 618 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); |
683 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); | 619 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); |
684 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); | 620 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); |
685 | input_report_key(dev, BTN_SIDE, data[8] & 0x40); | 621 | input_report_rel(dev, REL_WHEEL, ((data[8] & 0x02) >> 1) |
686 | input_report_key(dev, BTN_EXTRA, data[8] & 0x20); | 622 | - (data[8] & 0x01)); |
687 | /* mouse wheel is positive when rolled backwards */ | 623 | |
688 | input_report_rel(dev, REL_WHEEL, ((__u32)((data[8] & 0x02) >> 1) | 624 | /* I3 2D mouse side buttons */ |
689 | - (__u32)(data[8] & 0x01))); | 625 | if (wacom->features->type == INTUOS3) { |
626 | input_report_key(dev, BTN_SIDE, data[8] & 0x40); | ||
627 | input_report_key(dev, BTN_EXTRA, data[8] & 0x20); | ||
628 | } | ||
629 | |||
630 | } else if (wacom->features->type < INTUOS3) { | ||
631 | /* Lens cursor packets */ | ||
632 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
633 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
634 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
635 | input_report_key(dev, BTN_SIDE, data[8] & 0x10); | ||
636 | input_report_key(dev, BTN_EXTRA, data[8] & 0x08); | ||
690 | } | 637 | } |
691 | } | 638 | } |
692 | 639 | ||
@@ -702,35 +649,36 @@ exit: | |||
702 | } | 649 | } |
703 | 650 | ||
704 | static struct wacom_features wacom_features[] = { | 651 | static struct wacom_features wacom_features[] = { |
705 | { "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq }, | 652 | { "Wacom Penpartner", 7, 5040, 3780, 255, 32, PENPARTNER, wacom_penpartner_irq }, |
706 | { "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, | 653 | { "Wacom Graphire", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
707 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, | 654 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
708 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, 1, wacom_graphire_irq }, | 655 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
709 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, 1, wacom_graphire_irq }, | 656 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
710 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, 1, wacom_graphire_irq }, | 657 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
711 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, | 658 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, |
712 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | 659 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, |
713 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, | 660 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, |
714 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, | 661 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
715 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, | 662 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
716 | { "Wacom PL400", 8, 5408, 4056, 255, 32, 3, wacom_pl_irq }, | 663 | { "Wacom PL400", 8, 5408, 4056, 255, 32, PL, wacom_pl_irq }, |
717 | { "Wacom PL500", 8, 6144, 4608, 255, 32, 3, wacom_pl_irq }, | 664 | { "Wacom PL500", 8, 6144, 4608, 255, 32, PL, wacom_pl_irq }, |
718 | { "Wacom PL600", 8, 6126, 4604, 255, 32, 3, wacom_pl_irq }, | 665 | { "Wacom PL600", 8, 6126, 4604, 255, 32, PL, wacom_pl_irq }, |
719 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, 3, wacom_pl_irq }, | 666 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_pl_irq }, |
720 | { "Wacom PL550", 8, 6144, 4608, 511, 32, 3, wacom_pl_irq }, | 667 | { "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_pl_irq }, |
721 | { "Wacom PL800", 8, 7220, 5780, 511, 32, 3, wacom_pl_irq }, | 668 | { "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq }, |
722 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, | 669 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, |
723 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | 670 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, |
724 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, | 671 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, |
725 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, | 672 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
726 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, | 673 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
727 | { "Wacom Volito", 8, 5104, 3712, 511, 32, 1, wacom_graphire_irq }, | 674 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
728 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, 3, wacom_ptu_irq }, | 675 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq }, |
729 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, 4, wacom_intuos3_irq }, | 676 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq }, |
730 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq }, | 677 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq }, |
731 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq }, | 678 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq }, |
732 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | 679 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq }, |
733 | { } | 680 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, |
681 | { } | ||
734 | }; | 682 | }; |
735 | 683 | ||
736 | static struct usb_device_id wacom_ids[] = { | 684 | static struct usb_device_id wacom_ids[] = { |
@@ -761,6 +709,7 @@ static struct usb_device_id wacom_ids[] = { | |||
761 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, | 709 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, |
762 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, | 710 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, |
763 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, | 711 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, |
712 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, | ||
764 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | 713 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, |
765 | { } | 714 | { } |
766 | }; | 715 | }; |
@@ -771,14 +720,9 @@ static int wacom_open(struct input_dev *dev) | |||
771 | { | 720 | { |
772 | struct wacom *wacom = dev->private; | 721 | struct wacom *wacom = dev->private; |
773 | 722 | ||
774 | if (wacom->open++) | ||
775 | return 0; | ||
776 | |||
777 | wacom->irq->dev = wacom->usbdev; | 723 | wacom->irq->dev = wacom->usbdev; |
778 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { | 724 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) |
779 | wacom->open--; | ||
780 | return -EIO; | 725 | return -EIO; |
781 | } | ||
782 | 726 | ||
783 | return 0; | 727 | return 0; |
784 | } | 728 | } |
@@ -787,8 +731,7 @@ static void wacom_close(struct input_dev *dev) | |||
787 | { | 731 | { |
788 | struct wacom *wacom = dev->private; | 732 | struct wacom *wacom = dev->private; |
789 | 733 | ||
790 | if (!--wacom->open) | 734 | usb_kill_urb(wacom->irq); |
791 | usb_kill_urb(wacom->irq); | ||
792 | } | 735 | } |
793 | 736 | ||
794 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 737 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
@@ -823,32 +766,33 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
823 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); | 766 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); |
824 | 767 | ||
825 | switch (wacom->features->type) { | 768 | switch (wacom->features->type) { |
826 | case 1: | 769 | case GRAPHIRE: |
827 | wacom->dev.evbit[0] |= BIT(EV_REL); | 770 | wacom->dev.evbit[0] |= BIT(EV_REL); |
828 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); | 771 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); |
829 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); | 772 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); |
830 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | 773 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); |
831 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); | 774 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); |
832 | break; | 775 | break; |
833 | 776 | ||
834 | case 4: /* new functions for Intuos3 */ | 777 | case INTUOS3: |
778 | case CINTIQ: | ||
835 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | 779 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); |
836 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | 780 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); |
837 | wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY); | 781 | wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY); |
838 | /* fall through */ | 782 | /* fall through */ |
839 | 783 | ||
840 | case 2: | 784 | case INTUOS: |
841 | wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); | 785 | wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); |
842 | wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); | 786 | wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); |
843 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); | 787 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); |
844 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); | 788 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); |
845 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | 789 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) |
846 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); | 790 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); |
847 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); | 791 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); |
848 | break; | 792 | break; |
849 | 793 | ||
850 | case 3: | 794 | case PL: |
851 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); | 795 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); |
852 | break; | 796 | break; |
853 | } | 797 | } |
854 | 798 | ||
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index d65edb22e545..a7fa1b17dcfe 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c | |||
@@ -104,13 +104,12 @@ MODULE_DEVICE_TABLE (usb, xpad_table); | |||
104 | struct usb_xpad { | 104 | struct usb_xpad { |
105 | struct input_dev dev; /* input device interface */ | 105 | struct input_dev dev; /* input device interface */ |
106 | struct usb_device *udev; /* usb device */ | 106 | struct usb_device *udev; /* usb device */ |
107 | 107 | ||
108 | struct urb *irq_in; /* urb for interrupt in report */ | 108 | struct urb *irq_in; /* urb for interrupt in report */ |
109 | unsigned char *idata; /* input data */ | 109 | unsigned char *idata; /* input data */ |
110 | dma_addr_t idata_dma; | 110 | dma_addr_t idata_dma; |
111 | 111 | ||
112 | char phys[65]; /* physical device path */ | 112 | char phys[65]; /* physical device path */ |
113 | int open_count; /* reference count */ | ||
114 | }; | 113 | }; |
115 | 114 | ||
116 | /* | 115 | /* |
@@ -128,35 +127,35 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
128 | struct input_dev *dev = &xpad->dev; | 127 | struct input_dev *dev = &xpad->dev; |
129 | 128 | ||
130 | input_regs(dev, regs); | 129 | input_regs(dev, regs); |
131 | 130 | ||
132 | /* left stick */ | 131 | /* left stick */ |
133 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); | 132 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); |
134 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); | 133 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); |
135 | 134 | ||
136 | /* right stick */ | 135 | /* right stick */ |
137 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); | 136 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); |
138 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); | 137 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); |
139 | 138 | ||
140 | /* triggers left/right */ | 139 | /* triggers left/right */ |
141 | input_report_abs(dev, ABS_Z, data[10]); | 140 | input_report_abs(dev, ABS_Z, data[10]); |
142 | input_report_abs(dev, ABS_RZ, data[11]); | 141 | input_report_abs(dev, ABS_RZ, data[11]); |
143 | 142 | ||
144 | /* digital pad */ | 143 | /* digital pad */ |
145 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | 144 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); |
146 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | 145 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); |
147 | 146 | ||
148 | /* start/back buttons and stick press left/right */ | 147 | /* start/back buttons and stick press left/right */ |
149 | input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); | 148 | input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); |
150 | input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); | 149 | input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); |
151 | input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); | 150 | input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); |
152 | input_report_key(dev, BTN_THUMBR, data[2] >> 7); | 151 | input_report_key(dev, BTN_THUMBR, data[2] >> 7); |
153 | 152 | ||
154 | /* "analog" buttons A, B, X, Y */ | 153 | /* "analog" buttons A, B, X, Y */ |
155 | input_report_key(dev, BTN_A, data[4]); | 154 | input_report_key(dev, BTN_A, data[4]); |
156 | input_report_key(dev, BTN_B, data[5]); | 155 | input_report_key(dev, BTN_B, data[5]); |
157 | input_report_key(dev, BTN_X, data[6]); | 156 | input_report_key(dev, BTN_X, data[6]); |
158 | input_report_key(dev, BTN_Y, data[7]); | 157 | input_report_key(dev, BTN_Y, data[7]); |
159 | 158 | ||
160 | /* "analog" buttons black, white */ | 159 | /* "analog" buttons black, white */ |
161 | input_report_key(dev, BTN_C, data[8]); | 160 | input_report_key(dev, BTN_C, data[8]); |
162 | input_report_key(dev, BTN_Z, data[9]); | 161 | input_report_key(dev, BTN_Z, data[9]); |
@@ -168,7 +167,7 @@ static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) | |||
168 | { | 167 | { |
169 | struct usb_xpad *xpad = urb->context; | 168 | struct usb_xpad *xpad = urb->context; |
170 | int retval; | 169 | int retval; |
171 | 170 | ||
172 | switch (urb->status) { | 171 | switch (urb->status) { |
173 | case 0: | 172 | case 0: |
174 | /* success */ | 173 | /* success */ |
@@ -183,7 +182,7 @@ static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) | |||
183 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 182 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); |
184 | goto exit; | 183 | goto exit; |
185 | } | 184 | } |
186 | 185 | ||
187 | xpad_process_packet(xpad, 0, xpad->idata, regs); | 186 | xpad_process_packet(xpad, 0, xpad->idata, regs); |
188 | 187 | ||
189 | exit: | 188 | exit: |
@@ -196,25 +195,19 @@ exit: | |||
196 | static int xpad_open (struct input_dev *dev) | 195 | static int xpad_open (struct input_dev *dev) |
197 | { | 196 | { |
198 | struct usb_xpad *xpad = dev->private; | 197 | struct usb_xpad *xpad = dev->private; |
199 | 198 | ||
200 | if (xpad->open_count++) | ||
201 | return 0; | ||
202 | |||
203 | xpad->irq_in->dev = xpad->udev; | 199 | xpad->irq_in->dev = xpad->udev; |
204 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) { | 200 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) |
205 | xpad->open_count--; | ||
206 | return -EIO; | 201 | return -EIO; |
207 | } | 202 | |
208 | |||
209 | return 0; | 203 | return 0; |
210 | } | 204 | } |
211 | 205 | ||
212 | static void xpad_close (struct input_dev *dev) | 206 | static void xpad_close (struct input_dev *dev) |
213 | { | 207 | { |
214 | struct usb_xpad *xpad = dev->private; | 208 | struct usb_xpad *xpad = dev->private; |
215 | 209 | ||
216 | if (!--xpad->open_count) | 210 | usb_kill_urb(xpad->irq_in); |
217 | usb_kill_urb(xpad->irq_in); | ||
218 | } | 211 | } |
219 | 212 | ||
220 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) | 213 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) |
@@ -224,19 +217,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
224 | struct usb_endpoint_descriptor *ep_irq_in; | 217 | struct usb_endpoint_descriptor *ep_irq_in; |
225 | char path[64]; | 218 | char path[64]; |
226 | int i; | 219 | int i; |
227 | 220 | ||
228 | for (i = 0; xpad_device[i].idVendor; i++) { | 221 | for (i = 0; xpad_device[i].idVendor; i++) { |
229 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && | 222 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && |
230 | (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) | 223 | (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) |
231 | break; | 224 | break; |
232 | } | 225 | } |
233 | 226 | ||
234 | if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { | 227 | if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { |
235 | err("cannot allocate memory for new pad"); | 228 | err("cannot allocate memory for new pad"); |
236 | return -ENOMEM; | 229 | return -ENOMEM; |
237 | } | 230 | } |
238 | memset(xpad, 0, sizeof(struct usb_xpad)); | 231 | memset(xpad, 0, sizeof(struct usb_xpad)); |
239 | 232 | ||
240 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, | 233 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, |
241 | SLAB_ATOMIC, &xpad->idata_dma); | 234 | SLAB_ATOMIC, &xpad->idata_dma); |
242 | if (!xpad->idata) { | 235 | if (!xpad->idata) { |
@@ -251,18 +244,18 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
251 | kfree(xpad); | 244 | kfree(xpad); |
252 | return -ENOMEM; | 245 | return -ENOMEM; |
253 | } | 246 | } |
254 | 247 | ||
255 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; | 248 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; |
256 | 249 | ||
257 | usb_fill_int_urb(xpad->irq_in, udev, | 250 | usb_fill_int_urb(xpad->irq_in, udev, |
258 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), | 251 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), |
259 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, | 252 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, |
260 | xpad, ep_irq_in->bInterval); | 253 | xpad, ep_irq_in->bInterval); |
261 | xpad->irq_in->transfer_dma = xpad->idata_dma; | 254 | xpad->irq_in->transfer_dma = xpad->idata_dma; |
262 | xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 255 | xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
263 | 256 | ||
264 | xpad->udev = udev; | 257 | xpad->udev = udev; |
265 | 258 | ||
266 | xpad->dev.id.bustype = BUS_USB; | 259 | xpad->dev.id.bustype = BUS_USB; |
267 | xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | 260 | xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); |
268 | xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); | 261 | xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); |
@@ -273,21 +266,21 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
273 | xpad->dev.phys = xpad->phys; | 266 | xpad->dev.phys = xpad->phys; |
274 | xpad->dev.open = xpad_open; | 267 | xpad->dev.open = xpad_open; |
275 | xpad->dev.close = xpad_close; | 268 | xpad->dev.close = xpad_close; |
276 | 269 | ||
277 | usb_make_path(udev, path, 64); | 270 | usb_make_path(udev, path, 64); |
278 | snprintf(xpad->phys, 64, "%s/input0", path); | 271 | snprintf(xpad->phys, 64, "%s/input0", path); |
279 | 272 | ||
280 | xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 273 | xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
281 | 274 | ||
282 | for (i = 0; xpad_btn[i] >= 0; i++) | 275 | for (i = 0; xpad_btn[i] >= 0; i++) |
283 | set_bit(xpad_btn[i], xpad->dev.keybit); | 276 | set_bit(xpad_btn[i], xpad->dev.keybit); |
284 | 277 | ||
285 | for (i = 0; xpad_abs[i] >= 0; i++) { | 278 | for (i = 0; xpad_abs[i] >= 0; i++) { |
286 | 279 | ||
287 | signed short t = xpad_abs[i]; | 280 | signed short t = xpad_abs[i]; |
288 | 281 | ||
289 | set_bit(t, xpad->dev.absbit); | 282 | set_bit(t, xpad->dev.absbit); |
290 | 283 | ||
291 | switch (t) { | 284 | switch (t) { |
292 | case ABS_X: | 285 | case ABS_X: |
293 | case ABS_Y: | 286 | case ABS_Y: |
@@ -310,11 +303,11 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
310 | break; | 303 | break; |
311 | } | 304 | } |
312 | } | 305 | } |
313 | 306 | ||
314 | input_register_device(&xpad->dev); | 307 | input_register_device(&xpad->dev); |
315 | 308 | ||
316 | printk(KERN_INFO "input: %s on %s", xpad->dev.name, path); | 309 | printk(KERN_INFO "input: %s on %s", xpad->dev.name, path); |
317 | 310 | ||
318 | usb_set_intfdata(intf, xpad); | 311 | usb_set_intfdata(intf, xpad); |
319 | return 0; | 312 | return 0; |
320 | } | 313 | } |
@@ -322,7 +315,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
322 | static void xpad_disconnect(struct usb_interface *intf) | 315 | static void xpad_disconnect(struct usb_interface *intf) |
323 | { | 316 | { |
324 | struct usb_xpad *xpad = usb_get_intfdata (intf); | 317 | struct usb_xpad *xpad = usb_get_intfdata (intf); |
325 | 318 | ||
326 | usb_set_intfdata(intf, NULL); | 319 | usb_set_intfdata(intf, NULL); |
327 | if (xpad) { | 320 | if (xpad) { |
328 | usb_kill_urb(xpad->irq_in); | 321 | usb_kill_urb(xpad->irq_in); |
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c index ae455c8e3702..7398a7f19c1e 100644 --- a/drivers/usb/media/stv680.c +++ b/drivers/usb/media/stv680.c | |||
@@ -1375,9 +1375,13 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id | |||
1375 | (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) { | 1375 | (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) { |
1376 | camera_name = "STV0680"; | 1376 | camera_name = "STV0680"; |
1377 | PDEBUG (0, "STV(i): STV0680 camera found."); | 1377 | PDEBUG (0, "STV(i): STV0680 camera found."); |
1378 | } else if ((le16_to_cpu(dev->descriptor.idVendor) == USB_CREATIVEGOMINI_VENDOR_ID) && | ||
1379 | (le16_to_cpu(dev->descriptor.idProduct) == USB_CREATIVEGOMINI_PRODUCT_ID)) { | ||
1380 | camera_name = "Creative WebCam Go Mini"; | ||
1381 | PDEBUG (0, "STV(i): Creative WebCam Go Mini found."); | ||
1378 | } else { | 1382 | } else { |
1379 | PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values."); | 1383 | PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 or Creative WebCam Go Mini values."); |
1380 | PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer."); | 1384 | PDEBUG (0, "STV(e): Check that the STV0680 or Creative WebCam Go Mini camera is connected to the computer."); |
1381 | retval = -ENODEV; | 1385 | retval = -ENODEV; |
1382 | goto error; | 1386 | goto error; |
1383 | } | 1387 | } |
diff --git a/drivers/usb/media/stv680.h b/drivers/usb/media/stv680.h index 7e0e314dcf12..445940612603 100644 --- a/drivers/usb/media/stv680.h +++ b/drivers/usb/media/stv680.h | |||
@@ -41,12 +41,17 @@ | |||
41 | 41 | ||
42 | #define USB_PENCAM_VENDOR_ID 0x0553 | 42 | #define USB_PENCAM_VENDOR_ID 0x0553 |
43 | #define USB_PENCAM_PRODUCT_ID 0x0202 | 43 | #define USB_PENCAM_PRODUCT_ID 0x0202 |
44 | |||
45 | #define USB_CREATIVEGOMINI_VENDOR_ID 0x041e | ||
46 | #define USB_CREATIVEGOMINI_PRODUCT_ID 0x4007 | ||
47 | |||
44 | #define PENCAM_TIMEOUT 1000 | 48 | #define PENCAM_TIMEOUT 1000 |
45 | /* fmt 4 */ | 49 | /* fmt 4 */ |
46 | #define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24 | 50 | #define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24 |
47 | 51 | ||
48 | static struct usb_device_id device_table[] = { | 52 | static struct usb_device_id device_table[] = { |
49 | {USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)}, | 53 | {USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)}, |
54 | {USB_DEVICE (USB_CREATIVEGOMINI_VENDOR_ID, USB_CREATIVEGOMINI_PRODUCT_ID)}, | ||
50 | {} | 55 | {} |
51 | }; | 56 | }; |
52 | MODULE_DEVICE_TABLE (usb, device_table); | 57 | MODULE_DEVICE_TABLE (usb, device_table); |
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index ce030d1f1c1f..733acc213726 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Siemens ID Mouse driver v0.5 | 1 | /* Siemens ID Mouse driver v0.6 |
2 | 2 | ||
3 | This program is free software; you can redistribute it and/or | 3 | This program is free software; you can redistribute it and/or |
4 | modify it under the terms of the GNU General Public License as | 4 | modify it under the terms of the GNU General Public License as |
@@ -11,6 +11,9 @@ | |||
11 | Derived from the USB Skeleton driver 1.1, | 11 | Derived from the USB Skeleton driver 1.1, |
12 | Copyright (C) 2003 Greg Kroah-Hartman (greg@kroah.com) | 12 | Copyright (C) 2003 Greg Kroah-Hartman (greg@kroah.com) |
13 | 13 | ||
14 | Additional information provided by Martin Reising | ||
15 | <Martin.Reising@natural-computing.de> | ||
16 | |||
14 | */ | 17 | */ |
15 | 18 | ||
16 | #include <linux/config.h> | 19 | #include <linux/config.h> |
@@ -25,29 +28,44 @@ | |||
25 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
26 | #include <linux/usb.h> | 29 | #include <linux/usb.h> |
27 | 30 | ||
31 | /* image constants */ | ||
28 | #define WIDTH 225 | 32 | #define WIDTH 225 |
29 | #define HEIGHT 288 | 33 | #define HEIGHT 289 |
30 | #define HEADER "P5 225 288 255 " | 34 | #define HEADER "P5 225 289 255 " |
31 | #define IMGSIZE ((WIDTH * HEIGHT) + sizeof(HEADER)-1) | 35 | #define IMGSIZE ((WIDTH * HEIGHT) + sizeof(HEADER)-1) |
32 | 36 | ||
33 | /* Version Information */ | 37 | /* version information */ |
34 | #define DRIVER_VERSION "0.5" | 38 | #define DRIVER_VERSION "0.6" |
35 | #define DRIVER_SHORT "idmouse" | 39 | #define DRIVER_SHORT "idmouse" |
36 | #define DRIVER_AUTHOR "Florian 'Floe' Echtler <echtler@fs.tum.de>" | 40 | #define DRIVER_AUTHOR "Florian 'Floe' Echtler <echtler@fs.tum.de>" |
37 | #define DRIVER_DESC "Siemens ID Mouse FingerTIP Sensor Driver" | 41 | #define DRIVER_DESC "Siemens ID Mouse FingerTIP Sensor Driver" |
38 | 42 | ||
39 | /* Siemens ID Mouse */ | 43 | /* minor number for misc USB devices */ |
40 | #define USB_IDMOUSE_VENDOR_ID 0x0681 | ||
41 | #define USB_IDMOUSE_PRODUCT_ID 0x0005 | ||
42 | |||
43 | /* we still need a minor number */ | ||
44 | #define USB_IDMOUSE_MINOR_BASE 132 | 44 | #define USB_IDMOUSE_MINOR_BASE 132 |
45 | 45 | ||
46 | /* vendor and device IDs */ | ||
47 | #define ID_SIEMENS 0x0681 | ||
48 | #define ID_IDMOUSE 0x0005 | ||
49 | #define ID_CHERRY 0x0010 | ||
50 | |||
51 | /* device ID table */ | ||
46 | static struct usb_device_id idmouse_table[] = { | 52 | static struct usb_device_id idmouse_table[] = { |
47 | {USB_DEVICE(USB_IDMOUSE_VENDOR_ID, USB_IDMOUSE_PRODUCT_ID)}, | 53 | {USB_DEVICE(ID_SIEMENS, ID_IDMOUSE)}, /* Siemens ID Mouse (Professional) */ |
48 | {} /* null entry at the end */ | 54 | {USB_DEVICE(ID_SIEMENS, ID_CHERRY )}, /* Cherry FingerTIP ID Board */ |
55 | {} /* terminating null entry */ | ||
49 | }; | 56 | }; |
50 | 57 | ||
58 | /* sensor commands */ | ||
59 | #define FTIP_RESET 0x20 | ||
60 | #define FTIP_ACQUIRE 0x21 | ||
61 | #define FTIP_RELEASE 0x22 | ||
62 | #define FTIP_BLINK 0x23 /* LSB of value = blink pulse width */ | ||
63 | #define FTIP_SCROLL 0x24 | ||
64 | |||
65 | #define ftip_command(dev, command, value, index) \ | ||
66 | usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), command, \ | ||
67 | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000) | ||
68 | |||
51 | MODULE_DEVICE_TABLE(usb, idmouse_table); | 69 | MODULE_DEVICE_TABLE(usb, idmouse_table); |
52 | 70 | ||
53 | /* structure to hold all of our device specific stuff */ | 71 | /* structure to hold all of our device specific stuff */ |
@@ -57,7 +75,8 @@ struct usb_idmouse { | |||
57 | struct usb_interface *interface; /* the interface for this device */ | 75 | struct usb_interface *interface; /* the interface for this device */ |
58 | 76 | ||
59 | unsigned char *bulk_in_buffer; /* the buffer to receive data */ | 77 | unsigned char *bulk_in_buffer; /* the buffer to receive data */ |
60 | size_t bulk_in_size; /* the size of the receive buffer */ | 78 | size_t bulk_in_size; /* the maximum bulk packet size */ |
79 | size_t orig_bi_size; /* same as above, but reported by the device */ | ||
61 | __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ | 80 | __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ |
62 | 81 | ||
63 | int open; /* if the port is open or not */ | 82 | int open; /* if the port is open or not */ |
@@ -103,7 +122,7 @@ static struct usb_driver idmouse_driver = { | |||
103 | .id_table = idmouse_table, | 122 | .id_table = idmouse_table, |
104 | }; | 123 | }; |
105 | 124 | ||
106 | // prevent races between open() and disconnect() | 125 | /* prevent races between open() and disconnect() */ |
107 | static DECLARE_MUTEX(disconnect_sem); | 126 | static DECLARE_MUTEX(disconnect_sem); |
108 | 127 | ||
109 | static int idmouse_create_image(struct usb_idmouse *dev) | 128 | static int idmouse_create_image(struct usb_idmouse *dev) |
@@ -112,42 +131,34 @@ static int idmouse_create_image(struct usb_idmouse *dev) | |||
112 | int bulk_read = 0; | 131 | int bulk_read = 0; |
113 | int result = 0; | 132 | int result = 0; |
114 | 133 | ||
115 | if (dev->bulk_in_size < sizeof(HEADER)) | 134 | memcpy(dev->bulk_in_buffer, HEADER, sizeof(HEADER)-1); |
116 | return -ENOMEM; | ||
117 | |||
118 | memcpy(dev->bulk_in_buffer,HEADER,sizeof(HEADER)-1); | ||
119 | bytes_read += sizeof(HEADER)-1; | 135 | bytes_read += sizeof(HEADER)-1; |
120 | 136 | ||
121 | /* Dump the setup packets. Yes, they are uncommented, simply | 137 | /* reset the device and set a fast blink rate */ |
122 | because they were sniffed under Windows using SnoopyPro. | 138 | result = ftip_command(dev, FTIP_RELEASE, 0, 0); |
123 | I _guess_ that 0x22 is a kind of reset command and 0x21 | ||
124 | means init.. | ||
125 | */ | ||
126 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | ||
127 | 0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000); | ||
128 | if (result < 0) | ||
129 | return result; | ||
130 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | ||
131 | 0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000); | ||
132 | if (result < 0) | 139 | if (result < 0) |
133 | return result; | 140 | goto reset; |
134 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 141 | result = ftip_command(dev, FTIP_BLINK, 1, 0); |
135 | 0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000); | ||
136 | if (result < 0) | 142 | if (result < 0) |
137 | return result; | 143 | goto reset; |
138 | 144 | ||
139 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 145 | /* initialize the sensor - sending this command twice */ |
140 | 0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000); | 146 | /* significantly reduces the rate of failed reads */ |
147 | result = ftip_command(dev, FTIP_ACQUIRE, 0, 0); | ||
141 | if (result < 0) | 148 | if (result < 0) |
142 | return result; | 149 | goto reset; |
143 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 150 | result = ftip_command(dev, FTIP_ACQUIRE, 0, 0); |
144 | 0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000); | ||
145 | if (result < 0) | 151 | if (result < 0) |
146 | return result; | 152 | goto reset; |
147 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 153 | |
148 | 0x20, 0x42, 0x0000, 0x0002, NULL, 0, 1000); | 154 | /* start the readout - sending this command twice */ |
155 | /* presumably enables the high dynamic range mode */ | ||
156 | result = ftip_command(dev, FTIP_RESET, 0, 0); | ||
149 | if (result < 0) | 157 | if (result < 0) |
150 | return result; | 158 | goto reset; |
159 | result = ftip_command(dev, FTIP_RESET, 0, 0); | ||
160 | if (result < 0) | ||
161 | goto reset; | ||
151 | 162 | ||
152 | /* loop over a blocking bulk read to get data from the device */ | 163 | /* loop over a blocking bulk read to get data from the device */ |
153 | while (bytes_read < IMGSIZE) { | 164 | while (bytes_read < IMGSIZE) { |
@@ -155,22 +166,40 @@ static int idmouse_create_image(struct usb_idmouse *dev) | |||
155 | usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr), | 166 | usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr), |
156 | dev->bulk_in_buffer + bytes_read, | 167 | dev->bulk_in_buffer + bytes_read, |
157 | dev->bulk_in_size, &bulk_read, 5000); | 168 | dev->bulk_in_size, &bulk_read, 5000); |
158 | if (result < 0) | 169 | if (result < 0) { |
159 | return result; | 170 | /* Maybe this error was caused by the increased packet size? */ |
160 | if (signal_pending(current)) | 171 | /* Reset to the original value and tell userspace to retry. */ |
161 | return -EINTR; | 172 | if (dev->bulk_in_size != dev->orig_bi_size) { |
173 | dev->bulk_in_size = dev->orig_bi_size; | ||
174 | result = -EAGAIN; | ||
175 | } | ||
176 | break; | ||
177 | } | ||
178 | if (signal_pending(current)) { | ||
179 | result = -EINTR; | ||
180 | break; | ||
181 | } | ||
162 | bytes_read += bulk_read; | 182 | bytes_read += bulk_read; |
163 | } | 183 | } |
164 | 184 | ||
165 | /* reset the device */ | 185 | /* reset the device */ |
166 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 186 | reset: |
167 | 0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000); | 187 | ftip_command(dev, FTIP_RELEASE, 0, 0); |
168 | if (result < 0) | 188 | |
169 | return result; | 189 | /* check for valid image */ |
190 | /* right border should be black (0x00) */ | ||
191 | for (bytes_read = sizeof(HEADER)-1 + WIDTH-1; bytes_read < IMGSIZE; bytes_read += WIDTH) | ||
192 | if (dev->bulk_in_buffer[bytes_read] != 0x00) | ||
193 | return -EAGAIN; | ||
170 | 194 | ||
171 | /* should be IMGSIZE == 64815 */ | 195 | /* lower border should be white (0xFF) */ |
196 | for (bytes_read = IMGSIZE-WIDTH; bytes_read < IMGSIZE-1; bytes_read++) | ||
197 | if (dev->bulk_in_buffer[bytes_read] != 0xFF) | ||
198 | return -EAGAIN; | ||
199 | |||
200 | /* should be IMGSIZE == 65040 */ | ||
172 | dbg("read %d bytes fingerprint data", bytes_read); | 201 | dbg("read %d bytes fingerprint data", bytes_read); |
173 | return 0; | 202 | return result; |
174 | } | 203 | } |
175 | 204 | ||
176 | static inline void idmouse_delete(struct usb_idmouse *dev) | 205 | static inline void idmouse_delete(struct usb_idmouse *dev) |
@@ -282,10 +311,10 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count | |||
282 | 311 | ||
283 | dev = (struct usb_idmouse *) file->private_data; | 312 | dev = (struct usb_idmouse *) file->private_data; |
284 | 313 | ||
285 | // lock this object | 314 | /* lock this object */ |
286 | down (&dev->sem); | 315 | down (&dev->sem); |
287 | 316 | ||
288 | // verify that the device wasn't unplugged | 317 | /* verify that the device wasn't unplugged */ |
289 | if (!dev->present) { | 318 | if (!dev->present) { |
290 | up (&dev->sem); | 319 | up (&dev->sem); |
291 | return -ENODEV; | 320 | return -ENODEV; |
@@ -296,8 +325,7 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count | |||
296 | return 0; | 325 | return 0; |
297 | } | 326 | } |
298 | 327 | ||
299 | if (count > IMGSIZE - *ppos) | 328 | count = min ((loff_t)count, IMGSIZE - (*ppos)); |
300 | count = IMGSIZE - *ppos; | ||
301 | 329 | ||
302 | if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) { | 330 | if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) { |
303 | result = -EFAULT; | 331 | result = -EFAULT; |
@@ -306,7 +334,7 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count | |||
306 | *ppos += count; | 334 | *ppos += count; |
307 | } | 335 | } |
308 | 336 | ||
309 | // unlock the device | 337 | /* unlock the device */ |
310 | up(&dev->sem); | 338 | up(&dev->sem); |
311 | return result; | 339 | return result; |
312 | } | 340 | } |
@@ -318,7 +346,6 @@ static int idmouse_probe(struct usb_interface *interface, | |||
318 | struct usb_idmouse *dev = NULL; | 346 | struct usb_idmouse *dev = NULL; |
319 | struct usb_host_interface *iface_desc; | 347 | struct usb_host_interface *iface_desc; |
320 | struct usb_endpoint_descriptor *endpoint; | 348 | struct usb_endpoint_descriptor *endpoint; |
321 | size_t buffer_size; | ||
322 | int result; | 349 | int result; |
323 | 350 | ||
324 | /* check if we have gotten the data or the hid interface */ | 351 | /* check if we have gotten the data or the hid interface */ |
@@ -344,11 +371,11 @@ static int idmouse_probe(struct usb_interface *interface, | |||
344 | USB_ENDPOINT_XFER_BULK)) { | 371 | USB_ENDPOINT_XFER_BULK)) { |
345 | 372 | ||
346 | /* we found a bulk in endpoint */ | 373 | /* we found a bulk in endpoint */ |
347 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 374 | dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize); |
348 | dev->bulk_in_size = buffer_size; | 375 | dev->bulk_in_size = 0x200; /* works _much_ faster */ |
349 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; | 376 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; |
350 | dev->bulk_in_buffer = | 377 | dev->bulk_in_buffer = |
351 | kmalloc(IMGSIZE + buffer_size, GFP_KERNEL); | 378 | kmalloc(IMGSIZE + dev->bulk_in_size, GFP_KERNEL); |
352 | 379 | ||
353 | if (!dev->bulk_in_buffer) { | 380 | if (!dev->bulk_in_buffer) { |
354 | err("Unable to allocate input buffer."); | 381 | err("Unable to allocate input buffer."); |
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 3104f28f6aa8..cda7249a90b2 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -461,7 +461,7 @@ static int perform_sglist ( | |||
461 | 461 | ||
462 | static unsigned realworld = 1; | 462 | static unsigned realworld = 1; |
463 | module_param (realworld, uint, 0); | 463 | module_param (realworld, uint, 0); |
464 | MODULE_PARM_DESC (realworld, "clear to demand stricter ch9 compliance"); | 464 | MODULE_PARM_DESC (realworld, "clear to demand stricter spec compliance"); |
465 | 465 | ||
466 | static int get_altsetting (struct usbtest_dev *dev) | 466 | static int get_altsetting (struct usbtest_dev *dev) |
467 | { | 467 | { |
@@ -604,9 +604,8 @@ static int ch9_postconfig (struct usbtest_dev *dev) | |||
604 | USB_DIR_IN | USB_RECIP_DEVICE, | 604 | USB_DIR_IN | USB_RECIP_DEVICE, |
605 | 0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT); | 605 | 0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT); |
606 | if (retval != 1 || dev->buf [0] != expected) { | 606 | if (retval != 1 || dev->buf [0] != expected) { |
607 | dev_dbg (&iface->dev, | 607 | dev_dbg (&iface->dev, "get config --> %d %d (1 %d)\n", |
608 | "get config --> %d (%d)\n", retval, | 608 | retval, dev->buf[0], expected); |
609 | expected); | ||
610 | return (retval < 0) ? retval : -EDOM; | 609 | return (retval < 0) ? retval : -EDOM; |
611 | } | 610 | } |
612 | } | 611 | } |
@@ -1243,7 +1242,7 @@ static int ctrl_out (struct usbtest_dev *dev, | |||
1243 | char *what = "?"; | 1242 | char *what = "?"; |
1244 | struct usb_device *udev; | 1243 | struct usb_device *udev; |
1245 | 1244 | ||
1246 | if (length > 0xffff || vary >= length) | 1245 | if (length < 1 || length > 0xffff || vary >= length) |
1247 | return -EINVAL; | 1246 | return -EINVAL; |
1248 | 1247 | ||
1249 | buf = kmalloc(length, SLAB_KERNEL); | 1248 | buf = kmalloc(length, SLAB_KERNEL); |
@@ -1266,6 +1265,11 @@ static int ctrl_out (struct usbtest_dev *dev, | |||
1266 | 0, 0, buf, len, USB_CTRL_SET_TIMEOUT); | 1265 | 0, 0, buf, len, USB_CTRL_SET_TIMEOUT); |
1267 | if (retval != len) { | 1266 | if (retval != len) { |
1268 | what = "write"; | 1267 | what = "write"; |
1268 | if (retval >= 0) { | ||
1269 | INFO(dev, "ctrl_out, wlen %d (expected %d)\n", | ||
1270 | retval, len); | ||
1271 | retval = -EBADMSG; | ||
1272 | } | ||
1269 | break; | 1273 | break; |
1270 | } | 1274 | } |
1271 | 1275 | ||
@@ -1275,6 +1279,11 @@ static int ctrl_out (struct usbtest_dev *dev, | |||
1275 | 0, 0, buf, len, USB_CTRL_GET_TIMEOUT); | 1279 | 0, 0, buf, len, USB_CTRL_GET_TIMEOUT); |
1276 | if (retval != len) { | 1280 | if (retval != len) { |
1277 | what = "read"; | 1281 | what = "read"; |
1282 | if (retval >= 0) { | ||
1283 | INFO(dev, "ctrl_out, rlen %d (expected %d)\n", | ||
1284 | retval, len); | ||
1285 | retval = -EBADMSG; | ||
1286 | } | ||
1278 | break; | 1287 | break; |
1279 | } | 1288 | } |
1280 | 1289 | ||
@@ -1293,8 +1302,13 @@ static int ctrl_out (struct usbtest_dev *dev, | |||
1293 | } | 1302 | } |
1294 | 1303 | ||
1295 | len += vary; | 1304 | len += vary; |
1305 | |||
1306 | /* [real world] the "zero bytes IN" case isn't really used. | ||
1307 | * hardware can easily trip up in this wierd case, since its | ||
1308 | * status stage is IN, not OUT like other ep0in transfers. | ||
1309 | */ | ||
1296 | if (len > length) | 1310 | if (len > length) |
1297 | len = 0; | 1311 | len = realworld ? 1 : 0; |
1298 | } | 1312 | } |
1299 | 1313 | ||
1300 | if (retval < 0) | 1314 | if (retval < 0) |
@@ -1519,6 +1533,11 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) | |||
1519 | if (down_interruptible (&dev->sem)) | 1533 | if (down_interruptible (&dev->sem)) |
1520 | return -ERESTARTSYS; | 1534 | return -ERESTARTSYS; |
1521 | 1535 | ||
1536 | if (intf->dev.power.power_state != PMSG_ON) { | ||
1537 | up (&dev->sem); | ||
1538 | return -EHOSTUNREACH; | ||
1539 | } | ||
1540 | |||
1522 | /* some devices, like ez-usb default devices, need a non-default | 1541 | /* some devices, like ez-usb default devices, need a non-default |
1523 | * altsetting to have any active endpoints. some tests change | 1542 | * altsetting to have any active endpoints. some tests change |
1524 | * altsettings; force a default so most tests don't need to check. | 1543 | * altsettings; force a default so most tests don't need to check. |
@@ -1762,8 +1781,10 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) | |||
1762 | case 14: | 1781 | case 14: |
1763 | if (!dev->info->ctrl_out) | 1782 | if (!dev->info->ctrl_out) |
1764 | break; | 1783 | break; |
1765 | dev_dbg (&intf->dev, "TEST 14: %d ep0out, 0..%d vary %d\n", | 1784 | dev_dbg (&intf->dev, "TEST 14: %d ep0out, %d..%d vary %d\n", |
1766 | param->iterations, param->length, param->vary); | 1785 | param->iterations, |
1786 | realworld ? 1 : 0, param->length, | ||
1787 | param->vary); | ||
1767 | retval = ctrl_out (dev, param->iterations, | 1788 | retval = ctrl_out (dev, param->iterations, |
1768 | param->length, param->vary); | 1789 | param->length, param->vary); |
1769 | break; | 1790 | break; |
@@ -1927,6 +1948,27 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) | |||
1927 | return 0; | 1948 | return 0; |
1928 | } | 1949 | } |
1929 | 1950 | ||
1951 | static int usbtest_suspend (struct usb_interface *intf, pm_message_t message) | ||
1952 | { | ||
1953 | struct usbtest_dev *dev = usb_get_intfdata (intf); | ||
1954 | |||
1955 | down (&dev->sem); | ||
1956 | intf->dev.power.power_state = PMSG_SUSPEND; | ||
1957 | up (&dev->sem); | ||
1958 | return 0; | ||
1959 | } | ||
1960 | |||
1961 | static int usbtest_resume (struct usb_interface *intf) | ||
1962 | { | ||
1963 | struct usbtest_dev *dev = usb_get_intfdata (intf); | ||
1964 | |||
1965 | down (&dev->sem); | ||
1966 | intf->dev.power.power_state = PMSG_ON; | ||
1967 | up (&dev->sem); | ||
1968 | return 0; | ||
1969 | } | ||
1970 | |||
1971 | |||
1930 | static void usbtest_disconnect (struct usb_interface *intf) | 1972 | static void usbtest_disconnect (struct usb_interface *intf) |
1931 | { | 1973 | { |
1932 | struct usbtest_dev *dev = usb_get_intfdata (intf); | 1974 | struct usbtest_dev *dev = usb_get_intfdata (intf); |
@@ -2115,6 +2157,8 @@ static struct usb_driver usbtest_driver = { | |||
2115 | .probe = usbtest_probe, | 2157 | .probe = usbtest_probe, |
2116 | .ioctl = usbtest_ioctl, | 2158 | .ioctl = usbtest_ioctl, |
2117 | .disconnect = usbtest_disconnect, | 2159 | .disconnect = usbtest_disconnect, |
2160 | .suspend = usbtest_suspend, | ||
2161 | .resume = usbtest_resume, | ||
2118 | }; | 2162 | }; |
2119 | 2163 | ||
2120 | /*-------------------------------------------------------------------------*/ | 2164 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index d976790312aa..5f4496d8dbac 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c | |||
@@ -1166,7 +1166,7 @@ static void pegasus_set_multicast(struct net_device *net) | |||
1166 | pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; | 1166 | pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; |
1167 | if (netif_msg_link(pegasus)) | 1167 | if (netif_msg_link(pegasus)) |
1168 | pr_info("%s: Promiscuous mode enabled.\n", net->name); | 1168 | pr_info("%s: Promiscuous mode enabled.\n", net->name); |
1169 | } else if ((net->mc_count > multicast_filter_limit) || | 1169 | } else if (net->mc_count || |
1170 | (net->flags & IFF_ALLMULTI)) { | 1170 | (net->flags & IFF_ALLMULTI)) { |
1171 | pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; | 1171 | pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; |
1172 | pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; | 1172 | pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; |
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h index 13ccedef5c7e..b98f2a833442 100644 --- a/drivers/usb/net/pegasus.h +++ b/drivers/usb/net/pegasus.h | |||
@@ -249,6 +249,8 @@ PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a, | |||
249 | DEFAULT_GPIO_RESET) | 249 | DEFAULT_GPIO_RESET) |
250 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002, | 250 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002, |
251 | DEFAULT_GPIO_RESET ) | 251 | DEFAULT_GPIO_RESET ) |
252 | PEGASUS_DEV( "LANEED USB Ethernet LD-USBL/TX", VENDOR_LANEED, 0x4005, | ||
253 | DEFAULT_GPIO_RESET | PEGASUS_II) | ||
252 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b, | 254 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b, |
253 | DEFAULT_GPIO_RESET | PEGASUS_II ) | 255 | DEFAULT_GPIO_RESET | PEGASUS_II ) |
254 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1, | 256 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1, |
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index 8fb223385f2f..626b016addff 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c | |||
@@ -667,7 +667,7 @@ static void rtl8150_set_multicast(struct net_device *netdev) | |||
667 | if (netdev->flags & IFF_PROMISC) { | 667 | if (netdev->flags & IFF_PROMISC) { |
668 | dev->rx_creg |= cpu_to_le16(0x0001); | 668 | dev->rx_creg |= cpu_to_le16(0x0001); |
669 | info("%s: promiscuous mode", netdev->name); | 669 | info("%s: promiscuous mode", netdev->name); |
670 | } else if ((netdev->mc_count > multicast_filter_limit) || | 670 | } else if (netdev->mc_count || |
671 | (netdev->flags & IFF_ALLMULTI)) { | 671 | (netdev->flags & IFF_ALLMULTI)) { |
672 | dev->rx_creg &= cpu_to_le16(0xfffe); | 672 | dev->rx_creg &= cpu_to_le16(0xfffe); |
673 | dev->rx_creg |= cpu_to_le16(0x0002); | 673 | dev->rx_creg |= cpu_to_le16(0x0002); |
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 4cbb408af727..8a945f4f3693 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c | |||
@@ -1429,7 +1429,7 @@ static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf) | |||
1429 | info->ether = (void *) buf; | 1429 | info->ether = (void *) buf; |
1430 | if (info->ether->bLength != sizeof *info->ether) { | 1430 | if (info->ether->bLength != sizeof *info->ether) { |
1431 | dev_dbg (&intf->dev, "CDC ether len %u\n", | 1431 | dev_dbg (&intf->dev, "CDC ether len %u\n", |
1432 | info->u->bLength); | 1432 | info->ether->bLength); |
1433 | goto bad_desc; | 1433 | goto bad_desc; |
1434 | } | 1434 | } |
1435 | dev->net->mtu = le16_to_cpup ( | 1435 | dev->net->mtu = le16_to_cpup ( |
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c index 17b9718b8de6..72b06129e20a 100644 --- a/drivers/usb/net/zd1201.c +++ b/drivers/usb/net/zd1201.c | |||
@@ -1884,12 +1884,53 @@ static void zd1201_disconnect(struct usb_interface *interface) | |||
1884 | kfree(zd); | 1884 | kfree(zd); |
1885 | } | 1885 | } |
1886 | 1886 | ||
1887 | #ifdef CONFIG_PM | ||
1888 | |||
1889 | static int zd1201_suspend(struct usb_interface *interface, | ||
1890 | pm_message_t message) | ||
1891 | { | ||
1892 | struct zd1201 *zd = usb_get_intfdata(interface); | ||
1893 | |||
1894 | netif_device_detach(zd->dev); | ||
1895 | |||
1896 | zd->was_enabled = zd->mac_enabled; | ||
1897 | |||
1898 | if (zd->was_enabled) | ||
1899 | return zd1201_disable(zd); | ||
1900 | else | ||
1901 | return 0; | ||
1902 | } | ||
1903 | |||
1904 | static int zd1201_resume(struct usb_interface *interface) | ||
1905 | { | ||
1906 | struct zd1201 *zd = usb_get_intfdata(interface); | ||
1907 | |||
1908 | if (!zd || !zd->dev) | ||
1909 | return -ENODEV; | ||
1910 | |||
1911 | netif_device_attach(zd->dev); | ||
1912 | |||
1913 | if (zd->was_enabled) | ||
1914 | return zd1201_enable(zd); | ||
1915 | else | ||
1916 | return 0; | ||
1917 | } | ||
1918 | |||
1919 | #else | ||
1920 | |||
1921 | #define zd1201_suspend NULL | ||
1922 | #define zd1201_resume NULL | ||
1923 | |||
1924 | #endif | ||
1925 | |||
1887 | static struct usb_driver zd1201_usb = { | 1926 | static struct usb_driver zd1201_usb = { |
1888 | .owner = THIS_MODULE, | 1927 | .owner = THIS_MODULE, |
1889 | .name = "zd1201", | 1928 | .name = "zd1201", |
1890 | .probe = zd1201_probe, | 1929 | .probe = zd1201_probe, |
1891 | .disconnect = zd1201_disconnect, | 1930 | .disconnect = zd1201_disconnect, |
1892 | .id_table = zd1201_table, | 1931 | .id_table = zd1201_table, |
1932 | .suspend = zd1201_suspend, | ||
1933 | .resume = zd1201_resume, | ||
1893 | }; | 1934 | }; |
1894 | 1935 | ||
1895 | static int __init zd1201_init(void) | 1936 | static int __init zd1201_init(void) |
diff --git a/drivers/usb/net/zd1201.h b/drivers/usb/net/zd1201.h index 1627c71e8052..235f0ee34b24 100644 --- a/drivers/usb/net/zd1201.h +++ b/drivers/usb/net/zd1201.h | |||
@@ -46,6 +46,7 @@ struct zd1201 { | |||
46 | char essid[IW_ESSID_MAX_SIZE+1]; | 46 | char essid[IW_ESSID_MAX_SIZE+1]; |
47 | int essidlen; | 47 | int essidlen; |
48 | int mac_enabled; | 48 | int mac_enabled; |
49 | int was_enabled; | ||
49 | int monitor; | 50 | int monitor; |
50 | int encode_enabled; | 51 | int encode_enabled; |
51 | int encode_restricted; | 52 | int encode_restricted; |
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 46a204cd40e1..b5b431067b08 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
@@ -213,10 +213,14 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
213 | return (0); | 213 | return (0); |
214 | } | 214 | } |
215 | 215 | ||
216 | if (port->write_urb->status == -EINPROGRESS) { | 216 | spin_lock(&port->lock); |
217 | if (port->write_urb_busy) { | ||
218 | spin_unlock(&port->lock); | ||
217 | dbg("%s - already writing", __FUNCTION__); | 219 | dbg("%s - already writing", __FUNCTION__); |
218 | return (0); | 220 | return 0; |
219 | } | 221 | } |
222 | port->write_urb_busy = 1; | ||
223 | spin_unlock(&port->lock); | ||
220 | 224 | ||
221 | spin_lock_irqsave(&priv->lock, flags); | 225 | spin_lock_irqsave(&priv->lock, flags); |
222 | 226 | ||
@@ -224,6 +228,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
224 | /* To much data for buffer. Reset buffer. */ | 228 | /* To much data for buffer. Reset buffer. */ |
225 | priv->wrfilled=0; | 229 | priv->wrfilled=0; |
226 | spin_unlock_irqrestore(&priv->lock, flags); | 230 | spin_unlock_irqrestore(&priv->lock, flags); |
231 | port->write_urb_busy = 0; | ||
227 | return (0); | 232 | return (0); |
228 | } | 233 | } |
229 | 234 | ||
@@ -268,6 +273,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
268 | priv->wrfilled=0; | 273 | priv->wrfilled=0; |
269 | priv->wrsent=0; | 274 | priv->wrsent=0; |
270 | spin_unlock_irqrestore(&priv->lock, flags); | 275 | spin_unlock_irqrestore(&priv->lock, flags); |
276 | port->write_urb_busy = 0; | ||
271 | return 0; | 277 | return 0; |
272 | } | 278 | } |
273 | 279 | ||
@@ -412,7 +418,8 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs | |||
412 | struct cyberjack_private *priv = usb_get_serial_port_data(port); | 418 | struct cyberjack_private *priv = usb_get_serial_port_data(port); |
413 | 419 | ||
414 | dbg("%s - port %d", __FUNCTION__, port->number); | 420 | dbg("%s - port %d", __FUNCTION__, port->number); |
415 | 421 | ||
422 | port->write_urb_busy = 0; | ||
416 | if (urb->status) { | 423 | if (urb->status) { |
417 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 424 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
418 | return; | 425 | return; |
@@ -424,12 +431,6 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs | |||
424 | if( priv->wrfilled ) { | 431 | if( priv->wrfilled ) { |
425 | int length, blksize, result; | 432 | int length, blksize, result; |
426 | 433 | ||
427 | if (port->write_urb->status == -EINPROGRESS) { | ||
428 | dbg("%s - already writing", __FUNCTION__); | ||
429 | spin_unlock(&priv->lock); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | dbg("%s - transmitting data (frame n)", __FUNCTION__); | 434 | dbg("%s - transmitting data (frame n)", __FUNCTION__); |
434 | 435 | ||
435 | length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? | 436 | length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 99214aa3cd19..ddde5fb13f6b 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -174,10 +174,14 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * | |||
174 | 174 | ||
175 | /* only do something if we have a bulk out endpoint */ | 175 | /* only do something if we have a bulk out endpoint */ |
176 | if (serial->num_bulk_out) { | 176 | if (serial->num_bulk_out) { |
177 | if (port->write_urb->status == -EINPROGRESS) { | 177 | spin_lock(&port->lock); |
178 | if (port->write_urb_busy) { | ||
179 | spin_unlock(&port->lock); | ||
178 | dbg("%s - already writing", __FUNCTION__); | 180 | dbg("%s - already writing", __FUNCTION__); |
179 | return (0); | 181 | return 0; |
180 | } | 182 | } |
183 | port->write_urb_busy = 1; | ||
184 | spin_unlock(&port->lock); | ||
181 | 185 | ||
182 | count = (count > port->bulk_out_size) ? port->bulk_out_size : count; | 186 | count = (count > port->bulk_out_size) ? port->bulk_out_size : count; |
183 | 187 | ||
@@ -195,17 +199,20 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * | |||
195 | usb_serial_generic_write_bulk_callback), port); | 199 | usb_serial_generic_write_bulk_callback), port); |
196 | 200 | ||
197 | /* send the data out the bulk port */ | 201 | /* send the data out the bulk port */ |
202 | port->write_urb_busy = 1; | ||
198 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 203 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
199 | if (result) | 204 | if (result) { |
200 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); | 205 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); |
201 | else | 206 | /* don't have to grab the lock here, as we will retry if != 0 */ |
207 | port->write_urb_busy = 0; | ||
208 | } else | ||
202 | result = count; | 209 | result = count; |
203 | 210 | ||
204 | return result; | 211 | return result; |
205 | } | 212 | } |
206 | 213 | ||
207 | /* no bulk out, so return 0 bytes written */ | 214 | /* no bulk out, so return 0 bytes written */ |
208 | return (0); | 215 | return 0; |
209 | } | 216 | } |
210 | 217 | ||
211 | int usb_serial_generic_write_room (struct usb_serial_port *port) | 218 | int usb_serial_generic_write_room (struct usb_serial_port *port) |
@@ -214,9 +221,9 @@ int usb_serial_generic_write_room (struct usb_serial_port *port) | |||
214 | int room = 0; | 221 | int room = 0; |
215 | 222 | ||
216 | dbg("%s - port %d", __FUNCTION__, port->number); | 223 | dbg("%s - port %d", __FUNCTION__, port->number); |
217 | 224 | ||
218 | if (serial->num_bulk_out) { | 225 | if (serial->num_bulk_out) { |
219 | if (port->write_urb->status != -EINPROGRESS) | 226 | if (port->write_urb_busy) |
220 | room = port->bulk_out_size; | 227 | room = port->bulk_out_size; |
221 | } | 228 | } |
222 | 229 | ||
@@ -232,7 +239,7 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) | |||
232 | dbg("%s - port %d", __FUNCTION__, port->number); | 239 | dbg("%s - port %d", __FUNCTION__, port->number); |
233 | 240 | ||
234 | if (serial->num_bulk_out) { | 241 | if (serial->num_bulk_out) { |
235 | if (port->write_urb->status == -EINPROGRESS) | 242 | if (port->write_urb_busy) |
236 | chars = port->write_urb->transfer_buffer_length; | 243 | chars = port->write_urb->transfer_buffer_length; |
237 | } | 244 | } |
238 | 245 | ||
@@ -291,6 +298,7 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *re | |||
291 | 298 | ||
292 | dbg("%s - port %d", __FUNCTION__, port->number); | 299 | dbg("%s - port %d", __FUNCTION__, port->number); |
293 | 300 | ||
301 | port->write_urb_busy = 0; | ||
294 | if (urb->status) { | 302 | if (urb->status) { |
295 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 303 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
296 | return; | 304 | return; |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 3bd69c4ef24b..c05c2a2a0f31 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -818,11 +818,6 @@ static void ipaq_write_gather(struct usb_serial_port *port) | |||
818 | struct ipaq_packet *pkt, *tmp; | 818 | struct ipaq_packet *pkt, *tmp; |
819 | struct urb *urb = port->write_urb; | 819 | struct urb *urb = port->write_urb; |
820 | 820 | ||
821 | if (urb->status == -EINPROGRESS) { | ||
822 | /* Should never happen */ | ||
823 | err("%s - flushing while urb is active !", __FUNCTION__); | ||
824 | return; | ||
825 | } | ||
826 | room = URBDATA_SIZE; | 821 | room = URBDATA_SIZE; |
827 | list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { | 822 | list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { |
828 | count = min(room, (int)(pkt->len - pkt->written)); | 823 | count = min(room, (int)(pkt->len - pkt->written)); |
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 11105d74f461..85e242459c27 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
@@ -399,16 +399,21 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int | |||
399 | dbg("%s - write request of 0 bytes", __FUNCTION__); | 399 | dbg("%s - write request of 0 bytes", __FUNCTION__); |
400 | return 0; | 400 | return 0; |
401 | } | 401 | } |
402 | 402 | ||
403 | /* Racy and broken, FIXME properly! */ | 403 | spin_lock(&port->lock); |
404 | if (port->write_urb->status == -EINPROGRESS) | 404 | if (port->write_urb_busy) { |
405 | spin_unlock(&port->lock); | ||
406 | dbg("%s - already writing", __FUNCTION__); | ||
405 | return 0; | 407 | return 0; |
408 | } | ||
409 | port->write_urb_busy = 1; | ||
410 | spin_unlock(&port->lock); | ||
406 | 411 | ||
407 | count = min(count, port->bulk_out_size); | 412 | count = min(count, port->bulk_out_size); |
408 | memcpy(port->bulk_out_buffer, buf, count); | 413 | memcpy(port->bulk_out_buffer, buf, count); |
409 | 414 | ||
410 | dbg("%s count now:%d", __FUNCTION__, count); | 415 | dbg("%s count now:%d", __FUNCTION__, count); |
411 | 416 | ||
412 | usb_fill_bulk_urb(port->write_urb, dev, | 417 | usb_fill_bulk_urb(port->write_urb, dev, |
413 | usb_sndbulkpipe(dev, port->bulk_out_endpointAddress), | 418 | usb_sndbulkpipe(dev, port->bulk_out_endpointAddress), |
414 | port->write_urb->transfer_buffer, | 419 | port->write_urb->transfer_buffer, |
@@ -418,6 +423,7 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int | |||
418 | 423 | ||
419 | ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 424 | ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
420 | if (ret != 0) { | 425 | if (ret != 0) { |
426 | port->write_urb_busy = 0; | ||
421 | dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret); | 427 | dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret); |
422 | return ret; | 428 | return ret; |
423 | } | 429 | } |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 59f234df5f89..937b2fdd7171 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
@@ -341,10 +341,14 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int | |||
341 | if (count == 0) | 341 | if (count == 0) |
342 | return 0; | 342 | return 0; |
343 | 343 | ||
344 | if (port->write_urb->status == -EINPROGRESS) { | 344 | spin_lock(&port->lock); |
345 | dbg ("%s - already writing", __FUNCTION__); | 345 | if (port->write_urb_busy) { |
346 | spin_unlock(&port->lock); | ||
347 | dbg("%s - already writing", __FUNCTION__); | ||
346 | return 0; | 348 | return 0; |
347 | } | 349 | } |
350 | port->write_urb_busy = 1; | ||
351 | spin_unlock(&port->lock); | ||
348 | 352 | ||
349 | transfer_buffer = port->write_urb->transfer_buffer; | 353 | transfer_buffer = port->write_urb->transfer_buffer; |
350 | transfer_size = min(count, port->bulk_out_size - 1); | 354 | transfer_size = min(count, port->bulk_out_size - 1); |
@@ -374,9 +378,10 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int | |||
374 | port->write_urb->transfer_flags = URB_ZERO_PACKET; | 378 | port->write_urb->transfer_flags = URB_ZERO_PACKET; |
375 | 379 | ||
376 | result = usb_submit_urb (port->write_urb, GFP_ATOMIC); | 380 | result = usb_submit_urb (port->write_urb, GFP_ATOMIC); |
377 | if (result) | 381 | if (result) { |
382 | port->write_urb_busy = 0; | ||
378 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); | 383 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); |
379 | else | 384 | } else |
380 | result = transfer_size; | 385 | result = transfer_size; |
381 | 386 | ||
382 | return result; | 387 | return result; |
@@ -387,7 +392,8 @@ static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
387 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 392 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
388 | 393 | ||
389 | dbg("%s - port %d", __FUNCTION__, port->number); | 394 | dbg("%s - port %d", __FUNCTION__, port->number); |
390 | 395 | ||
396 | port->write_urb_busy = 0; | ||
391 | if (urb->status) { | 397 | if (urb->status) { |
392 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 398 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
393 | return; | 399 | return; |
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 7fd0aa9eccf6..635c384cb15a 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
@@ -520,9 +520,13 @@ static int keyspan_pda_write(struct usb_serial_port *port, | |||
520 | the TX urb is in-flight (wait until it completes) | 520 | the TX urb is in-flight (wait until it completes) |
521 | the device is full (wait until it says there is room) | 521 | the device is full (wait until it says there is room) |
522 | */ | 522 | */ |
523 | if (port->write_urb->status == -EINPROGRESS || priv->tx_throttled ) { | 523 | spin_lock(&port->lock); |
524 | return( 0 ); | 524 | if (port->write_urb_busy || priv->tx_throttled) { |
525 | spin_unlock(&port->lock); | ||
526 | return 0; | ||
525 | } | 527 | } |
528 | port->write_urb_busy = 1; | ||
529 | spin_unlock(&port->lock); | ||
526 | 530 | ||
527 | /* At this point the URB is in our control, nobody else can submit it | 531 | /* At this point the URB is in our control, nobody else can submit it |
528 | again (the only sudden transition was the one from EINPROGRESS to | 532 | again (the only sudden transition was the one from EINPROGRESS to |
@@ -570,7 +574,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, | |||
570 | memcpy (port->write_urb->transfer_buffer, buf, count); | 574 | memcpy (port->write_urb->transfer_buffer, buf, count); |
571 | /* send the data out the bulk port */ | 575 | /* send the data out the bulk port */ |
572 | port->write_urb->transfer_buffer_length = count; | 576 | port->write_urb->transfer_buffer_length = count; |
573 | 577 | ||
574 | priv->tx_room -= count; | 578 | priv->tx_room -= count; |
575 | 579 | ||
576 | port->write_urb->dev = port->serial->dev; | 580 | port->write_urb->dev = port->serial->dev; |
@@ -593,6 +597,8 @@ static int keyspan_pda_write(struct usb_serial_port *port, | |||
593 | 597 | ||
594 | rc = count; | 598 | rc = count; |
595 | exit: | 599 | exit: |
600 | if (rc < 0) | ||
601 | port->write_urb_busy = 0; | ||
596 | return rc; | 602 | return rc; |
597 | } | 603 | } |
598 | 604 | ||
@@ -602,6 +608,7 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb, struct pt_regs *re | |||
602 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 608 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
603 | struct keyspan_pda_private *priv; | 609 | struct keyspan_pda_private *priv; |
604 | 610 | ||
611 | port->write_urb_busy = 0; | ||
605 | priv = usb_get_serial_port_data(port); | 612 | priv = usb_get_serial_port_data(port); |
606 | 613 | ||
607 | /* queue up a wakeup at scheduler time */ | 614 | /* queue up a wakeup at scheduler time */ |
@@ -626,12 +633,12 @@ static int keyspan_pda_write_room (struct usb_serial_port *port) | |||
626 | static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) | 633 | static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) |
627 | { | 634 | { |
628 | struct keyspan_pda_private *priv; | 635 | struct keyspan_pda_private *priv; |
629 | 636 | ||
630 | priv = usb_get_serial_port_data(port); | 637 | priv = usb_get_serial_port_data(port); |
631 | 638 | ||
632 | /* when throttled, return at least WAKEUP_CHARS to tell select() (via | 639 | /* when throttled, return at least WAKEUP_CHARS to tell select() (via |
633 | n_tty.c:normal_poll() ) that we're not writeable. */ | 640 | n_tty.c:normal_poll() ) that we're not writeable. */ |
634 | if( port->write_urb->status == -EINPROGRESS || priv->tx_throttled ) | 641 | if (port->write_urb_busy || priv->tx_throttled) |
635 | return 256; | 642 | return 256; |
636 | return 0; | 643 | return 0; |
637 | } | 644 | } |
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index b5f2c06d4f3e..6a99ae192df1 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -254,10 +254,15 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf | |||
254 | dbg("%s - write request of 0 bytes", __FUNCTION__); | 254 | dbg("%s - write request of 0 bytes", __FUNCTION__); |
255 | return (0); | 255 | return (0); |
256 | } | 256 | } |
257 | if (wport->write_urb->status == -EINPROGRESS) { | 257 | |
258 | spin_lock(&port->lock); | ||
259 | if (port->write_urb_busy) { | ||
260 | spin_unlock(&port->lock); | ||
258 | dbg("%s - already writing", __FUNCTION__); | 261 | dbg("%s - already writing", __FUNCTION__); |
259 | return (0); | 262 | return 0; |
260 | } | 263 | } |
264 | port->write_urb_busy = 1; | ||
265 | spin_unlock(&port->lock); | ||
261 | 266 | ||
262 | count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; | 267 | count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; |
263 | 268 | ||
@@ -275,9 +280,10 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf | |||
275 | 280 | ||
276 | wport->write_urb->dev = serial->dev; | 281 | wport->write_urb->dev = serial->dev; |
277 | result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); | 282 | result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); |
278 | if (result) | 283 | if (result) { |
284 | port->write_urb_busy = 0; | ||
279 | err("%s - failed submitting write urb, error %d", __FUNCTION__, result); | 285 | err("%s - failed submitting write urb, error %d", __FUNCTION__, result); |
280 | else | 286 | } else |
281 | result = count; | 287 | result = count; |
282 | 288 | ||
283 | return result; | 289 | return result; |
@@ -291,7 +297,7 @@ static int omninet_write_room (struct usb_serial_port *port) | |||
291 | 297 | ||
292 | int room = 0; // Default: no room | 298 | int room = 0; // Default: no room |
293 | 299 | ||
294 | if (wport->write_urb->status != -EINPROGRESS) | 300 | if (wport->write_urb_busy) |
295 | room = wport->bulk_out_size - OMNINET_HEADERLEN; | 301 | room = wport->bulk_out_size - OMNINET_HEADERLEN; |
296 | 302 | ||
297 | // dbg("omninet_write_room returns %d", room); | 303 | // dbg("omninet_write_room returns %d", room); |
@@ -306,6 +312,7 @@ static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
306 | 312 | ||
307 | // dbg("omninet_write_bulk_callback, port %0x\n", port); | 313 | // dbg("omninet_write_bulk_callback, port %0x\n", port); |
308 | 314 | ||
315 | port->write_urb_busy = 0; | ||
309 | if (urb->status) { | 316 | if (urb->status) { |
310 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 317 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
311 | return; | 318 | return; |
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 0e85ed6c6c19..96a17568cbf1 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c | |||
@@ -299,10 +299,14 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i | |||
299 | dbg ("%s - write request of 0 bytes", __FUNCTION__); | 299 | dbg ("%s - write request of 0 bytes", __FUNCTION__); |
300 | return (0); | 300 | return (0); |
301 | } | 301 | } |
302 | if (port->write_urb->status == -EINPROGRESS) { | 302 | spin_lock(&port->lock); |
303 | dbg ("%s - already writing", __FUNCTION__); | 303 | if (port->write_urb_busy) { |
304 | return (0); | 304 | spin_unlock(&port->lock); |
305 | dbg("%s - already writing", __FUNCTION__); | ||
306 | return 0; | ||
305 | } | 307 | } |
308 | port->write_urb_busy = 1; | ||
309 | spin_unlock(&port->lock); | ||
306 | 310 | ||
307 | packet_length = port->bulk_out_size; // get max packetsize | 311 | packet_length = port->bulk_out_size; // get max packetsize |
308 | 312 | ||
@@ -354,6 +358,7 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i | |||
354 | #endif | 358 | #endif |
355 | port->write_urb->dev = port->serial->dev; | 359 | port->write_urb->dev = port->serial->dev; |
356 | if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) { | 360 | if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) { |
361 | port->write_urb_busy = 0; | ||
357 | err ("%s - failed submitting write urb, error %d", __FUNCTION__, result); | 362 | err ("%s - failed submitting write urb, error %d", __FUNCTION__, result); |
358 | return 0; | 363 | return 0; |
359 | } | 364 | } |
@@ -368,7 +373,7 @@ static int safe_write_room (struct usb_serial_port *port) | |||
368 | 373 | ||
369 | dbg ("%s", __FUNCTION__); | 374 | dbg ("%s", __FUNCTION__); |
370 | 375 | ||
371 | if (port->write_urb->status != -EINPROGRESS) | 376 | if (port->write_urb_busy) |
372 | room = port->bulk_out_size - (safe ? 2 : 0); | 377 | room = port->bulk_out_size - (safe ? 2 : 0); |
373 | 378 | ||
374 | if (room) { | 379 | if (room) { |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 5da76dd8fb28..0267b26dde18 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -1047,6 +1047,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
1047 | memset(port, 0x00, sizeof(struct usb_serial_port)); | 1047 | memset(port, 0x00, sizeof(struct usb_serial_port)); |
1048 | port->number = i + serial->minor; | 1048 | port->number = i + serial->minor; |
1049 | port->serial = serial; | 1049 | port->serial = serial; |
1050 | spin_lock_init(&port->lock); | ||
1050 | INIT_WORK(&port->work, usb_serial_port_softint, port); | 1051 | INIT_WORK(&port->work, usb_serial_port_softint, port); |
1051 | serial->port[i] = port; | 1052 | serial->port[i] = port; |
1052 | } | 1053 | } |
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index d1f0c4057fa6..57f92f054c75 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h | |||
@@ -69,6 +69,7 @@ | |||
69 | * usb_serial_port: structure for the specific ports of a device. | 69 | * usb_serial_port: structure for the specific ports of a device. |
70 | * @serial: pointer back to the struct usb_serial owner of this port. | 70 | * @serial: pointer back to the struct usb_serial owner of this port. |
71 | * @tty: pointer to the corresponding tty for this port. | 71 | * @tty: pointer to the corresponding tty for this port. |
72 | * @lock: spinlock to grab when updating portions of this structure. | ||
72 | * @number: the number of the port (the minor number). | 73 | * @number: the number of the port (the minor number). |
73 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. | 74 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. |
74 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. | 75 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. |
@@ -98,6 +99,7 @@ | |||
98 | struct usb_serial_port { | 99 | struct usb_serial_port { |
99 | struct usb_serial * serial; | 100 | struct usb_serial * serial; |
100 | struct tty_struct * tty; | 101 | struct tty_struct * tty; |
102 | spinlock_t lock; | ||
101 | unsigned char number; | 103 | unsigned char number; |
102 | 104 | ||
103 | unsigned char * interrupt_in_buffer; | 105 | unsigned char * interrupt_in_buffer; |
@@ -117,6 +119,7 @@ struct usb_serial_port { | |||
117 | unsigned char * bulk_out_buffer; | 119 | unsigned char * bulk_out_buffer; |
118 | int bulk_out_size; | 120 | int bulk_out_size; |
119 | struct urb * write_urb; | 121 | struct urb * write_urb; |
122 | int write_urb_busy; | ||
120 | __u8 bulk_out_endpointAddress; | 123 | __u8 bulk_out_endpointAddress; |
121 | 124 | ||
122 | wait_queue_head_t write_wait; | 125 | wait_queue_head_t write_wait; |
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index e43eddc3d44b..af294bb68c35 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c | |||
@@ -155,6 +155,15 @@ static int slave_configure(struct scsi_device *sdev) | |||
155 | * If this device makes that mistake, tell the sd driver. */ | 155 | * If this device makes that mistake, tell the sd driver. */ |
156 | if (us->flags & US_FL_FIX_CAPACITY) | 156 | if (us->flags & US_FL_FIX_CAPACITY) |
157 | sdev->fix_capacity = 1; | 157 | sdev->fix_capacity = 1; |
158 | |||
159 | /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable | ||
160 | * Hardware Error) when any low-level error occurs, | ||
161 | * recoverable or not. Setting this flag tells the SCSI | ||
162 | * midlayer to retry such commands, which frequently will | ||
163 | * succeed and fix the error. The worst this can lead to | ||
164 | * is an occasional series of retries that will all fail. */ | ||
165 | sdev->retry_hwerror = 1; | ||
166 | |||
158 | } else { | 167 | } else { |
159 | 168 | ||
160 | /* Non-disk-type devices don't need to blacklist any pages | 169 | /* Non-disk-type devices don't need to blacklist any pages |
@@ -255,50 +264,23 @@ static int device_reset(struct scsi_cmnd *srb) | |||
255 | 264 | ||
256 | /* lock the device pointers and do the reset */ | 265 | /* lock the device pointers and do the reset */ |
257 | down(&(us->dev_semaphore)); | 266 | down(&(us->dev_semaphore)); |
258 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { | 267 | result = us->transport_reset(us); |
259 | result = FAILED; | ||
260 | US_DEBUGP("No reset during disconnect\n"); | ||
261 | } else | ||
262 | result = us->transport_reset(us); | ||
263 | up(&(us->dev_semaphore)); | 268 | up(&(us->dev_semaphore)); |
264 | 269 | ||
265 | return result; | 270 | return result < 0 ? FAILED : SUCCESS; |
266 | } | 271 | } |
267 | 272 | ||
268 | /* This resets the device's USB port. */ | 273 | /* Simulate a SCSI bus reset by resetting the device's USB port. */ |
269 | /* It refuses to work if there's more than one interface in | ||
270 | * the device, so that other users are not affected. */ | ||
271 | /* This is always called with scsi_lock(host) held */ | 274 | /* This is always called with scsi_lock(host) held */ |
272 | static int bus_reset(struct scsi_cmnd *srb) | 275 | static int bus_reset(struct scsi_cmnd *srb) |
273 | { | 276 | { |
274 | struct us_data *us = host_to_us(srb->device->host); | 277 | struct us_data *us = host_to_us(srb->device->host); |
275 | int result, rc; | 278 | int result; |
276 | 279 | ||
277 | US_DEBUGP("%s called\n", __FUNCTION__); | 280 | US_DEBUGP("%s called\n", __FUNCTION__); |
278 | 281 | ||
279 | /* The USB subsystem doesn't handle synchronisation between | ||
280 | * a device's several drivers. Therefore we reset only devices | ||
281 | * with just one interface, which we of course own. */ | ||
282 | |||
283 | down(&(us->dev_semaphore)); | 282 | down(&(us->dev_semaphore)); |
284 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { | 283 | result = usb_stor_port_reset(us); |
285 | result = -EIO; | ||
286 | US_DEBUGP("No reset during disconnect\n"); | ||
287 | } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) { | ||
288 | result = -EBUSY; | ||
289 | US_DEBUGP("Refusing to reset a multi-interface device\n"); | ||
290 | } else { | ||
291 | rc = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); | ||
292 | if (rc < 0) { | ||
293 | US_DEBUGP("unable to lock device for reset: %d\n", rc); | ||
294 | result = rc; | ||
295 | } else { | ||
296 | result = usb_reset_device(us->pusb_dev); | ||
297 | if (rc) | ||
298 | usb_unlock_device(us->pusb_dev); | ||
299 | US_DEBUGP("usb_reset_device returns %d\n", result); | ||
300 | } | ||
301 | } | ||
302 | up(&(us->dev_semaphore)); | 284 | up(&(us->dev_semaphore)); |
303 | 285 | ||
304 | /* lock the host for the return */ | 286 | /* lock the host for the return */ |
@@ -320,6 +302,14 @@ void usb_stor_report_device_reset(struct us_data *us) | |||
320 | } | 302 | } |
321 | } | 303 | } |
322 | 304 | ||
305 | /* Report a driver-initiated bus reset to the SCSI layer. | ||
306 | * Calling this for a SCSI-initiated reset is unnecessary but harmless. | ||
307 | * The caller must own the SCSI host lock. */ | ||
308 | void usb_stor_report_bus_reset(struct us_data *us) | ||
309 | { | ||
310 | scsi_report_bus_reset(us_to_host(us), 0); | ||
311 | } | ||
312 | |||
323 | /*********************************************************************** | 313 | /*********************************************************************** |
324 | * /proc/scsi/ functions | 314 | * /proc/scsi/ functions |
325 | ***********************************************************************/ | 315 | ***********************************************************************/ |
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h index d0a49af026c4..737e4fa6045f 100644 --- a/drivers/usb/storage/scsiglue.h +++ b/drivers/usb/storage/scsiglue.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define _SCSIGLUE_H_ | 42 | #define _SCSIGLUE_H_ |
43 | 43 | ||
44 | extern void usb_stor_report_device_reset(struct us_data *us); | 44 | extern void usb_stor_report_device_reset(struct us_data *us); |
45 | extern void usb_stor_report_bus_reset(struct us_data *us); | ||
45 | 46 | ||
46 | extern unsigned char usb_stor_sense_invalidCDB[18]; | 47 | extern unsigned char usb_stor_sense_invalidCDB[18]; |
47 | extern struct scsi_host_template usb_stor_host_template; | 48 | extern struct scsi_host_template usb_stor_host_template; |
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 9743e289cd3b..e6b1c6cf07f2 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c | |||
@@ -266,8 +266,9 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) | |||
266 | NULL, 0, 3*HZ); | 266 | NULL, 0, 3*HZ); |
267 | 267 | ||
268 | /* reset the endpoint toggle */ | 268 | /* reset the endpoint toggle */ |
269 | usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), | 269 | if (result >= 0) |
270 | usb_pipeout(pipe), 0); | 270 | usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), |
271 | usb_pipeout(pipe), 0); | ||
271 | 272 | ||
272 | US_DEBUGP("%s: result = %d\n", __FUNCTION__, result); | 273 | US_DEBUGP("%s: result = %d\n", __FUNCTION__, result); |
273 | return result; | 274 | return result; |
@@ -540,15 +541,15 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
540 | */ | 541 | */ |
541 | if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { | 542 | if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { |
542 | US_DEBUGP("-- command was aborted\n"); | 543 | US_DEBUGP("-- command was aborted\n"); |
543 | goto Handle_Abort; | 544 | srb->result = DID_ABORT << 16; |
545 | goto Handle_Errors; | ||
544 | } | 546 | } |
545 | 547 | ||
546 | /* if there is a transport error, reset and don't auto-sense */ | 548 | /* if there is a transport error, reset and don't auto-sense */ |
547 | if (result == USB_STOR_TRANSPORT_ERROR) { | 549 | if (result == USB_STOR_TRANSPORT_ERROR) { |
548 | US_DEBUGP("-- transport indicates error, resetting\n"); | 550 | US_DEBUGP("-- transport indicates error, resetting\n"); |
549 | us->transport_reset(us); | ||
550 | srb->result = DID_ERROR << 16; | 551 | srb->result = DID_ERROR << 16; |
551 | return; | 552 | goto Handle_Errors; |
552 | } | 553 | } |
553 | 554 | ||
554 | /* if the transport provided its own sense data, don't auto-sense */ | 555 | /* if the transport provided its own sense data, don't auto-sense */ |
@@ -668,7 +669,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
668 | 669 | ||
669 | if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { | 670 | if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { |
670 | US_DEBUGP("-- auto-sense aborted\n"); | 671 | US_DEBUGP("-- auto-sense aborted\n"); |
671 | goto Handle_Abort; | 672 | srb->result = DID_ABORT << 16; |
673 | goto Handle_Errors; | ||
672 | } | 674 | } |
673 | if (temp_result != USB_STOR_TRANSPORT_GOOD) { | 675 | if (temp_result != USB_STOR_TRANSPORT_GOOD) { |
674 | US_DEBUGP("-- auto-sense failure\n"); | 676 | US_DEBUGP("-- auto-sense failure\n"); |
@@ -677,9 +679,9 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
677 | * multi-target device, since failure of an | 679 | * multi-target device, since failure of an |
678 | * auto-sense is perfectly valid | 680 | * auto-sense is perfectly valid |
679 | */ | 681 | */ |
680 | if (!(us->flags & US_FL_SCM_MULT_TARG)) | ||
681 | us->transport_reset(us); | ||
682 | srb->result = DID_ERROR << 16; | 682 | srb->result = DID_ERROR << 16; |
683 | if (!(us->flags & US_FL_SCM_MULT_TARG)) | ||
684 | goto Handle_Errors; | ||
683 | return; | 685 | return; |
684 | } | 686 | } |
685 | 687 | ||
@@ -720,12 +722,28 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
720 | 722 | ||
721 | return; | 723 | return; |
722 | 724 | ||
723 | /* abort processing: the bulk-only transport requires a reset | 725 | /* Error and abort processing: try to resynchronize with the device |
724 | * following an abort */ | 726 | * by issuing a port reset. If that fails, try a class-specific |
725 | Handle_Abort: | 727 | * device reset. */ |
726 | srb->result = DID_ABORT << 16; | 728 | Handle_Errors: |
727 | if (us->protocol == US_PR_BULK) | 729 | |
730 | /* Let the SCSI layer know we are doing a reset, set the | ||
731 | * RESETTING bit, and clear the ABORTING bit so that the reset | ||
732 | * may proceed. */ | ||
733 | scsi_lock(us_to_host(us)); | ||
734 | usb_stor_report_bus_reset(us); | ||
735 | set_bit(US_FLIDX_RESETTING, &us->flags); | ||
736 | clear_bit(US_FLIDX_ABORTING, &us->flags); | ||
737 | scsi_unlock(us_to_host(us)); | ||
738 | |||
739 | result = usb_stor_port_reset(us); | ||
740 | if (result < 0) { | ||
741 | scsi_lock(us_to_host(us)); | ||
742 | usb_stor_report_device_reset(us); | ||
743 | scsi_unlock(us_to_host(us)); | ||
728 | us->transport_reset(us); | 744 | us->transport_reset(us); |
745 | } | ||
746 | clear_bit(US_FLIDX_RESETTING, &us->flags); | ||
729 | } | 747 | } |
730 | 748 | ||
731 | /* Stop the current URB transfer */ | 749 | /* Stop the current URB transfer */ |
@@ -1124,7 +1142,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1124 | * It's handy that every transport mechanism uses the control endpoint for | 1142 | * It's handy that every transport mechanism uses the control endpoint for |
1125 | * resets. | 1143 | * resets. |
1126 | * | 1144 | * |
1127 | * Basically, we send a reset with a 20-second timeout, so we don't get | 1145 | * Basically, we send a reset with a 5-second timeout, so we don't get |
1128 | * jammed attempting to do the reset. | 1146 | * jammed attempting to do the reset. |
1129 | */ | 1147 | */ |
1130 | static int usb_stor_reset_common(struct us_data *us, | 1148 | static int usb_stor_reset_common(struct us_data *us, |
@@ -1133,28 +1151,18 @@ static int usb_stor_reset_common(struct us_data *us, | |||
1133 | { | 1151 | { |
1134 | int result; | 1152 | int result; |
1135 | int result2; | 1153 | int result2; |
1136 | int rc = FAILED; | ||
1137 | 1154 | ||
1138 | /* Let the SCSI layer know we are doing a reset, set the | 1155 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { |
1139 | * RESETTING bit, and clear the ABORTING bit so that the reset | 1156 | US_DEBUGP("No reset during disconnect\n"); |
1140 | * may proceed. | 1157 | return -EIO; |
1141 | */ | 1158 | } |
1142 | scsi_lock(us_to_host(us)); | ||
1143 | usb_stor_report_device_reset(us); | ||
1144 | set_bit(US_FLIDX_RESETTING, &us->flags); | ||
1145 | clear_bit(US_FLIDX_ABORTING, &us->flags); | ||
1146 | scsi_unlock(us_to_host(us)); | ||
1147 | 1159 | ||
1148 | /* A 20-second timeout may seem rather long, but a LaCie | ||
1149 | * StudioDrive USB2 device takes 16+ seconds to get going | ||
1150 | * following a powerup or USB attach event. | ||
1151 | */ | ||
1152 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, | 1160 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, |
1153 | request, requesttype, value, index, data, size, | 1161 | request, requesttype, value, index, data, size, |
1154 | 20*HZ); | 1162 | 5*HZ); |
1155 | if (result < 0) { | 1163 | if (result < 0) { |
1156 | US_DEBUGP("Soft reset failed: %d\n", result); | 1164 | US_DEBUGP("Soft reset failed: %d\n", result); |
1157 | goto Done; | 1165 | return result; |
1158 | } | 1166 | } |
1159 | 1167 | ||
1160 | /* Give the device some time to recover from the reset, | 1168 | /* Give the device some time to recover from the reset, |
@@ -1164,7 +1172,7 @@ static int usb_stor_reset_common(struct us_data *us, | |||
1164 | HZ*6); | 1172 | HZ*6); |
1165 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { | 1173 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { |
1166 | US_DEBUGP("Reset interrupted by disconnect\n"); | 1174 | US_DEBUGP("Reset interrupted by disconnect\n"); |
1167 | goto Done; | 1175 | return -EIO; |
1168 | } | 1176 | } |
1169 | 1177 | ||
1170 | US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); | 1178 | US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); |
@@ -1173,17 +1181,14 @@ static int usb_stor_reset_common(struct us_data *us, | |||
1173 | US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); | 1181 | US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); |
1174 | result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); | 1182 | result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); |
1175 | 1183 | ||
1176 | /* return a result code based on the result of the control message */ | 1184 | /* return a result code based on the result of the clear-halts */ |
1177 | if (result < 0 || result2 < 0) { | 1185 | if (result >= 0) |
1186 | result = result2; | ||
1187 | if (result < 0) | ||
1178 | US_DEBUGP("Soft reset failed\n"); | 1188 | US_DEBUGP("Soft reset failed\n"); |
1179 | goto Done; | 1189 | else |
1180 | } | 1190 | US_DEBUGP("Soft reset done\n"); |
1181 | US_DEBUGP("Soft reset done\n"); | 1191 | return result; |
1182 | rc = SUCCESS; | ||
1183 | |||
1184 | Done: | ||
1185 | clear_bit(US_FLIDX_RESETTING, &us->flags); | ||
1186 | return rc; | ||
1187 | } | 1192 | } |
1188 | 1193 | ||
1189 | /* This issues a CB[I] Reset to the device in question | 1194 | /* This issues a CB[I] Reset to the device in question |
@@ -1213,3 +1218,32 @@ int usb_stor_Bulk_reset(struct us_data *us) | |||
1213 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 1218 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
1214 | 0, us->ifnum, NULL, 0); | 1219 | 0, us->ifnum, NULL, 0); |
1215 | } | 1220 | } |
1221 | |||
1222 | /* Issue a USB port reset to the device. But don't do anything if | ||
1223 | * there's more than one interface in the device, so that other users | ||
1224 | * are not affected. */ | ||
1225 | int usb_stor_port_reset(struct us_data *us) | ||
1226 | { | ||
1227 | int result, rc; | ||
1228 | |||
1229 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { | ||
1230 | result = -EIO; | ||
1231 | US_DEBUGP("No reset during disconnect\n"); | ||
1232 | } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) { | ||
1233 | result = -EBUSY; | ||
1234 | US_DEBUGP("Refusing to reset a multi-interface device\n"); | ||
1235 | } else { | ||
1236 | result = rc = | ||
1237 | usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); | ||
1238 | if (result < 0) { | ||
1239 | US_DEBUGP("unable to lock device for reset: %d\n", | ||
1240 | result); | ||
1241 | } else { | ||
1242 | result = usb_reset_device(us->pusb_dev); | ||
1243 | if (rc) | ||
1244 | usb_unlock_device(us->pusb_dev); | ||
1245 | US_DEBUGP("usb_reset_device returns %d\n", result); | ||
1246 | } | ||
1247 | } | ||
1248 | return result; | ||
1249 | } | ||
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index e25f8d8fc741..8d9e0663f8fe 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h | |||
@@ -171,4 +171,5 @@ extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, | |||
171 | extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe, | 171 | extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe, |
172 | void *buf, unsigned int length, int use_sg, int *residual); | 172 | void *buf, unsigned int length, int use_sg, int *residual); |
173 | 173 | ||
174 | extern int usb_stor_port_reset(struct us_data *us); | ||
174 | #endif | 175 | #endif |
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 9789115980a5..7bc1d44d8814 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
@@ -350,10 +350,8 @@ static int default_vmode __initdata = VMODE_1024_768_60; | |||
350 | static int default_cmode __initdata = CMODE_8; | 350 | static int default_cmode __initdata = CMODE_8; |
351 | #endif | 351 | #endif |
352 | 352 | ||
353 | #ifdef CONFIG_PMAC_PBOOK | ||
354 | static int default_crt_on __initdata = 0; | 353 | static int default_crt_on __initdata = 0; |
355 | static int default_lcd_on __initdata = 1; | 354 | static int default_lcd_on __initdata = 1; |
356 | #endif | ||
357 | 355 | ||
358 | #ifdef CONFIG_MTRR | 356 | #ifdef CONFIG_MTRR |
359 | static int mtrr = 1; | 357 | static int mtrr = 1; |
@@ -1249,7 +1247,6 @@ static int aty128_crtc_to_var(const struct aty128_crtc *crtc, | |||
1249 | return 0; | 1247 | return 0; |
1250 | } | 1248 | } |
1251 | 1249 | ||
1252 | #ifdef CONFIG_PMAC_PBOOK | ||
1253 | static void aty128_set_crt_enable(struct aty128fb_par *par, int on) | 1250 | static void aty128_set_crt_enable(struct aty128fb_par *par, int on) |
1254 | { | 1251 | { |
1255 | if (on) { | 1252 | if (on) { |
@@ -1284,7 +1281,6 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) | |||
1284 | aty_st_le32(LVDS_GEN_CNTL, reg); | 1281 | aty_st_le32(LVDS_GEN_CNTL, reg); |
1285 | } | 1282 | } |
1286 | } | 1283 | } |
1287 | #endif /* CONFIG_PMAC_PBOOK */ | ||
1288 | 1284 | ||
1289 | static void aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par) | 1285 | static void aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par) |
1290 | { | 1286 | { |
@@ -1491,12 +1487,10 @@ static int aty128fb_set_par(struct fb_info *info) | |||
1491 | info->fix.visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR | 1487 | info->fix.visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR |
1492 | : FB_VISUAL_DIRECTCOLOR; | 1488 | : FB_VISUAL_DIRECTCOLOR; |
1493 | 1489 | ||
1494 | #ifdef CONFIG_PMAC_PBOOK | ||
1495 | if (par->chip_gen == rage_M3) { | 1490 | if (par->chip_gen == rage_M3) { |
1496 | aty128_set_crt_enable(par, par->crt_on); | 1491 | aty128_set_crt_enable(par, par->crt_on); |
1497 | aty128_set_lcd_enable(par, par->lcd_on); | 1492 | aty128_set_lcd_enable(par, par->lcd_on); |
1498 | } | 1493 | } |
1499 | #endif | ||
1500 | if (par->accel_flags & FB_ACCELF_TEXT) | 1494 | if (par->accel_flags & FB_ACCELF_TEXT) |
1501 | aty128_init_engine(par); | 1495 | aty128_init_engine(par); |
1502 | 1496 | ||
@@ -1652,7 +1646,6 @@ static int __init aty128fb_setup(char *options) | |||
1652 | return 0; | 1646 | return 0; |
1653 | 1647 | ||
1654 | while ((this_opt = strsep(&options, ",")) != NULL) { | 1648 | while ((this_opt = strsep(&options, ",")) != NULL) { |
1655 | #ifdef CONFIG_PMAC_PBOOK | ||
1656 | if (!strncmp(this_opt, "lcd:", 4)) { | 1649 | if (!strncmp(this_opt, "lcd:", 4)) { |
1657 | default_lcd_on = simple_strtoul(this_opt+4, NULL, 0); | 1650 | default_lcd_on = simple_strtoul(this_opt+4, NULL, 0); |
1658 | continue; | 1651 | continue; |
@@ -1660,7 +1653,6 @@ static int __init aty128fb_setup(char *options) | |||
1660 | default_crt_on = simple_strtoul(this_opt+4, NULL, 0); | 1653 | default_crt_on = simple_strtoul(this_opt+4, NULL, 0); |
1661 | continue; | 1654 | continue; |
1662 | } | 1655 | } |
1663 | #endif | ||
1664 | #ifdef CONFIG_MTRR | 1656 | #ifdef CONFIG_MTRR |
1665 | if(!strncmp(this_opt, "nomtrr", 6)) { | 1657 | if(!strncmp(this_opt, "nomtrr", 6)) { |
1666 | mtrr = 0; | 1658 | mtrr = 0; |
@@ -1752,10 +1744,8 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id * | |||
1752 | info->fbops = &aty128fb_ops; | 1744 | info->fbops = &aty128fb_ops; |
1753 | info->flags = FBINFO_FLAG_DEFAULT; | 1745 | info->flags = FBINFO_FLAG_DEFAULT; |
1754 | 1746 | ||
1755 | #ifdef CONFIG_PMAC_PBOOK | ||
1756 | par->lcd_on = default_lcd_on; | 1747 | par->lcd_on = default_lcd_on; |
1757 | par->crt_on = default_crt_on; | 1748 | par->crt_on = default_crt_on; |
1758 | #endif | ||
1759 | 1749 | ||
1760 | var = default_var; | 1750 | var = default_var; |
1761 | #ifdef CONFIG_PPC_PMAC | 1751 | #ifdef CONFIG_PPC_PMAC |
@@ -2035,12 +2025,10 @@ static int aty128fb_blank(int blank, struct fb_info *fb) | |||
2035 | 2025 | ||
2036 | aty_st_8(CRTC_EXT_CNTL+1, state); | 2026 | aty_st_8(CRTC_EXT_CNTL+1, state); |
2037 | 2027 | ||
2038 | #ifdef CONFIG_PMAC_PBOOK | ||
2039 | if (par->chip_gen == rage_M3) { | 2028 | if (par->chip_gen == rage_M3) { |
2040 | aty128_set_crt_enable(par, par->crt_on && !blank); | 2029 | aty128_set_crt_enable(par, par->crt_on && !blank); |
2041 | aty128_set_lcd_enable(par, par->lcd_on && !blank); | 2030 | aty128_set_lcd_enable(par, par->lcd_on && !blank); |
2042 | } | 2031 | } |
2043 | #endif | ||
2044 | #ifdef CONFIG_PMAC_BACKLIGHT | 2032 | #ifdef CONFIG_PMAC_BACKLIGHT |
2045 | if ((_machine == _MACH_Pmac) && !blank) | 2033 | if ((_machine == _MACH_Pmac) && !blank) |
2046 | set_backlight_enable(1); | 2034 | set_backlight_enable(1); |
@@ -2124,7 +2112,6 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
2124 | static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, | 2112 | static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, |
2125 | u_long arg, struct fb_info *info) | 2113 | u_long arg, struct fb_info *info) |
2126 | { | 2114 | { |
2127 | #ifdef CONFIG_PMAC_PBOOK | ||
2128 | struct aty128fb_par *par = info->par; | 2115 | struct aty128fb_par *par = info->par; |
2129 | u32 value; | 2116 | u32 value; |
2130 | int rc; | 2117 | int rc; |
@@ -2149,7 +2136,6 @@ static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, | |||
2149 | value = (par->crt_on << 1) | par->lcd_on; | 2136 | value = (par->crt_on << 1) | par->lcd_on; |
2150 | return put_user(value, (__u32 __user *)arg); | 2137 | return put_user(value, (__u32 __user *)arg); |
2151 | } | 2138 | } |
2152 | #endif | ||
2153 | return -EINVAL; | 2139 | return -EINVAL; |
2154 | } | 2140 | } |
2155 | 2141 | ||
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 95e72550d43f..e75a965ec760 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c | |||
@@ -28,22 +28,17 @@ | |||
28 | #include <linux/fb.h> | 28 | #include <linux/fb.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <linux/console.h> | ||
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
32 | 33 | ||
33 | #ifdef CONFIG_PMAC_BACKLIGHT | 34 | #ifdef CONFIG_PMAC_BACKLIGHT |
34 | #include <asm/backlight.h> | 35 | #include <asm/backlight.h> |
35 | #endif | 36 | #endif |
36 | #ifdef CONFIG_PMAC_PBOOK | ||
37 | #include <linux/adb.h> | ||
38 | #include <linux/pmu.h> | ||
39 | #endif | ||
40 | 37 | ||
41 | /* | 38 | /* |
42 | * Since we access the display with inb/outb to fixed port numbers, | 39 | * Since we access the display with inb/outb to fixed port numbers, |
43 | * we can only handle one 6555x chip. -- paulus | 40 | * we can only handle one 6555x chip. -- paulus |
44 | */ | 41 | */ |
45 | static struct fb_info chipsfb_info; | ||
46 | |||
47 | #define write_ind(num, val, ap, dp) do { \ | 42 | #define write_ind(num, val, ap, dp) do { \ |
48 | outb((num), (ap)); outb((val), (dp)); \ | 43 | outb((num), (ap)); outb((val), (dp)); \ |
49 | } while (0) | 44 | } while (0) |
@@ -74,14 +69,6 @@ static struct fb_info chipsfb_info; | |||
74 | inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); \ | 69 | inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); \ |
75 | } while (0) | 70 | } while (0) |
76 | 71 | ||
77 | #ifdef CONFIG_PMAC_PBOOK | ||
78 | static unsigned char *save_framebuffer; | ||
79 | int chips_sleep_notify(struct pmu_sleep_notifier *self, int when); | ||
80 | static struct pmu_sleep_notifier chips_sleep_notifier = { | ||
81 | chips_sleep_notify, SLEEP_LEVEL_VIDEO, | ||
82 | }; | ||
83 | #endif | ||
84 | |||
85 | /* | 72 | /* |
86 | * Exported functions | 73 | * Exported functions |
87 | */ | 74 | */ |
@@ -356,6 +343,8 @@ static struct fb_var_screeninfo chipsfb_var __initdata = { | |||
356 | 343 | ||
357 | static void __init init_chips(struct fb_info *p, unsigned long addr) | 344 | static void __init init_chips(struct fb_info *p, unsigned long addr) |
358 | { | 345 | { |
346 | memset(p->screen_base, 0, 0x100000); | ||
347 | |||
359 | p->fix = chipsfb_fix; | 348 | p->fix = chipsfb_fix; |
360 | p->fix.smem_start = addr; | 349 | p->fix.smem_start = addr; |
361 | 350 | ||
@@ -366,34 +355,41 @@ static void __init init_chips(struct fb_info *p, unsigned long addr) | |||
366 | 355 | ||
367 | fb_alloc_cmap(&p->cmap, 256, 0); | 356 | fb_alloc_cmap(&p->cmap, 256, 0); |
368 | 357 | ||
369 | if (register_framebuffer(p) < 0) { | ||
370 | printk(KERN_ERR "C&T 65550 framebuffer failed to register\n"); | ||
371 | return; | ||
372 | } | ||
373 | |||
374 | printk(KERN_INFO "fb%d: Chips 65550 frame buffer (%dK RAM detected)\n", | ||
375 | p->node, p->fix.smem_len / 1024); | ||
376 | |||
377 | chips_hw_init(); | 358 | chips_hw_init(); |
378 | } | 359 | } |
379 | 360 | ||
380 | static int __devinit | 361 | static int __devinit |
381 | chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) | 362 | chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) |
382 | { | 363 | { |
383 | struct fb_info *p = &chipsfb_info; | 364 | struct fb_info *p; |
384 | unsigned long addr, size; | 365 | unsigned long addr, size; |
385 | unsigned short cmd; | 366 | unsigned short cmd; |
367 | int rc = -ENODEV; | ||
368 | |||
369 | if (pci_enable_device(dp) < 0) { | ||
370 | dev_err(&dp->dev, "Cannot enable PCI device\n"); | ||
371 | goto err_out; | ||
372 | } | ||
386 | 373 | ||
387 | if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) | 374 | if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) |
388 | return -ENODEV; | 375 | goto err_disable; |
389 | addr = pci_resource_start(dp, 0); | 376 | addr = pci_resource_start(dp, 0); |
390 | size = pci_resource_len(dp, 0); | 377 | size = pci_resource_len(dp, 0); |
391 | if (addr == 0) | 378 | if (addr == 0) |
392 | return -ENODEV; | 379 | goto err_disable; |
393 | if (p->screen_base != 0) | 380 | |
394 | return -EBUSY; | 381 | p = framebuffer_alloc(0, &dp->dev); |
395 | if (!request_mem_region(addr, size, "chipsfb")) | 382 | if (p == NULL) { |
396 | return -EBUSY; | 383 | dev_err(&dp->dev, "Cannot allocate framebuffer structure\n"); |
384 | rc = -ENOMEM; | ||
385 | goto err_disable; | ||
386 | } | ||
387 | |||
388 | if (pci_request_region(dp, 0, "chipsfb") != 0) { | ||
389 | dev_err(&dp->dev, "Cannot request framebuffer\n"); | ||
390 | rc = -EBUSY; | ||
391 | goto err_release_fb; | ||
392 | } | ||
397 | 393 | ||
398 | #ifdef __BIG_ENDIAN | 394 | #ifdef __BIG_ENDIAN |
399 | addr += 0x800000; // Use big-endian aperture | 395 | addr += 0x800000; // Use big-endian aperture |
@@ -411,37 +407,89 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) | |||
411 | set_backlight_enable(1); | 407 | set_backlight_enable(1); |
412 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 408 | #endif /* CONFIG_PMAC_BACKLIGHT */ |
413 | 409 | ||
410 | #ifdef CONFIG_PPC | ||
414 | p->screen_base = __ioremap(addr, 0x200000, _PAGE_NO_CACHE); | 411 | p->screen_base = __ioremap(addr, 0x200000, _PAGE_NO_CACHE); |
412 | #else | ||
413 | p->screen_base = ioremap(addr, 0x200000); | ||
414 | #endif | ||
415 | if (p->screen_base == NULL) { | 415 | if (p->screen_base == NULL) { |
416 | release_mem_region(addr, size); | 416 | dev_err(&dp->dev, "Cannot map framebuffer\n"); |
417 | return -ENOMEM; | 417 | rc = -ENOMEM; |
418 | goto err_release_pci; | ||
418 | } | 419 | } |
420 | |||
421 | pci_set_drvdata(dp, p); | ||
419 | p->device = &dp->dev; | 422 | p->device = &dp->dev; |
423 | |||
420 | init_chips(p, addr); | 424 | init_chips(p, addr); |
421 | 425 | ||
422 | #ifdef CONFIG_PMAC_PBOOK | 426 | if (register_framebuffer(p) < 0) { |
423 | pmu_register_sleep_notifier(&chips_sleep_notifier); | 427 | dev_err(&dp->dev,"C&T 65550 framebuffer failed to register\n"); |
424 | #endif /* CONFIG_PMAC_PBOOK */ | 428 | goto err_unmap; |
429 | } | ||
430 | |||
431 | dev_info(&dp->dev,"fb%d: Chips 65550 frame buffer" | ||
432 | " (%dK RAM detected)\n", | ||
433 | p->node, p->fix.smem_len / 1024); | ||
425 | 434 | ||
426 | pci_set_drvdata(dp, p); | ||
427 | return 0; | 435 | return 0; |
436 | |||
437 | err_unmap: | ||
438 | iounmap(p->screen_base); | ||
439 | err_release_pci: | ||
440 | pci_release_region(dp, 0); | ||
441 | err_release_fb: | ||
442 | framebuffer_release(p); | ||
443 | err_disable: | ||
444 | err_out: | ||
445 | return rc; | ||
428 | } | 446 | } |
429 | 447 | ||
430 | static void __devexit chipsfb_remove(struct pci_dev *dp) | 448 | static void __devexit chipsfb_remove(struct pci_dev *dp) |
431 | { | 449 | { |
432 | struct fb_info *p = pci_get_drvdata(dp); | 450 | struct fb_info *p = pci_get_drvdata(dp); |
433 | 451 | ||
434 | if (p != &chipsfb_info || p->screen_base == NULL) | 452 | if (p->screen_base == NULL) |
435 | return; | 453 | return; |
436 | unregister_framebuffer(p); | 454 | unregister_framebuffer(p); |
437 | iounmap(p->screen_base); | 455 | iounmap(p->screen_base); |
438 | p->screen_base = NULL; | 456 | p->screen_base = NULL; |
439 | release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0)); | 457 | pci_release_region(dp, 0); |
458 | } | ||
459 | |||
460 | #ifdef CONFIG_PM | ||
461 | static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
462 | { | ||
463 | struct fb_info *p = pci_get_drvdata(pdev); | ||
464 | |||
465 | if (state == pdev->dev.power.power_state) | ||
466 | return 0; | ||
467 | if (state != PM_SUSPEND_MEM) | ||
468 | goto done; | ||
469 | |||
470 | acquire_console_sem(); | ||
471 | chipsfb_blank(1, p); | ||
472 | fb_set_suspend(p, 1); | ||
473 | release_console_sem(); | ||
474 | done: | ||
475 | pdev->dev.power.power_state = state; | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int chipsfb_pci_resume(struct pci_dev *pdev) | ||
480 | { | ||
481 | struct fb_info *p = pci_get_drvdata(pdev); | ||
440 | 482 | ||
441 | #ifdef CONFIG_PMAC_PBOOK | 483 | acquire_console_sem(); |
442 | pmu_unregister_sleep_notifier(&chips_sleep_notifier); | 484 | fb_set_suspend(p, 0); |
443 | #endif /* CONFIG_PMAC_PBOOK */ | 485 | chipsfb_blank(0, p); |
486 | release_console_sem(); | ||
487 | |||
488 | pdev->dev.power.power_state = PMSG_ON; | ||
489 | return 0; | ||
444 | } | 490 | } |
491 | #endif /* CONFIG_PM */ | ||
492 | |||
445 | 493 | ||
446 | static struct pci_device_id chipsfb_pci_tbl[] = { | 494 | static struct pci_device_id chipsfb_pci_tbl[] = { |
447 | { PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_65550, PCI_ANY_ID, PCI_ANY_ID }, | 495 | { PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_65550, PCI_ANY_ID, PCI_ANY_ID }, |
@@ -455,6 +503,10 @@ static struct pci_driver chipsfb_driver = { | |||
455 | .id_table = chipsfb_pci_tbl, | 503 | .id_table = chipsfb_pci_tbl, |
456 | .probe = chipsfb_pci_init, | 504 | .probe = chipsfb_pci_init, |
457 | .remove = __devexit_p(chipsfb_remove), | 505 | .remove = __devexit_p(chipsfb_remove), |
506 | #ifdef CONFIG_PM | ||
507 | .suspend = chipsfb_pci_suspend, | ||
508 | .resume = chipsfb_pci_resume, | ||
509 | #endif | ||
458 | }; | 510 | }; |
459 | 511 | ||
460 | int __init chips_init(void) | 512 | int __init chips_init(void) |
@@ -472,48 +524,4 @@ static void __exit chipsfb_exit(void) | |||
472 | pci_unregister_driver(&chipsfb_driver); | 524 | pci_unregister_driver(&chipsfb_driver); |
473 | } | 525 | } |
474 | 526 | ||
475 | #ifdef CONFIG_PMAC_PBOOK | ||
476 | /* | ||
477 | * Save the contents of the frame buffer when we go to sleep, | ||
478 | * and restore it when we wake up again. | ||
479 | */ | ||
480 | int | ||
481 | chips_sleep_notify(struct pmu_sleep_notifier *self, int when) | ||
482 | { | ||
483 | struct fb_info *p = &chipsfb_info; | ||
484 | int nb = p->var.yres * p->fix.line_length; | ||
485 | |||
486 | if (p->screen_base == NULL) | ||
487 | return PBOOK_SLEEP_OK; | ||
488 | |||
489 | switch (when) { | ||
490 | case PBOOK_SLEEP_REQUEST: | ||
491 | save_framebuffer = vmalloc(nb); | ||
492 | if (save_framebuffer == NULL) | ||
493 | return PBOOK_SLEEP_REFUSE; | ||
494 | break; | ||
495 | case PBOOK_SLEEP_REJECT: | ||
496 | if (save_framebuffer) { | ||
497 | vfree(save_framebuffer); | ||
498 | save_framebuffer = NULL; | ||
499 | } | ||
500 | break; | ||
501 | case PBOOK_SLEEP_NOW: | ||
502 | chipsfb_blank(1, p); | ||
503 | if (save_framebuffer) | ||
504 | memcpy(save_framebuffer, p->screen_base, nb); | ||
505 | break; | ||
506 | case PBOOK_WAKE: | ||
507 | if (save_framebuffer) { | ||
508 | memcpy(p->screen_base, save_framebuffer, nb); | ||
509 | vfree(save_framebuffer); | ||
510 | save_framebuffer = NULL; | ||
511 | } | ||
512 | chipsfb_blank(0, p); | ||
513 | break; | ||
514 | } | ||
515 | return PBOOK_SLEEP_OK; | ||
516 | } | ||
517 | #endif /* CONFIG_PMAC_PBOOK */ | ||
518 | |||
519 | MODULE_LICENSE("GPL"); | 527 | MODULE_LICENSE("GPL"); |
diff --git a/fs/Makefile b/fs/Makefile index fc92e59e9faf..20edcf28bfd2 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -10,6 +10,7 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \ | |||
10 | ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ | 10 | ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ |
11 | attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ | 11 | attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ |
12 | seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ | 12 | seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ |
13 | ioprio.o | ||
13 | 14 | ||
14 | obj-$(CONFIG_EPOLL) += eventpoll.o | 15 | obj-$(CONFIG_EPOLL) += eventpoll.o |
15 | obj-$(CONFIG_COMPAT) += compat.o | 16 | obj-$(CONFIG_COMPAT) += compat.o |
diff --git a/fs/ioprio.c b/fs/ioprio.c new file mode 100644 index 000000000000..663e420636d6 --- /dev/null +++ b/fs/ioprio.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * fs/ioprio.c | ||
3 | * | ||
4 | * Copyright (C) 2004 Jens Axboe <axboe@suse.de> | ||
5 | * | ||
6 | * Helper functions for setting/querying io priorities of processes. The | ||
7 | * system calls closely mimmick getpriority/setpriority, see the man page for | ||
8 | * those. The prio argument is a composite of prio class and prio data, where | ||
9 | * the data argument has meaning within that class. The standard scheduling | ||
10 | * classes have 8 distinct prio levels, with 0 being the highest prio and 7 | ||
11 | * being the lowest. | ||
12 | * | ||
13 | * IOW, setting BE scheduling class with prio 2 is done ala: | ||
14 | * | ||
15 | * unsigned int prio = (IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT) | 2; | ||
16 | * | ||
17 | * ioprio_set(PRIO_PROCESS, pid, prio); | ||
18 | * | ||
19 | * See also Documentation/block/ioprio.txt | ||
20 | * | ||
21 | */ | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/ioprio.h> | ||
24 | #include <linux/blkdev.h> | ||
25 | |||
26 | static int set_task_ioprio(struct task_struct *task, int ioprio) | ||
27 | { | ||
28 | struct io_context *ioc; | ||
29 | |||
30 | if (task->uid != current->euid && | ||
31 | task->uid != current->uid && !capable(CAP_SYS_NICE)) | ||
32 | return -EPERM; | ||
33 | |||
34 | task_lock(task); | ||
35 | |||
36 | task->ioprio = ioprio; | ||
37 | |||
38 | ioc = task->io_context; | ||
39 | if (ioc && ioc->set_ioprio) | ||
40 | ioc->set_ioprio(ioc, ioprio); | ||
41 | |||
42 | task_unlock(task); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | asmlinkage int sys_ioprio_set(int which, int who, int ioprio) | ||
47 | { | ||
48 | int class = IOPRIO_PRIO_CLASS(ioprio); | ||
49 | int data = IOPRIO_PRIO_DATA(ioprio); | ||
50 | struct task_struct *p, *g; | ||
51 | struct user_struct *user; | ||
52 | int ret; | ||
53 | |||
54 | switch (class) { | ||
55 | case IOPRIO_CLASS_RT: | ||
56 | if (!capable(CAP_SYS_ADMIN)) | ||
57 | return -EPERM; | ||
58 | /* fall through, rt has prio field too */ | ||
59 | case IOPRIO_CLASS_BE: | ||
60 | if (data >= IOPRIO_BE_NR || data < 0) | ||
61 | return -EINVAL; | ||
62 | |||
63 | break; | ||
64 | case IOPRIO_CLASS_IDLE: | ||
65 | break; | ||
66 | default: | ||
67 | return -EINVAL; | ||
68 | } | ||
69 | |||
70 | ret = -ESRCH; | ||
71 | read_lock_irq(&tasklist_lock); | ||
72 | switch (which) { | ||
73 | case IOPRIO_WHO_PROCESS: | ||
74 | if (!who) | ||
75 | p = current; | ||
76 | else | ||
77 | p = find_task_by_pid(who); | ||
78 | if (p) | ||
79 | ret = set_task_ioprio(p, ioprio); | ||
80 | break; | ||
81 | case IOPRIO_WHO_PGRP: | ||
82 | if (!who) | ||
83 | who = process_group(current); | ||
84 | do_each_task_pid(who, PIDTYPE_PGID, p) { | ||
85 | ret = set_task_ioprio(p, ioprio); | ||
86 | if (ret) | ||
87 | break; | ||
88 | } while_each_task_pid(who, PIDTYPE_PGID, p); | ||
89 | break; | ||
90 | case IOPRIO_WHO_USER: | ||
91 | if (!who) | ||
92 | user = current->user; | ||
93 | else | ||
94 | user = find_user(who); | ||
95 | |||
96 | if (!user) | ||
97 | break; | ||
98 | |||
99 | do_each_thread(g, p) { | ||
100 | if (p->uid != who) | ||
101 | continue; | ||
102 | ret = set_task_ioprio(p, ioprio); | ||
103 | if (ret) | ||
104 | break; | ||
105 | } while_each_thread(g, p); | ||
106 | |||
107 | if (who) | ||
108 | free_uid(user); | ||
109 | break; | ||
110 | default: | ||
111 | ret = -EINVAL; | ||
112 | } | ||
113 | |||
114 | read_unlock_irq(&tasklist_lock); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | asmlinkage int sys_ioprio_get(int which, int who) | ||
119 | { | ||
120 | struct task_struct *g, *p; | ||
121 | struct user_struct *user; | ||
122 | int ret = -ESRCH; | ||
123 | |||
124 | read_lock_irq(&tasklist_lock); | ||
125 | switch (which) { | ||
126 | case IOPRIO_WHO_PROCESS: | ||
127 | if (!who) | ||
128 | p = current; | ||
129 | else | ||
130 | p = find_task_by_pid(who); | ||
131 | if (p) | ||
132 | ret = p->ioprio; | ||
133 | break; | ||
134 | case IOPRIO_WHO_PGRP: | ||
135 | if (!who) | ||
136 | who = process_group(current); | ||
137 | do_each_task_pid(who, PIDTYPE_PGID, p) { | ||
138 | if (ret == -ESRCH) | ||
139 | ret = p->ioprio; | ||
140 | else | ||
141 | ret = ioprio_best(ret, p->ioprio); | ||
142 | } while_each_task_pid(who, PIDTYPE_PGID, p); | ||
143 | break; | ||
144 | case IOPRIO_WHO_USER: | ||
145 | if (!who) | ||
146 | user = current->user; | ||
147 | else | ||
148 | user = find_user(who); | ||
149 | |||
150 | if (!user) | ||
151 | break; | ||
152 | |||
153 | do_each_thread(g, p) { | ||
154 | if (p->uid != user->uid) | ||
155 | continue; | ||
156 | if (ret == -ESRCH) | ||
157 | ret = p->ioprio; | ||
158 | else | ||
159 | ret = ioprio_best(ret, p->ioprio); | ||
160 | } while_each_thread(g, p); | ||
161 | |||
162 | if (who) | ||
163 | free_uid(user); | ||
164 | break; | ||
165 | default: | ||
166 | ret = -EINVAL; | ||
167 | } | ||
168 | |||
169 | read_unlock_irq(&tasklist_lock); | ||
170 | return ret; | ||
171 | } | ||
172 | |||
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 7b87707acc36..d1bcf0da6728 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
@@ -645,18 +645,22 @@ struct buffer_chunk { | |||
645 | 645 | ||
646 | static void write_chunk(struct buffer_chunk *chunk) { | 646 | static void write_chunk(struct buffer_chunk *chunk) { |
647 | int i; | 647 | int i; |
648 | get_fs_excl(); | ||
648 | for (i = 0; i < chunk->nr ; i++) { | 649 | for (i = 0; i < chunk->nr ; i++) { |
649 | submit_logged_buffer(chunk->bh[i]) ; | 650 | submit_logged_buffer(chunk->bh[i]) ; |
650 | } | 651 | } |
651 | chunk->nr = 0; | 652 | chunk->nr = 0; |
653 | put_fs_excl(); | ||
652 | } | 654 | } |
653 | 655 | ||
654 | static void write_ordered_chunk(struct buffer_chunk *chunk) { | 656 | static void write_ordered_chunk(struct buffer_chunk *chunk) { |
655 | int i; | 657 | int i; |
658 | get_fs_excl(); | ||
656 | for (i = 0; i < chunk->nr ; i++) { | 659 | for (i = 0; i < chunk->nr ; i++) { |
657 | submit_ordered_buffer(chunk->bh[i]) ; | 660 | submit_ordered_buffer(chunk->bh[i]) ; |
658 | } | 661 | } |
659 | chunk->nr = 0; | 662 | chunk->nr = 0; |
663 | put_fs_excl(); | ||
660 | } | 664 | } |
661 | 665 | ||
662 | static int add_to_chunk(struct buffer_chunk *chunk, struct buffer_head *bh, | 666 | static int add_to_chunk(struct buffer_chunk *chunk, struct buffer_head *bh, |
@@ -918,6 +922,8 @@ static int flush_commit_list(struct super_block *s, struct reiserfs_journal_list | |||
918 | return 0 ; | 922 | return 0 ; |
919 | } | 923 | } |
920 | 924 | ||
925 | get_fs_excl(); | ||
926 | |||
921 | /* before we can put our commit blocks on disk, we have to make sure everyone older than | 927 | /* before we can put our commit blocks on disk, we have to make sure everyone older than |
922 | ** us is on disk too | 928 | ** us is on disk too |
923 | */ | 929 | */ |
@@ -1055,6 +1061,7 @@ put_jl: | |||
1055 | 1061 | ||
1056 | if (retval) | 1062 | if (retval) |
1057 | reiserfs_abort (s, retval, "Journal write error in %s", __FUNCTION__); | 1063 | reiserfs_abort (s, retval, "Journal write error in %s", __FUNCTION__); |
1064 | put_fs_excl(); | ||
1058 | return retval; | 1065 | return retval; |
1059 | } | 1066 | } |
1060 | 1067 | ||
@@ -1251,6 +1258,8 @@ static int flush_journal_list(struct super_block *s, | |||
1251 | return 0 ; | 1258 | return 0 ; |
1252 | } | 1259 | } |
1253 | 1260 | ||
1261 | get_fs_excl(); | ||
1262 | |||
1254 | /* if all the work is already done, get out of here */ | 1263 | /* if all the work is already done, get out of here */ |
1255 | if (atomic_read(&(jl->j_nonzerolen)) <= 0 && | 1264 | if (atomic_read(&(jl->j_nonzerolen)) <= 0 && |
1256 | atomic_read(&(jl->j_commit_left)) <= 0) { | 1265 | atomic_read(&(jl->j_commit_left)) <= 0) { |
@@ -1450,6 +1459,7 @@ flush_older_and_return: | |||
1450 | put_journal_list(s, jl); | 1459 | put_journal_list(s, jl); |
1451 | if (flushall) | 1460 | if (flushall) |
1452 | up(&journal->j_flush_sem); | 1461 | up(&journal->j_flush_sem); |
1462 | put_fs_excl(); | ||
1453 | return err ; | 1463 | return err ; |
1454 | } | 1464 | } |
1455 | 1465 | ||
@@ -2719,6 +2729,7 @@ relock: | |||
2719 | th->t_trans_id = journal->j_trans_id ; | 2729 | th->t_trans_id = journal->j_trans_id ; |
2720 | unlock_journal(p_s_sb) ; | 2730 | unlock_journal(p_s_sb) ; |
2721 | INIT_LIST_HEAD (&th->t_list); | 2731 | INIT_LIST_HEAD (&th->t_list); |
2732 | get_fs_excl(); | ||
2722 | return 0 ; | 2733 | return 0 ; |
2723 | 2734 | ||
2724 | out_fail: | 2735 | out_fail: |
@@ -3526,6 +3537,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, struct super_b | |||
3526 | BUG_ON (th->t_refcount > 1); | 3537 | BUG_ON (th->t_refcount > 1); |
3527 | BUG_ON (!th->t_trans_id); | 3538 | BUG_ON (!th->t_trans_id); |
3528 | 3539 | ||
3540 | put_fs_excl(); | ||
3529 | current->journal_info = th->t_handle_save; | 3541 | current->journal_info = th->t_handle_save; |
3530 | reiserfs_check_lock_depth(p_s_sb, "journal end"); | 3542 | reiserfs_check_lock_depth(p_s_sb, "journal end"); |
3531 | if (journal->j_len == 0) { | 3543 | if (journal->j_len == 0) { |
diff --git a/include/asm-arm/arch-ixp4xx/debug-macro.S b/include/asm-arm/arch-ixp4xx/debug-macro.S index 45a6c6cc29d5..2e23651e217f 100644 --- a/include/asm-arm/arch-ixp4xx/debug-macro.S +++ b/include/asm-arm/arch-ixp4xx/debug-macro.S | |||
@@ -14,8 +14,8 @@ | |||
14 | mrc p15, 0, \rx, c1, c0 | 14 | mrc p15, 0, \rx, c1, c0 |
15 | tst \rx, #1 @ MMU enabled? | 15 | tst \rx, #1 @ MMU enabled? |
16 | moveq \rx, #0xc8000000 | 16 | moveq \rx, #0xc8000000 |
17 | orrne \rx, \rx, #0x00b00000 | ||
18 | movne \rx, #0xff000000 | 17 | movne \rx, #0xff000000 |
18 | orrne \rx, \rx, #0x00b00000 | ||
19 | add \rx,\rx,#3 @ Uart regs are at off set of 3 if | 19 | add \rx,\rx,#3 @ Uart regs are at off set of 3 if |
20 | @ byte writes used - Big Endian. | 20 | @ byte writes used - Big Endian. |
21 | .endm | 21 | .endm |
diff --git a/include/asm-arm/arch-omap/usb.h b/include/asm-arm/arch-omap/usb.h index 1438c6cef0ca..054fb9a8e0c6 100644 --- a/include/asm-arm/arch-omap/usb.h +++ b/include/asm-arm/arch-omap/usb.h | |||
@@ -47,6 +47,15 @@ | |||
47 | # define HMC_TLLATTACH (1 << 6) | 47 | # define HMC_TLLATTACH (1 << 6) |
48 | # define OTG_HMC(w) (((w)>>0)&0x3f) | 48 | # define OTG_HMC(w) (((w)>>0)&0x3f) |
49 | #define OTG_CTRL_REG OTG_REG32(0x0c) | 49 | #define OTG_CTRL_REG OTG_REG32(0x0c) |
50 | # define OTG_USB2_EN (1 << 29) | ||
51 | # define OTG_USB2_DP (1 << 28) | ||
52 | # define OTG_USB2_DM (1 << 27) | ||
53 | # define OTG_USB1_EN (1 << 26) | ||
54 | # define OTG_USB1_DP (1 << 25) | ||
55 | # define OTG_USB1_DM (1 << 24) | ||
56 | # define OTG_USB0_EN (1 << 23) | ||
57 | # define OTG_USB0_DP (1 << 22) | ||
58 | # define OTG_USB0_DM (1 << 21) | ||
50 | # define OTG_ASESSVLD (1 << 20) | 59 | # define OTG_ASESSVLD (1 << 20) |
51 | # define OTG_BSESSEND (1 << 19) | 60 | # define OTG_BSESSEND (1 << 19) |
52 | # define OTG_BSESSVLD (1 << 18) | 61 | # define OTG_BSESSVLD (1 << 18) |
diff --git a/include/asm-arm/ide.h b/include/asm-arm/ide.h index 2114acb3d237..4f68c8a5a199 100644 --- a/include/asm-arm/ide.h +++ b/include/asm-arm/ide.h | |||
@@ -5,7 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * This file contains the i386 architecture specific IDE code. | 8 | * This file contains the ARM architecture specific IDE code. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #ifndef __ASMARM_IDE_H | 11 | #ifndef __ASMARM_IDE_H |
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index cc4b5f5dbfcf..cfa71a0dffb6 100644 --- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h | |||
@@ -82,7 +82,7 @@ extern void __readwrite_bug(const char *fn); | |||
82 | * only. Their primary purpose is to access PCI and ISA peripherals. | 82 | * only. Their primary purpose is to access PCI and ISA peripherals. |
83 | * | 83 | * |
84 | * Note that for a big endian machine, this implies that the following | 84 | * Note that for a big endian machine, this implies that the following |
85 | * big endian mode connectivity is in place, as described by numerious | 85 | * big endian mode connectivity is in place, as described by numerous |
86 | * ARM documents: | 86 | * ARM documents: |
87 | * | 87 | * |
88 | * PCI: D0-D7 D8-D15 D16-D23 D24-D31 | 88 | * PCI: D0-D7 D8-D15 D16-D23 D24-D31 |
diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h index 047980ad18d1..2cf279a44017 100644 --- a/include/asm-arm/mach/time.h +++ b/include/asm-arm/mach/time.h | |||
@@ -60,6 +60,8 @@ struct dyn_tick_timer { | |||
60 | }; | 60 | }; |
61 | 61 | ||
62 | void timer_dyn_reprogram(void); | 62 | void timer_dyn_reprogram(void); |
63 | #else | ||
64 | #define timer_dyn_reprogram() do { } while (0) | ||
63 | #endif | 65 | #endif |
64 | 66 | ||
65 | extern struct sys_timer *system_timer; | 67 | extern struct sys_timer *system_timer; |
diff --git a/include/asm-i386/tlbflush.h b/include/asm-i386/tlbflush.h index f22fab0cea26..ab216e1370ef 100644 --- a/include/asm-i386/tlbflush.h +++ b/include/asm-i386/tlbflush.h | |||
@@ -22,16 +22,18 @@ | |||
22 | */ | 22 | */ |
23 | #define __flush_tlb_global() \ | 23 | #define __flush_tlb_global() \ |
24 | do { \ | 24 | do { \ |
25 | unsigned int tmpreg; \ | 25 | unsigned int tmpreg, cr4, cr4_orig; \ |
26 | \ | 26 | \ |
27 | __asm__ __volatile__( \ | 27 | __asm__ __volatile__( \ |
28 | "movl %1, %%cr4; # turn off PGE \n" \ | 28 | "movl %%cr4, %2; # turn off PGE \n" \ |
29 | "movl %2, %1; \n" \ | ||
30 | "andl %3, %1; \n" \ | ||
31 | "movl %1, %%cr4; \n" \ | ||
29 | "movl %%cr3, %0; \n" \ | 32 | "movl %%cr3, %0; \n" \ |
30 | "movl %0, %%cr3; # flush TLB \n" \ | 33 | "movl %0, %%cr3; # flush TLB \n" \ |
31 | "movl %2, %%cr4; # turn PGE back on \n" \ | 34 | "movl %2, %%cr4; # turn PGE back on \n" \ |
32 | : "=&r" (tmpreg) \ | 35 | : "=&r" (tmpreg), "=&r" (cr4), "=&r" (cr4_orig) \ |
33 | : "r" (mmu_cr4_features & ~X86_CR4_PGE), \ | 36 | : "i" (~X86_CR4_PGE) \ |
34 | "r" (mmu_cr4_features) \ | ||
35 | : "memory"); \ | 37 | : "memory"); \ |
36 | } while (0) | 38 | } while (0) |
37 | 39 | ||
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 176413fb9ae3..e25e4c71a879 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h | |||
@@ -294,8 +294,10 @@ | |||
294 | #define __NR_add_key 286 | 294 | #define __NR_add_key 286 |
295 | #define __NR_request_key 287 | 295 | #define __NR_request_key 287 |
296 | #define __NR_keyctl 288 | 296 | #define __NR_keyctl 288 |
297 | #define __NR_ioprio_set 289 | ||
298 | #define __NR_ioprio_get 290 | ||
297 | 299 | ||
298 | #define NR_syscalls 289 | 300 | #define NR_syscalls 291 |
299 | 301 | ||
300 | /* | 302 | /* |
301 | * user-visible error numbers are in the range -1 - -128: see | 303 | * user-visible error numbers are in the range -1 - -128: see |
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h index 7b700035e36d..bf36a32e37e4 100644 --- a/include/asm-ia64/kprobes.h +++ b/include/asm-ia64/kprobes.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/ptrace.h> | 28 | #include <linux/ptrace.h> |
29 | #include <asm/break.h> | 29 | #include <asm/break.h> |
30 | 30 | ||
31 | #define MAX_INSN_SIZE 16 | ||
31 | #define BREAK_INST (long)(__IA64_BREAK_KPROBE << 6) | 32 | #define BREAK_INST (long)(__IA64_BREAK_KPROBE << 6) |
32 | 33 | ||
33 | typedef union cmp_inst { | 34 | typedef union cmp_inst { |
@@ -63,6 +64,8 @@ typedef struct _bundle { | |||
63 | 64 | ||
64 | #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry | 65 | #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry |
65 | 66 | ||
67 | #define ARCH_SUPPORTS_KRETPROBES | ||
68 | |||
66 | #define SLOT0_OPCODE_SHIFT (37) | 69 | #define SLOT0_OPCODE_SHIFT (37) |
67 | #define SLOT1_p1_OPCODE_SHIFT (37 - (64-46)) | 70 | #define SLOT1_p1_OPCODE_SHIFT (37 - (64-46)) |
68 | #define SLOT2_OPCODE_SHIFT (37) | 71 | #define SLOT2_OPCODE_SHIFT (37) |
@@ -94,11 +97,6 @@ struct arch_specific_insn { | |||
94 | }; | 97 | }; |
95 | 98 | ||
96 | /* ia64 does not need this */ | 99 | /* ia64 does not need this */ |
97 | static inline void jprobe_return(void) | ||
98 | { | ||
99 | } | ||
100 | |||
101 | /* ia64 does not need this */ | ||
102 | static inline void arch_copy_kprobe(struct kprobe *p) | 100 | static inline void arch_copy_kprobe(struct kprobe *p) |
103 | { | 101 | { |
104 | } | 102 | } |
@@ -106,6 +104,12 @@ static inline void arch_copy_kprobe(struct kprobe *p) | |||
106 | #ifdef CONFIG_KPROBES | 104 | #ifdef CONFIG_KPROBES |
107 | extern int kprobe_exceptions_notify(struct notifier_block *self, | 105 | extern int kprobe_exceptions_notify(struct notifier_block *self, |
108 | unsigned long val, void *data); | 106 | unsigned long val, void *data); |
107 | |||
108 | /* ia64 does not need this */ | ||
109 | static inline void jprobe_return(void) | ||
110 | { | ||
111 | } | ||
112 | |||
109 | #else /* !CONFIG_KPROBES */ | 113 | #else /* !CONFIG_KPROBES */ |
110 | static inline int kprobe_exceptions_notify(struct notifier_block *self, | 114 | static inline int kprobe_exceptions_notify(struct notifier_block *self, |
111 | unsigned long val, void *data) | 115 | unsigned long val, void *data) |
diff --git a/include/asm-ia64/sections.h b/include/asm-ia64/sections.h index 8e3dbde1b429..e9eb7f62d32b 100644 --- a/include/asm-ia64/sections.h +++ b/include/asm-ia64/sections.h | |||
@@ -17,6 +17,7 @@ extern char __start_gate_vtop_patchlist[], __end_gate_vtop_patchlist[]; | |||
17 | extern char __start_gate_fsyscall_patchlist[], __end_gate_fsyscall_patchlist[]; | 17 | extern char __start_gate_fsyscall_patchlist[], __end_gate_fsyscall_patchlist[]; |
18 | extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_bubble_down_patchlist[]; | 18 | extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_bubble_down_patchlist[]; |
19 | extern char __start_unwind[], __end_unwind[]; | 19 | extern char __start_unwind[], __end_unwind[]; |
20 | extern char __start_ivt_text[], __end_ivt_text[]; | ||
20 | 21 | ||
21 | #endif /* _ASM_IA64_SECTIONS_H */ | 22 | #endif /* _ASM_IA64_SECTIONS_H */ |
22 | 23 | ||
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index f7f43ec2483a..517f1649ee64 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h | |||
@@ -263,6 +263,8 @@ | |||
263 | #define __NR_add_key 1271 | 263 | #define __NR_add_key 1271 |
264 | #define __NR_request_key 1272 | 264 | #define __NR_request_key 1272 |
265 | #define __NR_keyctl 1273 | 265 | #define __NR_keyctl 1273 |
266 | #define __NR_ioprio_set 1274 | ||
267 | #define __NR_ioprio_get 1275 | ||
266 | #define __NR_set_zone_reclaim 1276 | 268 | #define __NR_set_zone_reclaim 1276 |
267 | 269 | ||
268 | #ifdef __KERNEL__ | 270 | #ifdef __KERNEL__ |
diff --git a/include/asm-ppc/open_pic.h b/include/asm-ppc/open_pic.h index dbe853319741..7848aa610c05 100644 --- a/include/asm-ppc/open_pic.h +++ b/include/asm-ppc/open_pic.h | |||
@@ -25,6 +25,11 @@ | |||
25 | #define OPENPIC_VEC_IPI 118 /* and up */ | 25 | #define OPENPIC_VEC_IPI 118 /* and up */ |
26 | #define OPENPIC_VEC_SPURIOUS 255 | 26 | #define OPENPIC_VEC_SPURIOUS 255 |
27 | 27 | ||
28 | /* Priorities */ | ||
29 | #define OPENPIC_PRIORITY_IPI_BASE 10 | ||
30 | #define OPENPIC_PRIORITY_DEFAULT 4 | ||
31 | #define OPENPIC_PRIORITY_NMI 9 | ||
32 | |||
28 | /* OpenPIC IRQ controller structure */ | 33 | /* OpenPIC IRQ controller structure */ |
29 | extern struct hw_interrupt_type open_pic; | 34 | extern struct hw_interrupt_type open_pic; |
30 | 35 | ||
@@ -42,6 +47,7 @@ extern int epic_serial_mode; | |||
42 | extern void openpic_set_sources(int first_irq, int num_irqs, void __iomem *isr); | 47 | extern void openpic_set_sources(int first_irq, int num_irqs, void __iomem *isr); |
43 | extern void openpic_init(int linux_irq_offset); | 48 | extern void openpic_init(int linux_irq_offset); |
44 | extern void openpic_init_nmi_irq(u_int irq); | 49 | extern void openpic_init_nmi_irq(u_int irq); |
50 | extern void openpic_set_irq_priority(u_int irq, u_int pri); | ||
45 | extern void openpic_hookup_cascade(u_int irq, char *name, | 51 | extern void openpic_hookup_cascade(u_int irq, char *name, |
46 | int (*cascade_fn)(struct pt_regs *)); | 52 | int (*cascade_fn)(struct pt_regs *)); |
47 | extern u_int openpic_irq(void); | 53 | extern u_int openpic_irq(void); |
diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h index cc51e5c9acc2..e8b79220b29c 100644 --- a/include/asm-ppc/unistd.h +++ b/include/asm-ppc/unistd.h | |||
@@ -277,8 +277,10 @@ | |||
277 | #define __NR_request_key 270 | 277 | #define __NR_request_key 270 |
278 | #define __NR_keyctl 271 | 278 | #define __NR_keyctl 271 |
279 | #define __NR_waitid 272 | 279 | #define __NR_waitid 272 |
280 | #define __NR_ioprio_set 273 | ||
281 | #define __NR_ioprio_get 274 | ||
280 | 282 | ||
281 | #define __NR_syscalls 273 | 283 | #define __NR_syscalls 275 |
282 | 284 | ||
283 | #define __NR(n) #n | 285 | #define __NR(n) #n |
284 | 286 | ||
diff --git a/include/asm-ppc64/kprobes.h b/include/asm-ppc64/kprobes.h index 19b468bed059..0802919c3235 100644 --- a/include/asm-ppc64/kprobes.h +++ b/include/asm-ppc64/kprobes.h | |||
@@ -42,10 +42,13 @@ typedef unsigned int kprobe_opcode_t; | |||
42 | 42 | ||
43 | #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)((func_descr_t *)pentry) | 43 | #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)((func_descr_t *)pentry) |
44 | 44 | ||
45 | #define ARCH_SUPPORTS_KRETPROBES | ||
46 | void kretprobe_trampoline(void); | ||
47 | |||
45 | /* Architecture specific copy of original instruction */ | 48 | /* Architecture specific copy of original instruction */ |
46 | struct arch_specific_insn { | 49 | struct arch_specific_insn { |
47 | /* copy of original instruction */ | 50 | /* copy of original instruction */ |
48 | kprobe_opcode_t insn[MAX_INSN_SIZE]; | 51 | kprobe_opcode_t *insn; |
49 | }; | 52 | }; |
50 | 53 | ||
51 | #ifdef CONFIG_KPROBES | 54 | #ifdef CONFIG_KPROBES |
diff --git a/include/asm-x86_64/tlbflush.h b/include/asm-x86_64/tlbflush.h index 2e811ac262af..061742382520 100644 --- a/include/asm-x86_64/tlbflush.h +++ b/include/asm-x86_64/tlbflush.h | |||
@@ -22,16 +22,18 @@ | |||
22 | */ | 22 | */ |
23 | #define __flush_tlb_global() \ | 23 | #define __flush_tlb_global() \ |
24 | do { \ | 24 | do { \ |
25 | unsigned long tmpreg; \ | 25 | unsigned long tmpreg, cr4, cr4_orig; \ |
26 | \ | 26 | \ |
27 | __asm__ __volatile__( \ | 27 | __asm__ __volatile__( \ |
28 | "movq %1, %%cr4; # turn off PGE \n" \ | 28 | "movq %%cr4, %2; # turn off PGE \n" \ |
29 | "movq %2, %1; \n" \ | ||
30 | "andq %3, %1; \n" \ | ||
31 | "movq %1, %%cr4; \n" \ | ||
29 | "movq %%cr3, %0; # flush TLB \n" \ | 32 | "movq %%cr3, %0; # flush TLB \n" \ |
30 | "movq %0, %%cr3; \n" \ | 33 | "movq %0, %%cr3; \n" \ |
31 | "movq %2, %%cr4; # turn PGE back on \n" \ | 34 | "movq %2, %%cr4; # turn PGE back on \n" \ |
32 | : "=&r" (tmpreg) \ | 35 | : "=&r" (tmpreg), "=&r" (cr4), "=&r" (cr4_orig) \ |
33 | : "r" (mmu_cr4_features & ~X86_CR4_PGE), \ | 36 | : "i" (~X86_CR4_PGE) \ |
34 | "r" (mmu_cr4_features) \ | ||
35 | : "memory"); \ | 37 | : "memory"); \ |
36 | } while (0) | 38 | } while (0) |
37 | 39 | ||
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index d767adcbf0ff..6560439a83e4 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h | |||
@@ -561,8 +561,12 @@ __SYSCALL(__NR_add_key, sys_add_key) | |||
561 | __SYSCALL(__NR_request_key, sys_request_key) | 561 | __SYSCALL(__NR_request_key, sys_request_key) |
562 | #define __NR_keyctl 250 | 562 | #define __NR_keyctl 250 |
563 | __SYSCALL(__NR_keyctl, sys_keyctl) | 563 | __SYSCALL(__NR_keyctl, sys_keyctl) |
564 | #define __NR_ioprio_set 251 | ||
565 | __SYSCALL(__NR_ioprio_set, sys_ioprio_set) | ||
566 | #define __NR_ioprio_get 252 | ||
567 | __SYSCALL(__NR_ioprio_get, sys_ioprio_get) | ||
564 | 568 | ||
565 | #define __NR_syscall_max __NR_keyctl | 569 | #define __NR_syscall_max __NR_ioprio_get |
566 | #ifndef __NO_STUBS | 570 | #ifndef __NO_STUBS |
567 | 571 | ||
568 | /* user-visible error numbers are in the range -1 - -4095 */ | 572 | /* user-visible error numbers are in the range -1 - -4095 */ |
diff --git a/include/linux/bio.h b/include/linux/bio.h index 038022763f09..36ef29fa0d8b 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/highmem.h> | 23 | #include <linux/highmem.h> |
24 | #include <linux/mempool.h> | 24 | #include <linux/mempool.h> |
25 | #include <linux/ioprio.h> | ||
25 | 26 | ||
26 | /* Platforms may set this to teach the BIO layer about IOMMU hardware. */ | 27 | /* Platforms may set this to teach the BIO layer about IOMMU hardware. */ |
27 | #include <asm/io.h> | 28 | #include <asm/io.h> |
@@ -150,6 +151,19 @@ struct bio { | |||
150 | #define BIO_RW_SYNC 4 | 151 | #define BIO_RW_SYNC 4 |
151 | 152 | ||
152 | /* | 153 | /* |
154 | * upper 16 bits of bi_rw define the io priority of this bio | ||
155 | */ | ||
156 | #define BIO_PRIO_SHIFT (8 * sizeof(unsigned long) - IOPRIO_BITS) | ||
157 | #define bio_prio(bio) ((bio)->bi_rw >> BIO_PRIO_SHIFT) | ||
158 | #define bio_prio_valid(bio) ioprio_valid(bio_prio(bio)) | ||
159 | |||
160 | #define bio_set_prio(bio, prio) do { \ | ||
161 | WARN_ON(prio >= (1 << IOPRIO_BITS)); \ | ||
162 | (bio)->bi_rw &= ((1UL << BIO_PRIO_SHIFT) - 1); \ | ||
163 | (bio)->bi_rw |= ((unsigned long) (prio) << BIO_PRIO_SHIFT); \ | ||
164 | } while (0) | ||
165 | |||
166 | /* | ||
153 | * various member access, note that bio_data should of course not be used | 167 | * various member access, note that bio_data should of course not be used |
154 | * on highmem page vectors | 168 | * on highmem page vectors |
155 | */ | 169 | */ |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index b54a0348a890..21a8674cd149 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -54,16 +54,23 @@ struct as_io_context { | |||
54 | 54 | ||
55 | struct cfq_queue; | 55 | struct cfq_queue; |
56 | struct cfq_io_context { | 56 | struct cfq_io_context { |
57 | void (*dtor)(struct cfq_io_context *); | ||
58 | void (*exit)(struct cfq_io_context *); | ||
59 | |||
60 | struct io_context *ioc; | ||
61 | |||
62 | /* | 57 | /* |
63 | * circular list of cfq_io_contexts belonging to a process io context | 58 | * circular list of cfq_io_contexts belonging to a process io context |
64 | */ | 59 | */ |
65 | struct list_head list; | 60 | struct list_head list; |
66 | struct cfq_queue *cfqq; | 61 | struct cfq_queue *cfqq; |
62 | void *key; | ||
63 | |||
64 | struct io_context *ioc; | ||
65 | |||
66 | unsigned long last_end_request; | ||
67 | unsigned long last_queue; | ||
68 | unsigned long ttime_total; | ||
69 | unsigned long ttime_samples; | ||
70 | unsigned long ttime_mean; | ||
71 | |||
72 | void (*dtor)(struct cfq_io_context *); | ||
73 | void (*exit)(struct cfq_io_context *); | ||
67 | }; | 74 | }; |
68 | 75 | ||
69 | /* | 76 | /* |
@@ -73,7 +80,9 @@ struct cfq_io_context { | |||
73 | */ | 80 | */ |
74 | struct io_context { | 81 | struct io_context { |
75 | atomic_t refcount; | 82 | atomic_t refcount; |
76 | pid_t pid; | 83 | struct task_struct *task; |
84 | |||
85 | int (*set_ioprio)(struct io_context *, unsigned int); | ||
77 | 86 | ||
78 | /* | 87 | /* |
79 | * For request batching | 88 | * For request batching |
@@ -81,8 +90,6 @@ struct io_context { | |||
81 | unsigned long last_waited; /* Time last woken after wait for request */ | 90 | unsigned long last_waited; /* Time last woken after wait for request */ |
82 | int nr_batch_requests; /* Number of requests left in the batch */ | 91 | int nr_batch_requests; /* Number of requests left in the batch */ |
83 | 92 | ||
84 | spinlock_t lock; | ||
85 | |||
86 | struct as_io_context *aic; | 93 | struct as_io_context *aic; |
87 | struct cfq_io_context *cic; | 94 | struct cfq_io_context *cic; |
88 | }; | 95 | }; |
@@ -134,6 +141,8 @@ struct request { | |||
134 | 141 | ||
135 | void *elevator_private; | 142 | void *elevator_private; |
136 | 143 | ||
144 | unsigned short ioprio; | ||
145 | |||
137 | int rq_status; /* should split this into a few status bits */ | 146 | int rq_status; /* should split this into a few status bits */ |
138 | struct gendisk *rq_disk; | 147 | struct gendisk *rq_disk; |
139 | int errors; | 148 | int errors; |
diff --git a/include/linux/cciss_ioctl.h b/include/linux/cciss_ioctl.h index ee0c6e8995da..424d5e622b43 100644 --- a/include/linux/cciss_ioctl.h +++ b/include/linux/cciss_ioctl.h | |||
@@ -10,6 +10,7 @@ | |||
10 | typedef struct _cciss_pci_info_struct | 10 | typedef struct _cciss_pci_info_struct |
11 | { | 11 | { |
12 | unsigned char bus; | 12 | unsigned char bus; |
13 | unsigned short domain; | ||
13 | unsigned char dev_fn; | 14 | unsigned char dev_fn; |
14 | __u32 board_id; | 15 | __u32 board_id; |
15 | } cciss_pci_info_struct; | 16 | } cciss_pci_info_struct; |
diff --git a/include/linux/elevator.h b/include/linux/elevator.h index ee54f81faad5..ea6bbc2d7407 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h | |||
@@ -16,9 +16,9 @@ typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *); | |||
16 | typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *); | 16 | typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *); |
17 | typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *); | 17 | typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *); |
18 | typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *); | 18 | typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *); |
19 | typedef int (elevator_may_queue_fn) (request_queue_t *, int); | 19 | typedef int (elevator_may_queue_fn) (request_queue_t *, int, struct bio *); |
20 | 20 | ||
21 | typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, int); | 21 | typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, int); |
22 | typedef void (elevator_put_req_fn) (request_queue_t *, struct request *); | 22 | typedef void (elevator_put_req_fn) (request_queue_t *, struct request *); |
23 | typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *); | 23 | typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *); |
24 | 24 | ||
@@ -96,9 +96,9 @@ extern struct request *elv_former_request(request_queue_t *, struct request *); | |||
96 | extern struct request *elv_latter_request(request_queue_t *, struct request *); | 96 | extern struct request *elv_latter_request(request_queue_t *, struct request *); |
97 | extern int elv_register_queue(request_queue_t *q); | 97 | extern int elv_register_queue(request_queue_t *q); |
98 | extern void elv_unregister_queue(request_queue_t *q); | 98 | extern void elv_unregister_queue(request_queue_t *q); |
99 | extern int elv_may_queue(request_queue_t *, int); | 99 | extern int elv_may_queue(request_queue_t *, int, struct bio *); |
100 | extern void elv_completed_request(request_queue_t *, struct request *); | 100 | extern void elv_completed_request(request_queue_t *, struct request *); |
101 | extern int elv_set_request(request_queue_t *, struct request *, int); | 101 | extern int elv_set_request(request_queue_t *, struct request *, struct bio *, int); |
102 | extern void elv_put_request(request_queue_t *, struct request *); | 102 | extern void elv_put_request(request_queue_t *, struct request *); |
103 | 103 | ||
104 | /* | 104 | /* |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 3ae8e37bdfc8..047bde30836a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -213,6 +213,7 @@ extern int dir_notify_enable; | |||
213 | #include <linux/radix-tree.h> | 213 | #include <linux/radix-tree.h> |
214 | #include <linux/prio_tree.h> | 214 | #include <linux/prio_tree.h> |
215 | #include <linux/init.h> | 215 | #include <linux/init.h> |
216 | #include <linux/sched.h> | ||
216 | 217 | ||
217 | #include <asm/atomic.h> | 218 | #include <asm/atomic.h> |
218 | #include <asm/semaphore.h> | 219 | #include <asm/semaphore.h> |
@@ -822,16 +823,34 @@ enum { | |||
822 | #define vfs_check_frozen(sb, level) \ | 823 | #define vfs_check_frozen(sb, level) \ |
823 | wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) | 824 | wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) |
824 | 825 | ||
826 | static inline void get_fs_excl(void) | ||
827 | { | ||
828 | atomic_inc(¤t->fs_excl); | ||
829 | } | ||
830 | |||
831 | static inline void put_fs_excl(void) | ||
832 | { | ||
833 | atomic_dec(¤t->fs_excl); | ||
834 | } | ||
835 | |||
836 | static inline int has_fs_excl(void) | ||
837 | { | ||
838 | return atomic_read(¤t->fs_excl); | ||
839 | } | ||
840 | |||
841 | |||
825 | /* | 842 | /* |
826 | * Superblock locking. | 843 | * Superblock locking. |
827 | */ | 844 | */ |
828 | static inline void lock_super(struct super_block * sb) | 845 | static inline void lock_super(struct super_block * sb) |
829 | { | 846 | { |
847 | get_fs_excl(); | ||
830 | down(&sb->s_lock); | 848 | down(&sb->s_lock); |
831 | } | 849 | } |
832 | 850 | ||
833 | static inline void unlock_super(struct super_block * sb) | 851 | static inline void unlock_super(struct super_block * sb) |
834 | { | 852 | { |
853 | put_fs_excl(); | ||
835 | up(&sb->s_lock); | 854 | up(&sb->s_lock); |
836 | } | 855 | } |
837 | 856 | ||
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 03206a425d7a..c727c195a91a 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -81,6 +81,7 @@ extern struct group_info init_groups; | |||
81 | .mm = NULL, \ | 81 | .mm = NULL, \ |
82 | .active_mm = &init_mm, \ | 82 | .active_mm = &init_mm, \ |
83 | .run_list = LIST_HEAD_INIT(tsk.run_list), \ | 83 | .run_list = LIST_HEAD_INIT(tsk.run_list), \ |
84 | .ioprio = 0, \ | ||
84 | .time_slice = HZ, \ | 85 | .time_slice = HZ, \ |
85 | .tasks = LIST_HEAD_INIT(tsk.tasks), \ | 86 | .tasks = LIST_HEAD_INIT(tsk.tasks), \ |
86 | .ptrace_children= LIST_HEAD_INIT(tsk.ptrace_children), \ | 87 | .ptrace_children= LIST_HEAD_INIT(tsk.ptrace_children), \ |
@@ -110,6 +111,7 @@ extern struct group_info init_groups; | |||
110 | .proc_lock = SPIN_LOCK_UNLOCKED, \ | 111 | .proc_lock = SPIN_LOCK_UNLOCKED, \ |
111 | .journal_info = NULL, \ | 112 | .journal_info = NULL, \ |
112 | .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ | 113 | .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ |
114 | .fs_excl = ATOMIC_INIT(0), \ | ||
113 | } | 115 | } |
114 | 116 | ||
115 | 117 | ||
diff --git a/include/linux/input.h b/include/linux/input.h index 9d9598ed760d..b9cc0ac71f44 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
@@ -859,6 +859,10 @@ struct input_dev { | |||
859 | int (*erase_effect)(struct input_dev *dev, int effect_id); | 859 | int (*erase_effect)(struct input_dev *dev, int effect_id); |
860 | 860 | ||
861 | struct input_handle *grab; | 861 | struct input_handle *grab; |
862 | |||
863 | struct semaphore sem; /* serializes open and close operations */ | ||
864 | unsigned int users; | ||
865 | |||
862 | struct device *dev; | 866 | struct device *dev; |
863 | 867 | ||
864 | struct list_head h_list; | 868 | struct list_head h_list; |
diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h new file mode 100644 index 000000000000..8a453a0b5e4b --- /dev/null +++ b/include/linux/ioprio.h | |||
@@ -0,0 +1,88 @@ | |||
1 | #ifndef IOPRIO_H | ||
2 | #define IOPRIO_H | ||
3 | |||
4 | #include <linux/sched.h> | ||
5 | |||
6 | /* | ||
7 | * Gives us 8 prio classes with 13-bits of data for each class | ||
8 | */ | ||
9 | #define IOPRIO_BITS (16) | ||
10 | #define IOPRIO_CLASS_SHIFT (13) | ||
11 | #define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) | ||
12 | |||
13 | #define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) | ||
14 | #define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) | ||
15 | #define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) | ||
16 | |||
17 | #define ioprio_valid(mask) (IOPRIO_PRIO_CLASS((mask)) != IOPRIO_CLASS_NONE) | ||
18 | |||
19 | /* | ||
20 | * These are the io priority groups as implemented by CFQ. RT is the realtime | ||
21 | * class, it always gets premium service. BE is the best-effort scheduling | ||
22 | * class, the default for any process. IDLE is the idle scheduling class, it | ||
23 | * is only served when no one else is using the disk. | ||
24 | */ | ||
25 | enum { | ||
26 | IOPRIO_CLASS_NONE, | ||
27 | IOPRIO_CLASS_RT, | ||
28 | IOPRIO_CLASS_BE, | ||
29 | IOPRIO_CLASS_IDLE, | ||
30 | }; | ||
31 | |||
32 | /* | ||
33 | * 8 best effort priority levels are supported | ||
34 | */ | ||
35 | #define IOPRIO_BE_NR (8) | ||
36 | |||
37 | asmlinkage int sys_ioprio_set(int, int, int); | ||
38 | asmlinkage int sys_ioprio_get(int, int); | ||
39 | |||
40 | enum { | ||
41 | IOPRIO_WHO_PROCESS = 1, | ||
42 | IOPRIO_WHO_PGRP, | ||
43 | IOPRIO_WHO_USER, | ||
44 | }; | ||
45 | |||
46 | /* | ||
47 | * if process has set io priority explicitly, use that. if not, convert | ||
48 | * the cpu scheduler nice value to an io priority | ||
49 | */ | ||
50 | #define IOPRIO_NORM (4) | ||
51 | static inline int task_ioprio(struct task_struct *task) | ||
52 | { | ||
53 | WARN_ON(!ioprio_valid(task->ioprio)); | ||
54 | return IOPRIO_PRIO_DATA(task->ioprio); | ||
55 | } | ||
56 | |||
57 | static inline int task_nice_ioprio(struct task_struct *task) | ||
58 | { | ||
59 | return (task_nice(task) + 20) / 5; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * For inheritance, return the highest of the two given priorities | ||
64 | */ | ||
65 | static inline int ioprio_best(unsigned short aprio, unsigned short bprio) | ||
66 | { | ||
67 | unsigned short aclass = IOPRIO_PRIO_CLASS(aprio); | ||
68 | unsigned short bclass = IOPRIO_PRIO_CLASS(bprio); | ||
69 | |||
70 | if (!ioprio_valid(aprio)) | ||
71 | return bprio; | ||
72 | if (!ioprio_valid(bprio)) | ||
73 | return aprio; | ||
74 | |||
75 | if (aclass == IOPRIO_CLASS_NONE) | ||
76 | aclass = IOPRIO_CLASS_BE; | ||
77 | if (bclass == IOPRIO_CLASS_NONE) | ||
78 | bclass = IOPRIO_CLASS_BE; | ||
79 | |||
80 | if (aclass == bclass) | ||
81 | return min(aprio, bprio); | ||
82 | if (aclass > bclass) | ||
83 | return bprio; | ||
84 | else | ||
85 | return aprio; | ||
86 | } | ||
87 | |||
88 | #endif | ||
diff --git a/include/linux/joystick.h b/include/linux/joystick.h index b7e0ab622cd7..06b9af77eb7f 100644 --- a/include/linux/joystick.h +++ b/include/linux/joystick.h | |||
@@ -111,18 +111,35 @@ struct js_corr { | |||
111 | #define JS_SET_ALL 8 | 111 | #define JS_SET_ALL 8 |
112 | 112 | ||
113 | struct JS_DATA_TYPE { | 113 | struct JS_DATA_TYPE { |
114 | int buttons; | 114 | __s32 buttons; |
115 | int x; | 115 | __s32 x; |
116 | int y; | 116 | __s32 y; |
117 | }; | 117 | }; |
118 | 118 | ||
119 | struct JS_DATA_SAVE_TYPE { | 119 | struct JS_DATA_SAVE_TYPE_32 { |
120 | int JS_TIMEOUT; | 120 | __s32 JS_TIMEOUT; |
121 | int BUSY; | 121 | __s32 BUSY; |
122 | long JS_EXPIRETIME; | 122 | __s32 JS_EXPIRETIME; |
123 | long JS_TIMELIMIT; | 123 | __s32 JS_TIMELIMIT; |
124 | struct JS_DATA_TYPE JS_SAVE; | 124 | struct JS_DATA_TYPE JS_SAVE; |
125 | struct JS_DATA_TYPE JS_CORR; | 125 | struct JS_DATA_TYPE JS_CORR; |
126 | }; | 126 | }; |
127 | 127 | ||
128 | struct JS_DATA_SAVE_TYPE_64 { | ||
129 | __s32 JS_TIMEOUT; | ||
130 | __s32 BUSY; | ||
131 | __s64 JS_EXPIRETIME; | ||
132 | __s64 JS_TIMELIMIT; | ||
133 | struct JS_DATA_TYPE JS_SAVE; | ||
134 | struct JS_DATA_TYPE JS_CORR; | ||
135 | }; | ||
136 | |||
137 | #if BITS_PER_LONG == 64 | ||
138 | #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64 | ||
139 | #elif BITS_PER_LONG == 32 | ||
140 | #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_32 | ||
141 | #else | ||
142 | #error Unexpected BITS_PER_LONG | ||
143 | #endif | ||
144 | |||
128 | #endif /* _LINUX_JOYSTICK_H */ | 145 | #endif /* _LINUX_JOYSTICK_H */ |
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 5e1a7b0d7b3f..b7a194c4362a 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h | |||
@@ -104,33 +104,12 @@ struct jprobe { | |||
104 | }; | 104 | }; |
105 | 105 | ||
106 | #ifdef ARCH_SUPPORTS_KRETPROBES | 106 | #ifdef ARCH_SUPPORTS_KRETPROBES |
107 | extern int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs); | ||
108 | extern void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs, | ||
109 | unsigned long flags); | ||
110 | extern struct task_struct *arch_get_kprobe_task(void *ptr); | ||
111 | extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs); | 107 | extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs); |
112 | extern void arch_kprobe_flush_task(struct task_struct *tk); | ||
113 | #else /* ARCH_SUPPORTS_KRETPROBES */ | 108 | #else /* ARCH_SUPPORTS_KRETPROBES */ |
114 | static inline void kretprobe_trampoline(void) | ||
115 | { | ||
116 | } | ||
117 | static inline int trampoline_probe_handler(struct kprobe *p, | ||
118 | struct pt_regs *regs) | ||
119 | { | ||
120 | return 0; | ||
121 | } | ||
122 | static inline void trampoline_post_handler(struct kprobe *p, | ||
123 | struct pt_regs *regs, unsigned long flags) | ||
124 | { | ||
125 | } | ||
126 | static inline void arch_prepare_kretprobe(struct kretprobe *rp, | 109 | static inline void arch_prepare_kretprobe(struct kretprobe *rp, |
127 | struct pt_regs *regs) | 110 | struct pt_regs *regs) |
128 | { | 111 | { |
129 | } | 112 | } |
130 | static inline void arch_kprobe_flush_task(struct task_struct *tk) | ||
131 | { | ||
132 | } | ||
133 | #define arch_get_kprobe_task(ptr) ((struct task_struct *)NULL) | ||
134 | #endif /* ARCH_SUPPORTS_KRETPROBES */ | 113 | #endif /* ARCH_SUPPORTS_KRETPROBES */ |
135 | /* | 114 | /* |
136 | * Function-return probe - | 115 | * Function-return probe - |
@@ -155,8 +134,8 @@ struct kretprobe_instance { | |||
155 | struct hlist_node uflist; /* either on free list or used list */ | 134 | struct hlist_node uflist; /* either on free list or used list */ |
156 | struct hlist_node hlist; | 135 | struct hlist_node hlist; |
157 | struct kretprobe *rp; | 136 | struct kretprobe *rp; |
158 | void *ret_addr; | 137 | kprobe_opcode_t *ret_addr; |
159 | void *stack_addr; | 138 | struct task_struct *task; |
160 | }; | 139 | }; |
161 | 140 | ||
162 | #ifdef CONFIG_KPROBES | 141 | #ifdef CONFIG_KPROBES |
@@ -176,7 +155,10 @@ extern void arch_copy_kprobe(struct kprobe *p); | |||
176 | extern void arch_arm_kprobe(struct kprobe *p); | 155 | extern void arch_arm_kprobe(struct kprobe *p); |
177 | extern void arch_disarm_kprobe(struct kprobe *p); | 156 | extern void arch_disarm_kprobe(struct kprobe *p); |
178 | extern void arch_remove_kprobe(struct kprobe *p); | 157 | extern void arch_remove_kprobe(struct kprobe *p); |
158 | extern int arch_init(void); | ||
179 | extern void show_registers(struct pt_regs *regs); | 159 | extern void show_registers(struct pt_regs *regs); |
160 | extern kprobe_opcode_t *get_insn_slot(void); | ||
161 | extern void free_insn_slot(kprobe_opcode_t *slot); | ||
180 | 162 | ||
181 | /* Get the kprobe at this addr (if any). Must have called lock_kprobes */ | 163 | /* Get the kprobe at this addr (if any). Must have called lock_kprobes */ |
182 | struct kprobe *get_kprobe(void *addr); | 164 | struct kprobe *get_kprobe(void *addr); |
@@ -194,8 +176,6 @@ int register_kretprobe(struct kretprobe *rp); | |||
194 | void unregister_kretprobe(struct kretprobe *rp); | 176 | void unregister_kretprobe(struct kretprobe *rp); |
195 | 177 | ||
196 | struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp); | 178 | struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp); |
197 | struct kretprobe_instance *get_rp_inst(void *sara); | ||
198 | struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk); | ||
199 | void add_rp_inst(struct kretprobe_instance *ri); | 179 | void add_rp_inst(struct kretprobe_instance *ri); |
200 | void kprobe_flush_task(struct task_struct *tk); | 180 | void kprobe_flush_task(struct task_struct *tk); |
201 | void recycle_rp_inst(struct kretprobe_instance *ri); | 181 | void recycle_rp_inst(struct kretprobe_instance *ri); |
diff --git a/include/linux/libps2.h b/include/linux/libps2.h index 923bdbc6d9e4..a710bddda4eb 100644 --- a/include/linux/libps2.h +++ b/include/linux/libps2.h | |||
@@ -41,6 +41,7 @@ struct ps2dev { | |||
41 | 41 | ||
42 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); | 42 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); |
43 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); | 43 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); |
44 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); | ||
44 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); | 45 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); |
45 | int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command); | 46 | int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command); |
46 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); | 47 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bf608808a60c..a3961e1d5183 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -712,8 +712,9 @@ | |||
712 | #define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 | 712 | #define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 |
713 | #define PCI_DEVICE_ID_HP_DIVA_RMP3 0x1301 | 713 | #define PCI_DEVICE_ID_HP_DIVA_RMP3 0x1301 |
714 | #define PCI_DEVICE_ID_HP_CISSA 0x3220 | 714 | #define PCI_DEVICE_ID_HP_CISSA 0x3220 |
715 | #define PCI_DEVICE_ID_HP_CISSB 0x3230 | 715 | #define PCI_DEVICE_ID_HP_CISSB 0x3222 |
716 | #define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031 | 716 | #define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031 |
717 | #define PCI_DEVICE_ID_HP_CISSC 0x3230 | ||
717 | 718 | ||
718 | #define PCI_VENDOR_ID_PCTECH 0x1042 | 719 | #define PCI_VENDOR_ID_PCTECH 0x1042 |
719 | #define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 | 720 | #define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 |
@@ -1284,6 +1285,8 @@ | |||
1284 | #define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2 0x0348 | 1285 | #define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2 0x0348 |
1285 | #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000 0x034C | 1286 | #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000 0x034C |
1286 | #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100 0x034E | 1287 | #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100 0x034E |
1288 | #define PCI_DEVICE_ID_NVIDIA_NVENET_14 0x0372 | ||
1289 | #define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373 | ||
1287 | 1290 | ||
1288 | #define PCI_VENDOR_ID_IMS 0x10e0 | 1291 | #define PCI_VENDOR_ID_IMS 0x10e0 |
1289 | #define PCI_DEVICE_ID_IMS_8849 0x8849 | 1292 | #define PCI_DEVICE_ID_IMS_8849 0x8849 |
diff --git a/include/linux/pmu.h b/include/linux/pmu.h index 6d73eada277e..373bd3b9b330 100644 --- a/include/linux/pmu.h +++ b/include/linux/pmu.h | |||
@@ -166,7 +166,7 @@ extern int pmu_i2c_simple_read(int bus, int addr, u8* data, int len); | |||
166 | extern int pmu_i2c_simple_write(int bus, int addr, u8* data, int len); | 166 | extern int pmu_i2c_simple_write(int bus, int addr, u8* data, int len); |
167 | 167 | ||
168 | 168 | ||
169 | #ifdef CONFIG_PMAC_PBOOK | 169 | #ifdef CONFIG_PM |
170 | /* | 170 | /* |
171 | * Stuff for putting the powerbook to sleep and waking it again. | 171 | * Stuff for putting the powerbook to sleep and waking it again. |
172 | * | 172 | * |
@@ -208,6 +208,8 @@ struct pmu_sleep_notifier | |||
208 | int pmu_register_sleep_notifier(struct pmu_sleep_notifier* notifier); | 208 | int pmu_register_sleep_notifier(struct pmu_sleep_notifier* notifier); |
209 | int pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* notifier); | 209 | int pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* notifier); |
210 | 210 | ||
211 | #endif /* CONFIG_PM */ | ||
212 | |||
211 | #define PMU_MAX_BATTERIES 2 | 213 | #define PMU_MAX_BATTERIES 2 |
212 | 214 | ||
213 | /* values for pmu_power_flags */ | 215 | /* values for pmu_power_flags */ |
@@ -235,6 +237,4 @@ extern int pmu_battery_count; | |||
235 | extern struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES]; | 237 | extern struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES]; |
236 | extern unsigned int pmu_power_flags; | 238 | extern unsigned int pmu_power_flags; |
237 | 239 | ||
238 | #endif /* CONFIG_PMAC_PBOOK */ | ||
239 | |||
240 | #endif /* __KERNEL__ */ | 240 | #endif /* __KERNEL__ */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 9530b1903160..ff48815bd3a2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -608,6 +608,8 @@ struct task_struct { | |||
608 | struct list_head run_list; | 608 | struct list_head run_list; |
609 | prio_array_t *array; | 609 | prio_array_t *array; |
610 | 610 | ||
611 | unsigned short ioprio; | ||
612 | |||
611 | unsigned long sleep_avg; | 613 | unsigned long sleep_avg; |
612 | unsigned long long timestamp, last_ran; | 614 | unsigned long long timestamp, last_ran; |
613 | unsigned long long sched_time; /* sched_clock time spent running */ | 615 | unsigned long long sched_time; /* sched_clock time spent running */ |
@@ -763,6 +765,7 @@ struct task_struct { | |||
763 | nodemask_t mems_allowed; | 765 | nodemask_t mems_allowed; |
764 | int cpuset_mems_generation; | 766 | int cpuset_mems_generation; |
765 | #endif | 767 | #endif |
768 | atomic_t fs_excl; /* holding fs exclusive resources */ | ||
766 | }; | 769 | }; |
767 | 770 | ||
768 | static inline pid_t process_group(struct task_struct *tsk) | 771 | static inline pid_t process_group(struct task_struct *tsk) |
@@ -1112,7 +1115,8 @@ extern void unhash_process(struct task_struct *p); | |||
1112 | 1115 | ||
1113 | /* | 1116 | /* |
1114 | * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring | 1117 | * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring |
1115 | * subscriptions and synchronises with wait4(). Also used in procfs. | 1118 | * subscriptions and synchronises with wait4(). Also used in procfs. Also |
1119 | * pins the final release of task.io_context. | ||
1116 | * | 1120 | * |
1117 | * Nests both inside and outside of read_lock(&tasklist_lock). | 1121 | * Nests both inside and outside of read_lock(&tasklist_lock). |
1118 | * It must not be nested with write_lock_irq(&tasklist_lock), | 1122 | * It must not be nested with write_lock_irq(&tasklist_lock), |
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index 3a2702bbb1d6..dc89116bb1ca 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h | |||
@@ -19,6 +19,11 @@ static inline void secure_computing(int this_syscall) | |||
19 | __secure_computing(this_syscall); | 19 | __secure_computing(this_syscall); |
20 | } | 20 | } |
21 | 21 | ||
22 | static inline int has_secure_computing(struct thread_info *ti) | ||
23 | { | ||
24 | return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP)); | ||
25 | } | ||
26 | |||
22 | #else /* CONFIG_SECCOMP */ | 27 | #else /* CONFIG_SECCOMP */ |
23 | 28 | ||
24 | #if (__GNUC__ > 2) | 29 | #if (__GNUC__ > 2) |
@@ -28,6 +33,11 @@ static inline void secure_computing(int this_syscall) | |||
28 | #endif | 33 | #endif |
29 | 34 | ||
30 | #define secure_computing(x) do { } while (0) | 35 | #define secure_computing(x) do { } while (0) |
36 | /* static inline to preserve typechecking */ | ||
37 | static inline int has_secure_computing(struct thread_info *ti) | ||
38 | { | ||
39 | return 0; | ||
40 | } | ||
31 | 41 | ||
32 | #endif /* CONFIG_SECCOMP */ | 42 | #endif /* CONFIG_SECCOMP */ |
33 | 43 | ||
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 823181af6ddf..3e3c1fa35b06 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h | |||
@@ -22,6 +22,7 @@ struct plat_serial8250_port { | |||
22 | unsigned int uartclk; /* UART clock rate */ | 22 | unsigned int uartclk; /* UART clock rate */ |
23 | unsigned char regshift; /* register shift */ | 23 | unsigned char regshift; /* register shift */ |
24 | unsigned char iotype; /* UPIO_* */ | 24 | unsigned char iotype; /* UPIO_* */ |
25 | unsigned char hub6; | ||
25 | unsigned int flags; /* UPF_* flags */ | 26 | unsigned int flags; /* UPF_* flags */ |
26 | }; | 27 | }; |
27 | 28 | ||
diff --git a/include/linux/serio.h b/include/linux/serio.h index a2d3b9ae06f4..aa4d6493a034 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h | |||
@@ -83,6 +83,7 @@ static inline void serio_register_port(struct serio *serio) | |||
83 | } | 83 | } |
84 | 84 | ||
85 | void serio_unregister_port(struct serio *serio); | 85 | void serio_unregister_port(struct serio *serio); |
86 | void serio_unregister_child_port(struct serio *serio); | ||
86 | void __serio_unregister_port_delayed(struct serio *serio, struct module *owner); | 87 | void __serio_unregister_port_delayed(struct serio *serio, struct module *owner); |
87 | static inline void serio_unregister_port_delayed(struct serio *serio) | 88 | static inline void serio_unregister_port_delayed(struct serio *serio) |
88 | { | 89 | { |
@@ -153,6 +154,11 @@ static inline int serio_pin_driver(struct serio *serio) | |||
153 | return down_interruptible(&serio->drv_sem); | 154 | return down_interruptible(&serio->drv_sem); |
154 | } | 155 | } |
155 | 156 | ||
157 | static inline void serio_pin_driver_uninterruptible(struct serio *serio) | ||
158 | { | ||
159 | down(&serio->drv_sem); | ||
160 | } | ||
161 | |||
156 | static inline void serio_unpin_driver(struct serio *serio) | 162 | static inline void serio_unpin_driver(struct serio *serio) |
157 | { | 163 | { |
158 | up(&serio->drv_sem); | 164 | up(&serio->drv_sem); |
diff --git a/include/linux/usb_ch9.h b/include/linux/usb_ch9.h index f5fe94e09a03..39e7ff4ffd28 100644 --- a/include/linux/usb_ch9.h +++ b/include/linux/usb_ch9.h | |||
@@ -6,11 +6,14 @@ | |||
6 | * | 6 | * |
7 | * - the master/host side Linux-USB kernel driver API; | 7 | * - the master/host side Linux-USB kernel driver API; |
8 | * - the "usbfs" user space API; and | 8 | * - the "usbfs" user space API; and |
9 | * - (eventually) a Linux "gadget" slave/device side driver API. | 9 | * - the Linux "gadget" slave/device/peripheral side driver API. |
10 | * | 10 | * |
11 | * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems | 11 | * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems |
12 | * act either as a USB master/host or as a USB slave/device. That means | 12 | * act either as a USB master/host or as a USB slave/device. That means |
13 | * the master and slave side APIs will benefit from working well together. | 13 | * the master and slave side APIs benefit from working well together. |
14 | * | ||
15 | * There's also "Wireless USB", using low power short range radios for | ||
16 | * peripheral interconnection but otherwise building on the USB framework. | ||
14 | */ | 17 | */ |
15 | 18 | ||
16 | #ifndef __LINUX_USB_CH9_H | 19 | #ifndef __LINUX_USB_CH9_H |
@@ -68,6 +71,18 @@ | |||
68 | #define USB_REQ_SET_INTERFACE 0x0B | 71 | #define USB_REQ_SET_INTERFACE 0x0B |
69 | #define USB_REQ_SYNCH_FRAME 0x0C | 72 | #define USB_REQ_SYNCH_FRAME 0x0C |
70 | 73 | ||
74 | #define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ | ||
75 | #define USB_REQ_GET_ENCRYPTION 0x0E | ||
76 | #define USB_REQ_SET_HANDSHAKE 0x0F | ||
77 | #define USB_REQ_GET_HANDSHAKE 0x10 | ||
78 | #define USB_REQ_SET_CONNECTION 0x11 | ||
79 | #define USB_REQ_SET_SECURITY_DATA 0x12 | ||
80 | #define USB_REQ_GET_SECURITY_DATA 0x13 | ||
81 | #define USB_REQ_SET_WUSB_DATA 0x14 | ||
82 | #define USB_REQ_LOOPBACK_DATA_WRITE 0x15 | ||
83 | #define USB_REQ_LOOPBACK_DATA_READ 0x16 | ||
84 | #define USB_REQ_SET_INTERFACE_DS 0x17 | ||
85 | |||
71 | /* | 86 | /* |
72 | * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and | 87 | * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and |
73 | * are read as a bit array returned by USB_REQ_GET_STATUS. (So there | 88 | * are read as a bit array returned by USB_REQ_GET_STATUS. (So there |
@@ -75,10 +90,12 @@ | |||
75 | */ | 90 | */ |
76 | #define USB_DEVICE_SELF_POWERED 0 /* (read only) */ | 91 | #define USB_DEVICE_SELF_POWERED 0 /* (read only) */ |
77 | #define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ | 92 | #define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ |
78 | #define USB_DEVICE_TEST_MODE 2 /* (high speed only) */ | 93 | #define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ |
79 | #define USB_DEVICE_B_HNP_ENABLE 3 /* dev may initiate HNP */ | 94 | #define USB_DEVICE_BATTERY 2 /* (wireless) */ |
80 | #define USB_DEVICE_A_HNP_SUPPORT 4 /* RH port supports HNP */ | 95 | #define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ |
81 | #define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* other RH port does */ | 96 | #define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ |
97 | #define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ | ||
98 | #define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ | ||
82 | #define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ | 99 | #define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ |
83 | 100 | ||
84 | #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ | 101 | #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ |
@@ -135,6 +152,13 @@ struct usb_ctrlrequest { | |||
135 | #define USB_DT_OTG 0x09 | 152 | #define USB_DT_OTG 0x09 |
136 | #define USB_DT_DEBUG 0x0a | 153 | #define USB_DT_DEBUG 0x0a |
137 | #define USB_DT_INTERFACE_ASSOCIATION 0x0b | 154 | #define USB_DT_INTERFACE_ASSOCIATION 0x0b |
155 | /* these are from the Wireless USB spec */ | ||
156 | #define USB_DT_SECURITY 0x0c | ||
157 | #define USB_DT_KEY 0x0d | ||
158 | #define USB_DT_ENCRYPTION_TYPE 0x0e | ||
159 | #define USB_DT_BOS 0x0f | ||
160 | #define USB_DT_DEVICE_CAPABILITY 0x10 | ||
161 | #define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 | ||
138 | 162 | ||
139 | /* conventional codes for class-specific descriptors */ | 163 | /* conventional codes for class-specific descriptors */ |
140 | #define USB_DT_CS_DEVICE 0x21 | 164 | #define USB_DT_CS_DEVICE 0x21 |
@@ -192,6 +216,7 @@ struct usb_device_descriptor { | |||
192 | #define USB_CLASS_CSCID 0x0b /* chip+ smart card */ | 216 | #define USB_CLASS_CSCID 0x0b /* chip+ smart card */ |
193 | #define USB_CLASS_CONTENT_SEC 0x0d /* content security */ | 217 | #define USB_CLASS_CONTENT_SEC 0x0d /* content security */ |
194 | #define USB_CLASS_VIDEO 0x0e | 218 | #define USB_CLASS_VIDEO 0x0e |
219 | #define USB_CLASS_WIRELESS_CONTROLLER 0xe0 | ||
195 | #define USB_CLASS_APP_SPEC 0xfe | 220 | #define USB_CLASS_APP_SPEC 0xfe |
196 | #define USB_CLASS_VENDOR_SPEC 0xff | 221 | #define USB_CLASS_VENDOR_SPEC 0xff |
197 | 222 | ||
@@ -223,6 +248,7 @@ struct usb_config_descriptor { | |||
223 | #define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ | 248 | #define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ |
224 | #define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ | 249 | #define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ |
225 | #define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ | 250 | #define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ |
251 | #define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ | ||
226 | 252 | ||
227 | /*-------------------------------------------------------------------------*/ | 253 | /*-------------------------------------------------------------------------*/ |
228 | 254 | ||
@@ -289,6 +315,7 @@ struct usb_endpoint_descriptor { | |||
289 | #define USB_ENDPOINT_XFER_ISOC 1 | 315 | #define USB_ENDPOINT_XFER_ISOC 1 |
290 | #define USB_ENDPOINT_XFER_BULK 2 | 316 | #define USB_ENDPOINT_XFER_BULK 2 |
291 | #define USB_ENDPOINT_XFER_INT 3 | 317 | #define USB_ENDPOINT_XFER_INT 3 |
318 | #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 | ||
292 | 319 | ||
293 | 320 | ||
294 | /*-------------------------------------------------------------------------*/ | 321 | /*-------------------------------------------------------------------------*/ |
@@ -352,12 +379,154 @@ struct usb_interface_assoc_descriptor { | |||
352 | 379 | ||
353 | /*-------------------------------------------------------------------------*/ | 380 | /*-------------------------------------------------------------------------*/ |
354 | 381 | ||
382 | /* USB_DT_SECURITY: group of wireless security descriptors, including | ||
383 | * encryption types available for setting up a CC/association. | ||
384 | */ | ||
385 | struct usb_security_descriptor { | ||
386 | __u8 bLength; | ||
387 | __u8 bDescriptorType; | ||
388 | |||
389 | __le16 wTotalLength; | ||
390 | __u8 bNumEncryptionTypes; | ||
391 | }; | ||
392 | |||
393 | /*-------------------------------------------------------------------------*/ | ||
394 | |||
395 | /* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys | ||
396 | * may be retrieved. | ||
397 | */ | ||
398 | struct usb_key_descriptor { | ||
399 | __u8 bLength; | ||
400 | __u8 bDescriptorType; | ||
401 | |||
402 | __u8 tTKID[3]; | ||
403 | __u8 bReserved; | ||
404 | __u8 bKeyData[0]; | ||
405 | }; | ||
406 | |||
407 | /*-------------------------------------------------------------------------*/ | ||
408 | |||
409 | /* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */ | ||
410 | struct usb_encryption_descriptor { | ||
411 | __u8 bLength; | ||
412 | __u8 bDescriptorType; | ||
413 | |||
414 | __u8 bEncryptionType; | ||
415 | #define USB_ENC_TYPE_UNSECURE 0 | ||
416 | #define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */ | ||
417 | #define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */ | ||
418 | #define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */ | ||
419 | __u8 bEncryptionValue; /* use in SET_ENCRYPTION */ | ||
420 | __u8 bAuthKeyIndex; | ||
421 | }; | ||
422 | |||
423 | |||
424 | /*-------------------------------------------------------------------------*/ | ||
425 | |||
426 | /* USB_DT_BOS: group of wireless capabilities */ | ||
427 | struct usb_bos_descriptor { | ||
428 | __u8 bLength; | ||
429 | __u8 bDescriptorType; | ||
430 | |||
431 | __le16 wTotalLength; | ||
432 | __u8 bNumDeviceCaps; | ||
433 | }; | ||
434 | |||
435 | /*-------------------------------------------------------------------------*/ | ||
436 | |||
437 | /* USB_DT_DEVICE_CAPABILITY: grouped with BOS */ | ||
438 | struct usb_dev_cap_header { | ||
439 | __u8 bLength; | ||
440 | __u8 bDescriptorType; | ||
441 | __u8 bDevCapabilityType; | ||
442 | }; | ||
443 | |||
444 | #define USB_CAP_TYPE_WIRELESS_USB 1 | ||
445 | |||
446 | struct usb_wireless_cap_descriptor { /* Ultra Wide Band */ | ||
447 | __u8 bLength; | ||
448 | __u8 bDescriptorType; | ||
449 | __u8 bDevCapabilityType; | ||
450 | |||
451 | __u8 bmAttributes; | ||
452 | #define USB_WIRELESS_P2P_DRD (1 << 1) | ||
453 | #define USB_WIRELESS_BEACON_MASK (3 << 2) | ||
454 | #define USB_WIRELESS_BEACON_SELF (1 << 2) | ||
455 | #define USB_WIRELESS_BEACON_DIRECTED (2 << 2) | ||
456 | #define USB_WIRELESS_BEACON_NONE (3 << 2) | ||
457 | __le16 wPHYRates; /* bit rates, Mbps */ | ||
458 | #define USB_WIRELESS_PHY_53 (1 << 0) /* always set */ | ||
459 | #define USB_WIRELESS_PHY_80 (1 << 1) | ||
460 | #define USB_WIRELESS_PHY_107 (1 << 2) /* always set */ | ||
461 | #define USB_WIRELESS_PHY_160 (1 << 3) | ||
462 | #define USB_WIRELESS_PHY_200 (1 << 4) /* always set */ | ||
463 | #define USB_WIRELESS_PHY_320 (1 << 5) | ||
464 | #define USB_WIRELESS_PHY_400 (1 << 6) | ||
465 | #define USB_WIRELESS_PHY_480 (1 << 7) | ||
466 | __u8 bmTFITXPowerInfo; /* TFI power levels */ | ||
467 | __u8 bmFFITXPowerInfo; /* FFI power levels */ | ||
468 | __le16 bmBandGroup; | ||
469 | __u8 bReserved; | ||
470 | }; | ||
471 | |||
472 | /*-------------------------------------------------------------------------*/ | ||
473 | |||
474 | /* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with | ||
475 | * each endpoint descriptor for a wireless device | ||
476 | */ | ||
477 | struct usb_wireless_ep_comp_descriptor { | ||
478 | __u8 bLength; | ||
479 | __u8 bDescriptorType; | ||
480 | |||
481 | __u8 bMaxBurst; | ||
482 | __u8 bMaxSequence; | ||
483 | __le16 wMaxStreamDelay; | ||
484 | __le16 wOverTheAirPacketSize; | ||
485 | __u8 bOverTheAirInterval; | ||
486 | __u8 bmCompAttributes; | ||
487 | #define USB_ENDPOINT_SWITCH_MASK 0x03 /* in bmCompAttributes */ | ||
488 | #define USB_ENDPOINT_SWITCH_NO 0 | ||
489 | #define USB_ENDPOINT_SWITCH_SWITCH 1 | ||
490 | #define USB_ENDPOINT_SWITCH_SCALE 2 | ||
491 | }; | ||
492 | |||
493 | /*-------------------------------------------------------------------------*/ | ||
494 | |||
495 | /* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless | ||
496 | * host and a device for connection set up, mutual authentication, and | ||
497 | * exchanging short lived session keys. The handshake depends on a CC. | ||
498 | */ | ||
499 | struct usb_handshake { | ||
500 | __u8 bMessageNumber; | ||
501 | __u8 bStatus; | ||
502 | __u8 tTKID[3]; | ||
503 | __u8 bReserved; | ||
504 | __u8 CDID[16]; | ||
505 | __u8 nonce[16]; | ||
506 | __u8 MIC[8]; | ||
507 | }; | ||
508 | |||
509 | /*-------------------------------------------------------------------------*/ | ||
510 | |||
511 | /* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC). | ||
512 | * A CC may also be set up using non-wireless secure channels (including | ||
513 | * wired USB!), and some devices may support CCs with multiple hosts. | ||
514 | */ | ||
515 | struct usb_connection_context { | ||
516 | __u8 CHID[16]; /* persistent host id */ | ||
517 | __u8 CDID[16]; /* device id (unique w/in host context) */ | ||
518 | __u8 CK[16]; /* connection key */ | ||
519 | }; | ||
520 | |||
521 | /*-------------------------------------------------------------------------*/ | ||
522 | |||
355 | /* USB 2.0 defines three speeds, here's how Linux identifies them */ | 523 | /* USB 2.0 defines three speeds, here's how Linux identifies them */ |
356 | 524 | ||
357 | enum usb_device_speed { | 525 | enum usb_device_speed { |
358 | USB_SPEED_UNKNOWN = 0, /* enumerating */ | 526 | USB_SPEED_UNKNOWN = 0, /* enumerating */ |
359 | USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ | 527 | USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ |
360 | USB_SPEED_HIGH /* usb 2.0 */ | 528 | USB_SPEED_HIGH, /* usb 2.0 */ |
529 | USB_SPEED_VARIABLE, /* wireless (usb 2.5) */ | ||
361 | }; | 530 | }; |
362 | 531 | ||
363 | enum usb_device_state { | 532 | enum usb_device_state { |
diff --git a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h index 9bba9997947b..b00f127cb447 100644 --- a/include/linux/usb_gadget.h +++ b/include/linux/usb_gadget.h | |||
@@ -711,7 +711,7 @@ usb_gadget_disconnect (struct usb_gadget *gadget) | |||
711 | * the hardware level driver. Most calls must be handled by | 711 | * the hardware level driver. Most calls must be handled by |
712 | * the gadget driver, including descriptor and configuration | 712 | * the gadget driver, including descriptor and configuration |
713 | * management. The 16 bit members of the setup data are in | 713 | * management. The 16 bit members of the setup data are in |
714 | * cpu order. Called in_interrupt; this may not sleep. Driver | 714 | * USB byte order. Called in_interrupt; this may not sleep. Driver |
715 | * queues a response to ep0, or returns negative to stall. | 715 | * queues a response to ep0, or returns negative to stall. |
716 | * @disconnect: Invoked after all transfers have been stopped, | 716 | * @disconnect: Invoked after all transfers have been stopped, |
717 | * when the host is disconnected. May be called in_interrupt; this | 717 | * when the host is disconnected. May be called in_interrupt; this |
diff --git a/include/linux/usb_isp116x.h b/include/linux/usb_isp116x.h new file mode 100644 index 000000000000..5f5a9d9bd6c2 --- /dev/null +++ b/include/linux/usb_isp116x.h | |||
@@ -0,0 +1,47 @@ | |||
1 | |||
2 | /* | ||
3 | * Board initialization code should put one of these into dev->platform_data | ||
4 | * and place the isp116x onto platform_bus. | ||
5 | */ | ||
6 | |||
7 | struct isp116x_platform_data { | ||
8 | /* Enable internal resistors on downstream ports */ | ||
9 | unsigned sel15Kres:1; | ||
10 | /* Chip's internal clock won't be stopped in suspended state. | ||
11 | Setting/unsetting this bit takes effect only if | ||
12 | 'remote_wakeup_enable' below is not set. */ | ||
13 | unsigned clknotstop:1; | ||
14 | /* On-chip overcurrent protection */ | ||
15 | unsigned oc_enable:1; | ||
16 | /* INT output polarity */ | ||
17 | unsigned int_act_high:1; | ||
18 | /* INT edge or level triggered */ | ||
19 | unsigned int_edge_triggered:1; | ||
20 | /* WAKEUP pin connected - NOT SUPPORTED */ | ||
21 | /* unsigned remote_wakeup_connected:1; */ | ||
22 | /* Wakeup by devices on usb bus enabled */ | ||
23 | unsigned remote_wakeup_enable:1; | ||
24 | /* Switch or not to switch (keep always powered) */ | ||
25 | unsigned no_power_switching:1; | ||
26 | /* Ganged port power switching (0) or individual port | ||
27 | power switching (1) */ | ||
28 | unsigned power_switching_mode:1; | ||
29 | /* Given port_power, msec/2 after power on till power good */ | ||
30 | u8 potpg; | ||
31 | /* Hardware reset set/clear. If implemented, this function must: | ||
32 | if set == 0, deassert chip's HW reset pin | ||
33 | otherwise, assert chip's HW reset pin */ | ||
34 | void (*reset) (struct device * dev, int set); | ||
35 | /* Hardware clock start/stop. If implemented, this function must: | ||
36 | if start == 0, stop the external clock | ||
37 | otherwise, start the external clock | ||
38 | */ | ||
39 | void (*clock) (struct device * dev, int start); | ||
40 | /* Inter-io delay (ns). The chip is picky about access timings; it | ||
41 | expects at least: | ||
42 | 150ns delay between consecutive accesses to DATA_REG, | ||
43 | 300ns delay between access to ADDR_REG and DATA_REG | ||
44 | OE, WE MUST NOT be changed during these intervals | ||
45 | */ | ||
46 | void (*delay) (struct device * dev, int delay); | ||
47 | }; | ||
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 1262cb43c3ab..d5c3fe1bf33d 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -14,11 +14,13 @@ extern struct list_head inode_unused; | |||
14 | * Yes, writeback.h requires sched.h | 14 | * Yes, writeback.h requires sched.h |
15 | * No, sched.h is not included from here. | 15 | * No, sched.h is not included from here. |
16 | */ | 16 | */ |
17 | static inline int current_is_pdflush(void) | 17 | static inline int task_is_pdflush(struct task_struct *task) |
18 | { | 18 | { |
19 | return current->flags & PF_FLUSHER; | 19 | return task->flags & PF_FLUSHER; |
20 | } | 20 | } |
21 | 21 | ||
22 | #define current_is_pdflush() task_is_pdflush(current) | ||
23 | |||
22 | /* | 24 | /* |
23 | * fs/fs-writeback.c | 25 | * fs/fs-writeback.c |
24 | */ | 26 | */ |
diff --git a/kernel/exit.c b/kernel/exit.c index 3ebcd60a19c6..9d1b10ed0135 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -784,6 +784,8 @@ fastcall NORET_TYPE void do_exit(long code) | |||
784 | 784 | ||
785 | profile_task_exit(tsk); | 785 | profile_task_exit(tsk); |
786 | 786 | ||
787 | WARN_ON(atomic_read(&tsk->fs_excl)); | ||
788 | |||
787 | if (unlikely(in_interrupt())) | 789 | if (unlikely(in_interrupt())) |
788 | panic("Aiee, killing interrupt handler!"); | 790 | panic("Aiee, killing interrupt handler!"); |
789 | if (unlikely(!tsk->pid)) | 791 | if (unlikely(!tsk->pid)) |
diff --git a/kernel/fork.c b/kernel/fork.c index 2c7806873bfd..cdef6cea8900 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1090,6 +1090,11 @@ static task_t *copy_process(unsigned long clone_flags, | |||
1090 | spin_unlock(¤t->sighand->siglock); | 1090 | spin_unlock(¤t->sighand->siglock); |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | /* | ||
1094 | * inherit ioprio | ||
1095 | */ | ||
1096 | p->ioprio = current->ioprio; | ||
1097 | |||
1093 | SET_LINKS(p); | 1098 | SET_LINKS(p); |
1094 | if (unlikely(p->ptrace & PT_PTRACED)) | 1099 | if (unlikely(p->ptrace & PT_PTRACED)) |
1095 | __ptrace_link(p, current->parent); | 1100 | __ptrace_link(p, current->parent); |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 334f37472c56..90c0e82b650c 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/hash.h> | 36 | #include <linux/hash.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/moduleloader.h> | ||
39 | #include <asm/cacheflush.h> | 40 | #include <asm/cacheflush.h> |
40 | #include <asm/errno.h> | 41 | #include <asm/errno.h> |
41 | #include <asm/kdebug.h> | 42 | #include <asm/kdebug.h> |
@@ -50,6 +51,106 @@ unsigned int kprobe_cpu = NR_CPUS; | |||
50 | static DEFINE_SPINLOCK(kprobe_lock); | 51 | static DEFINE_SPINLOCK(kprobe_lock); |
51 | static struct kprobe *curr_kprobe; | 52 | static struct kprobe *curr_kprobe; |
52 | 53 | ||
54 | /* | ||
55 | * kprobe->ainsn.insn points to the copy of the instruction to be | ||
56 | * single-stepped. x86_64, POWER4 and above have no-exec support and | ||
57 | * stepping on the instruction on a vmalloced/kmalloced/data page | ||
58 | * is a recipe for disaster | ||
59 | */ | ||
60 | #define INSNS_PER_PAGE (PAGE_SIZE/(MAX_INSN_SIZE * sizeof(kprobe_opcode_t))) | ||
61 | |||
62 | struct kprobe_insn_page { | ||
63 | struct hlist_node hlist; | ||
64 | kprobe_opcode_t *insns; /* Page of instruction slots */ | ||
65 | char slot_used[INSNS_PER_PAGE]; | ||
66 | int nused; | ||
67 | }; | ||
68 | |||
69 | static struct hlist_head kprobe_insn_pages; | ||
70 | |||
71 | /** | ||
72 | * get_insn_slot() - Find a slot on an executable page for an instruction. | ||
73 | * We allocate an executable page if there's no room on existing ones. | ||
74 | */ | ||
75 | kprobe_opcode_t *get_insn_slot(void) | ||
76 | { | ||
77 | struct kprobe_insn_page *kip; | ||
78 | struct hlist_node *pos; | ||
79 | |||
80 | hlist_for_each(pos, &kprobe_insn_pages) { | ||
81 | kip = hlist_entry(pos, struct kprobe_insn_page, hlist); | ||
82 | if (kip->nused < INSNS_PER_PAGE) { | ||
83 | int i; | ||
84 | for (i = 0; i < INSNS_PER_PAGE; i++) { | ||
85 | if (!kip->slot_used[i]) { | ||
86 | kip->slot_used[i] = 1; | ||
87 | kip->nused++; | ||
88 | return kip->insns + (i * MAX_INSN_SIZE); | ||
89 | } | ||
90 | } | ||
91 | /* Surprise! No unused slots. Fix kip->nused. */ | ||
92 | kip->nused = INSNS_PER_PAGE; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /* All out of space. Need to allocate a new page. Use slot 0.*/ | ||
97 | kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL); | ||
98 | if (!kip) { | ||
99 | return NULL; | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * Use module_alloc so this page is within +/- 2GB of where the | ||
104 | * kernel image and loaded module images reside. This is required | ||
105 | * so x86_64 can correctly handle the %rip-relative fixups. | ||
106 | */ | ||
107 | kip->insns = module_alloc(PAGE_SIZE); | ||
108 | if (!kip->insns) { | ||
109 | kfree(kip); | ||
110 | return NULL; | ||
111 | } | ||
112 | INIT_HLIST_NODE(&kip->hlist); | ||
113 | hlist_add_head(&kip->hlist, &kprobe_insn_pages); | ||
114 | memset(kip->slot_used, 0, INSNS_PER_PAGE); | ||
115 | kip->slot_used[0] = 1; | ||
116 | kip->nused = 1; | ||
117 | return kip->insns; | ||
118 | } | ||
119 | |||
120 | void free_insn_slot(kprobe_opcode_t *slot) | ||
121 | { | ||
122 | struct kprobe_insn_page *kip; | ||
123 | struct hlist_node *pos; | ||
124 | |||
125 | hlist_for_each(pos, &kprobe_insn_pages) { | ||
126 | kip = hlist_entry(pos, struct kprobe_insn_page, hlist); | ||
127 | if (kip->insns <= slot && | ||
128 | slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) { | ||
129 | int i = (slot - kip->insns) / MAX_INSN_SIZE; | ||
130 | kip->slot_used[i] = 0; | ||
131 | kip->nused--; | ||
132 | if (kip->nused == 0) { | ||
133 | /* | ||
134 | * Page is no longer in use. Free it unless | ||
135 | * it's the last one. We keep the last one | ||
136 | * so as not to have to set it up again the | ||
137 | * next time somebody inserts a probe. | ||
138 | */ | ||
139 | hlist_del(&kip->hlist); | ||
140 | if (hlist_empty(&kprobe_insn_pages)) { | ||
141 | INIT_HLIST_NODE(&kip->hlist); | ||
142 | hlist_add_head(&kip->hlist, | ||
143 | &kprobe_insn_pages); | ||
144 | } else { | ||
145 | module_free(NULL, kip->insns); | ||
146 | kfree(kip); | ||
147 | } | ||
148 | } | ||
149 | return; | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | |||
53 | /* Locks kprobe: irqs must be disabled */ | 154 | /* Locks kprobe: irqs must be disabled */ |
54 | void lock_kprobes(void) | 155 | void lock_kprobes(void) |
55 | { | 156 | { |
@@ -139,12 +240,6 @@ static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
139 | return 0; | 240 | return 0; |
140 | } | 241 | } |
141 | 242 | ||
142 | struct kprobe trampoline_p = { | ||
143 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, | ||
144 | .pre_handler = trampoline_probe_handler, | ||
145 | .post_handler = trampoline_post_handler | ||
146 | }; | ||
147 | |||
148 | struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp) | 243 | struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp) |
149 | { | 244 | { |
150 | struct hlist_node *node; | 245 | struct hlist_node *node; |
@@ -163,35 +258,18 @@ static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp) | |||
163 | return NULL; | 258 | return NULL; |
164 | } | 259 | } |
165 | 260 | ||
166 | struct kretprobe_instance *get_rp_inst(void *sara) | ||
167 | { | ||
168 | struct hlist_head *head; | ||
169 | struct hlist_node *node; | ||
170 | struct task_struct *tsk; | ||
171 | struct kretprobe_instance *ri; | ||
172 | |||
173 | tsk = arch_get_kprobe_task(sara); | ||
174 | head = &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; | ||
175 | hlist_for_each_entry(ri, node, head, hlist) { | ||
176 | if (ri->stack_addr == sara) | ||
177 | return ri; | ||
178 | } | ||
179 | return NULL; | ||
180 | } | ||
181 | |||
182 | void add_rp_inst(struct kretprobe_instance *ri) | 261 | void add_rp_inst(struct kretprobe_instance *ri) |
183 | { | 262 | { |
184 | struct task_struct *tsk; | ||
185 | /* | 263 | /* |
186 | * Remove rp inst off the free list - | 264 | * Remove rp inst off the free list - |
187 | * Add it back when probed function returns | 265 | * Add it back when probed function returns |
188 | */ | 266 | */ |
189 | hlist_del(&ri->uflist); | 267 | hlist_del(&ri->uflist); |
190 | tsk = arch_get_kprobe_task(ri->stack_addr); | 268 | |
191 | /* Add rp inst onto table */ | 269 | /* Add rp inst onto table */ |
192 | INIT_HLIST_NODE(&ri->hlist); | 270 | INIT_HLIST_NODE(&ri->hlist); |
193 | hlist_add_head(&ri->hlist, | 271 | hlist_add_head(&ri->hlist, |
194 | &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]); | 272 | &kretprobe_inst_table[hash_ptr(ri->task, KPROBE_HASH_BITS)]); |
195 | 273 | ||
196 | /* Also add this rp inst to the used list. */ | 274 | /* Also add this rp inst to the used list. */ |
197 | INIT_HLIST_NODE(&ri->uflist); | 275 | INIT_HLIST_NODE(&ri->uflist); |
@@ -218,34 +296,25 @@ struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk) | |||
218 | return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; | 296 | return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; |
219 | } | 297 | } |
220 | 298 | ||
221 | struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk) | ||
222 | { | ||
223 | struct task_struct *tsk; | ||
224 | struct hlist_head *head; | ||
225 | struct hlist_node *node; | ||
226 | struct kretprobe_instance *ri; | ||
227 | |||
228 | head = &kretprobe_inst_table[hash_ptr(tk, KPROBE_HASH_BITS)]; | ||
229 | |||
230 | hlist_for_each_entry(ri, node, head, hlist) { | ||
231 | tsk = arch_get_kprobe_task(ri->stack_addr); | ||
232 | if (tsk == tk) | ||
233 | return ri; | ||
234 | } | ||
235 | return NULL; | ||
236 | } | ||
237 | |||
238 | /* | 299 | /* |
239 | * This function is called from do_exit or do_execv when task tk's stack is | 300 | * This function is called from exit_thread or flush_thread when task tk's |
240 | * about to be recycled. Recycle any function-return probe instances | 301 | * stack is being recycled so that we can recycle any function-return probe |
241 | * associated with this task. These represent probed functions that have | 302 | * instances associated with this task. These left over instances represent |
242 | * been called but may never return. | 303 | * probed functions that have been called but will never return. |
243 | */ | 304 | */ |
244 | void kprobe_flush_task(struct task_struct *tk) | 305 | void kprobe_flush_task(struct task_struct *tk) |
245 | { | 306 | { |
307 | struct kretprobe_instance *ri; | ||
308 | struct hlist_head *head; | ||
309 | struct hlist_node *node, *tmp; | ||
246 | unsigned long flags = 0; | 310 | unsigned long flags = 0; |
311 | |||
247 | spin_lock_irqsave(&kprobe_lock, flags); | 312 | spin_lock_irqsave(&kprobe_lock, flags); |
248 | arch_kprobe_flush_task(tk); | 313 | head = kretprobe_inst_table_head(current); |
314 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | ||
315 | if (ri->task == tk) | ||
316 | recycle_rp_inst(ri); | ||
317 | } | ||
249 | spin_unlock_irqrestore(&kprobe_lock, flags); | 318 | spin_unlock_irqrestore(&kprobe_lock, flags); |
250 | } | 319 | } |
251 | 320 | ||
@@ -505,9 +574,10 @@ static int __init init_kprobes(void) | |||
505 | INIT_HLIST_HEAD(&kretprobe_inst_table[i]); | 574 | INIT_HLIST_HEAD(&kretprobe_inst_table[i]); |
506 | } | 575 | } |
507 | 576 | ||
508 | err = register_die_notifier(&kprobe_exceptions_nb); | 577 | err = arch_init(); |
509 | /* Register the trampoline probe for return probe */ | 578 | if (!err) |
510 | register_kprobe(&trampoline_p); | 579 | err = register_die_notifier(&kprobe_exceptions_nb); |
580 | |||
511 | return err; | 581 | return err; |
512 | } | 582 | } |
513 | 583 | ||
diff --git a/kernel/sched.c b/kernel/sched.c index a07cff90d849..e2b0d3e4dd06 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -3448,15 +3448,7 @@ int task_nice(const task_t *p) | |||
3448 | { | 3448 | { |
3449 | return TASK_NICE(p); | 3449 | return TASK_NICE(p); |
3450 | } | 3450 | } |
3451 | |||
3452 | /* | ||
3453 | * The only users of task_nice are binfmt_elf and binfmt_elf32. | ||
3454 | * binfmt_elf is no longer modular, but binfmt_elf32 still is. | ||
3455 | * Therefore, task_nice is needed if there is a compat_mode. | ||
3456 | */ | ||
3457 | #ifdef CONFIG_COMPAT | ||
3458 | EXPORT_SYMBOL_GPL(task_nice); | 3451 | EXPORT_SYMBOL_GPL(task_nice); |
3459 | #endif | ||
3460 | 3452 | ||
3461 | /** | 3453 | /** |
3462 | * idle_cpu - is a given cpu idle currently? | 3454 | * idle_cpu - is a given cpu idle currently? |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 7ee675ad101e..3c9f7f881125 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1667,9 +1667,8 @@ void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
1667 | #ifdef WANT_PAGE_VIRTUAL | 1667 | #ifdef WANT_PAGE_VIRTUAL |
1668 | /* The shift won't overflow because ZONE_NORMAL is below 4G. */ | 1668 | /* The shift won't overflow because ZONE_NORMAL is below 4G. */ |
1669 | if (!is_highmem_idx(zone)) | 1669 | if (!is_highmem_idx(zone)) |
1670 | set_page_address(page, __va(start_pfn << PAGE_SHIFT)); | 1670 | set_page_address(page, __va(pfn << PAGE_SHIFT)); |
1671 | #endif | 1671 | #endif |
1672 | start_pfn++; | ||
1673 | } | 1672 | } |
1674 | } | 1673 | } |
1675 | 1674 | ||
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index 3b1fafc8f4f5..7bd95ceab7cc 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig | |||
@@ -52,7 +52,7 @@ config SOUND_CMPCI_MIDI | |||
52 | 52 | ||
53 | config SOUND_CMPCI_JOYSTICK | 53 | config SOUND_CMPCI_JOYSTICK |
54 | bool "Enable joystick" | 54 | bool "Enable joystick" |
55 | depends on SOUND_CMPCI && X86 | 55 | depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT) |
56 | help | 56 | help |
57 | Say Y here in order to enable the joystick port on a sound card using | 57 | Say Y here in order to enable the joystick port on a sound card using |
58 | the CMI8338 or the CMI8738 chipset. You need to config the | 58 | the CMI8338 or the CMI8738 chipset. You need to config the |
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index 33108661e671..2704e1598add 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c | |||
@@ -255,7 +255,7 @@ static int awacs_burgundy_read_mvolume(unsigned address); | |||
255 | 255 | ||
256 | static volatile struct dbdma_cmd *emergency_dbdma_cmd; | 256 | static volatile struct dbdma_cmd *emergency_dbdma_cmd; |
257 | 257 | ||
258 | #ifdef CONFIG_PMAC_PBOOK | 258 | #ifdef CONFIG_PM |
259 | /* | 259 | /* |
260 | * Stuff for restoring after a sleep. | 260 | * Stuff for restoring after a sleep. |
261 | */ | 261 | */ |
@@ -263,7 +263,7 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when); | |||
263 | struct pmu_sleep_notifier awacs_sleep_notifier = { | 263 | struct pmu_sleep_notifier awacs_sleep_notifier = { |
264 | awacs_sleep_notify, SLEEP_LEVEL_SOUND, | 264 | awacs_sleep_notify, SLEEP_LEVEL_SOUND, |
265 | }; | 265 | }; |
266 | #endif /* CONFIG_PMAC_PBOOK */ | 266 | #endif /* CONFIG_PM */ |
267 | 267 | ||
268 | /* for (soft) sample rate translations */ | 268 | /* for (soft) sample rate translations */ |
269 | int expand_bal; /* Balance factor for expanding (not volume!) */ | 269 | int expand_bal; /* Balance factor for expanding (not volume!) */ |
@@ -675,7 +675,7 @@ static void PMacIrqCleanup(void) | |||
675 | kfree(awacs_rx_cmd_space); | 675 | kfree(awacs_rx_cmd_space); |
676 | kfree(beep_dbdma_cmd_space); | 676 | kfree(beep_dbdma_cmd_space); |
677 | kfree(beep_buf); | 677 | kfree(beep_buf); |
678 | #ifdef CONFIG_PMAC_PBOOK | 678 | #ifdef CONFIG_PM |
679 | pmu_unregister_sleep_notifier(&awacs_sleep_notifier); | 679 | pmu_unregister_sleep_notifier(&awacs_sleep_notifier); |
680 | #endif | 680 | #endif |
681 | } | 681 | } |
@@ -1415,7 +1415,7 @@ load_awacs(void) | |||
1415 | } | 1415 | } |
1416 | } | 1416 | } |
1417 | 1417 | ||
1418 | #ifdef CONFIG_PMAC_PBOOK | 1418 | #ifdef CONFIG_PM |
1419 | /* | 1419 | /* |
1420 | * Save state when going to sleep, restore it afterwards. | 1420 | * Save state when going to sleep, restore it afterwards. |
1421 | */ | 1421 | */ |
@@ -1551,7 +1551,7 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) | |||
1551 | } | 1551 | } |
1552 | return PBOOK_SLEEP_OK; | 1552 | return PBOOK_SLEEP_OK; |
1553 | } | 1553 | } |
1554 | #endif /* CONFIG_PMAC_PBOOK */ | 1554 | #endif /* CONFIG_PM */ |
1555 | 1555 | ||
1556 | 1556 | ||
1557 | /* All the burgundy functions: */ | 1557 | /* All the burgundy functions: */ |
@@ -3053,9 +3053,9 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev); | |||
3053 | if ((res=setup_beep())) | 3053 | if ((res=setup_beep())) |
3054 | return res ; | 3054 | return res ; |
3055 | 3055 | ||
3056 | #ifdef CONFIG_PMAC_PBOOK | 3056 | #ifdef CONFIG_PM |
3057 | pmu_register_sleep_notifier(&awacs_sleep_notifier); | 3057 | pmu_register_sleep_notifier(&awacs_sleep_notifier); |
3058 | #endif /* CONFIG_PMAC_PBOOK */ | 3058 | #endif /* CONFIG_PM */ |
3059 | 3059 | ||
3060 | /* Powerbooks have odd ways of enabling inputs such as | 3060 | /* Powerbooks have odd ways of enabling inputs such as |
3061 | an expansion-bay CD or sound from an internal modem | 3061 | an expansion-bay CD or sound from an internal modem |
diff --git a/sound/oss/es1370.c b/sound/oss/es1370.c index 886f61c1c34a..8538085086e7 100644 --- a/sound/oss/es1370.c +++ b/sound/oss/es1370.c | |||
@@ -162,6 +162,10 @@ | |||
162 | #include <asm/page.h> | 162 | #include <asm/page.h> |
163 | #include <asm/uaccess.h> | 163 | #include <asm/uaccess.h> |
164 | 164 | ||
165 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
166 | #define SUPPORT_JOYSTICK | ||
167 | #endif | ||
168 | |||
165 | /* --------------------------------------------------------------------- */ | 169 | /* --------------------------------------------------------------------- */ |
166 | 170 | ||
167 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS | 171 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS |
@@ -385,7 +389,10 @@ struct es1370_state { | |||
385 | unsigned char obuf[MIDIOUTBUF]; | 389 | unsigned char obuf[MIDIOUTBUF]; |
386 | } midi; | 390 | } midi; |
387 | 391 | ||
392 | #ifdef SUPPORT_JOYSTICK | ||
388 | struct gameport *gameport; | 393 | struct gameport *gameport; |
394 | #endif | ||
395 | |||
389 | struct semaphore sem; | 396 | struct semaphore sem; |
390 | }; | 397 | }; |
391 | 398 | ||
@@ -2554,10 +2561,55 @@ static struct initvol { | |||
2554 | { SOUND_MIXER_WRITE_OGAIN, 0x4040 } | 2561 | { SOUND_MIXER_WRITE_OGAIN, 0x4040 } |
2555 | }; | 2562 | }; |
2556 | 2563 | ||
2564 | #ifdef SUPPORT_JOYSTICK | ||
2565 | |||
2566 | static int __devinit es1370_register_gameport(struct es1370_state *s) | ||
2567 | { | ||
2568 | struct gameport *gp; | ||
2569 | |||
2570 | if (!request_region(0x200, JOY_EXTENT, "es1370")) { | ||
2571 | printk(KERN_ERR "es1370: joystick io port 0x200 in use\n"); | ||
2572 | return -EBUSY; | ||
2573 | } | ||
2574 | |||
2575 | s->gameport = gp = gameport_allocate_port(); | ||
2576 | if (!gp) { | ||
2577 | printk(KERN_ERR "es1370: can not allocate memory for gameport\n"); | ||
2578 | release_region(0x200, JOY_EXTENT); | ||
2579 | return -ENOMEM; | ||
2580 | } | ||
2581 | |||
2582 | gameport_set_name(gp, "ESS1370"); | ||
2583 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); | ||
2584 | gp->dev.parent = &s->dev->dev; | ||
2585 | gp->io = 0x200; | ||
2586 | |||
2587 | s->ctrl |= CTRL_JYSTK_EN; | ||
2588 | outl(s->ctrl, s->io + ES1370_REG_CONTROL); | ||
2589 | |||
2590 | gameport_register_port(gp); | ||
2591 | |||
2592 | return 0; | ||
2593 | } | ||
2594 | |||
2595 | static inline void es1370_unregister_gameport(struct es1370_state *s) | ||
2596 | { | ||
2597 | if (s->gameport) { | ||
2598 | int gpio = s->gameport->io; | ||
2599 | gameport_unregister_port(s->gameport); | ||
2600 | release_region(gpio, JOY_EXTENT); | ||
2601 | |||
2602 | } | ||
2603 | } | ||
2604 | |||
2605 | #else | ||
2606 | static inline int es1370_register_gameport(struct es1370_state *s) { return -ENOSYS; } | ||
2607 | static inline void es1370_unregister_gameport(struct es1370_state *s) { } | ||
2608 | #endif /* SUPPORT_JOYSTICK */ | ||
2609 | |||
2557 | static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2610 | static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
2558 | { | 2611 | { |
2559 | struct es1370_state *s; | 2612 | struct es1370_state *s; |
2560 | struct gameport *gp = NULL; | ||
2561 | mm_segment_t fs; | 2613 | mm_segment_t fs; |
2562 | int i, val, ret; | 2614 | int i, val, ret; |
2563 | 2615 | ||
@@ -2606,28 +2658,14 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2606 | /* note: setting CTRL_SERR_DIS is reported to break | 2658 | /* note: setting CTRL_SERR_DIS is reported to break |
2607 | * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */ | 2659 | * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */ |
2608 | s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL); | 2660 | s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL); |
2609 | if (!request_region(0x200, JOY_EXTENT, "es1370")) { | ||
2610 | printk(KERN_ERR "es1370: joystick io port 0x200 in use\n"); | ||
2611 | } else if (!(s->gameport = gp = gameport_allocate_port())) { | ||
2612 | printk(KERN_ERR "es1370: can not allocate memory for gameport\n"); | ||
2613 | release_region(0x200, JOY_EXTENT); | ||
2614 | } else { | ||
2615 | gameport_set_name(gp, "ESS1370"); | ||
2616 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); | ||
2617 | gp->dev.parent = &s->dev->dev; | ||
2618 | gp->io = 0x200; | ||
2619 | s->ctrl |= CTRL_JYSTK_EN; | ||
2620 | } | ||
2621 | if (lineout[devindex]) | 2661 | if (lineout[devindex]) |
2622 | s->ctrl |= CTRL_XCTL0; | 2662 | s->ctrl |= CTRL_XCTL0; |
2623 | if (micbias[devindex]) | 2663 | if (micbias[devindex]) |
2624 | s->ctrl |= CTRL_XCTL1; | 2664 | s->ctrl |= CTRL_XCTL1; |
2625 | s->sctrl = 0; | 2665 | s->sctrl = 0; |
2626 | printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n" | 2666 | printk(KERN_INFO "es1370: adapter at io %#lx irq %u, line %s, mic impedance %s\n", |
2627 | KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n", | 2667 | s->io, s->irq, (s->ctrl & CTRL_XCTL0) ? "out" : "in", |
2628 | s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off", | 2668 | (s->ctrl & CTRL_XCTL1) ? "1" : "0"); |
2629 | (s->ctrl & CTRL_XCTL0) ? "out" : "in", | ||
2630 | (s->ctrl & CTRL_XCTL1) ? "1" : "0"); | ||
2631 | /* register devices */ | 2669 | /* register devices */ |
2632 | if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) { | 2670 | if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) { |
2633 | ret = s->dev_audio; | 2671 | ret = s->dev_audio; |
@@ -2673,9 +2711,7 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2673 | } | 2711 | } |
2674 | set_fs(fs); | 2712 | set_fs(fs); |
2675 | 2713 | ||
2676 | /* register gameport */ | 2714 | es1370_register_gameport(s); |
2677 | if (gp) | ||
2678 | gameport_register_port(gp); | ||
2679 | 2715 | ||
2680 | /* store it in the driver field */ | 2716 | /* store it in the driver field */ |
2681 | pci_set_drvdata(pcidev, s); | 2717 | pci_set_drvdata(pcidev, s); |
@@ -2697,10 +2733,6 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2697 | err_dev1: | 2733 | err_dev1: |
2698 | printk(KERN_ERR "es1370: cannot register misc device\n"); | 2734 | printk(KERN_ERR "es1370: cannot register misc device\n"); |
2699 | free_irq(s->irq, s); | 2735 | free_irq(s->irq, s); |
2700 | if (s->gameport) { | ||
2701 | release_region(s->gameport->io, JOY_EXTENT); | ||
2702 | gameport_free_port(s->gameport); | ||
2703 | } | ||
2704 | err_irq: | 2736 | err_irq: |
2705 | release_region(s->io, ES1370_EXTENT); | 2737 | release_region(s->io, ES1370_EXTENT); |
2706 | err_region: | 2738 | err_region: |
@@ -2719,11 +2751,7 @@ static void __devexit es1370_remove(struct pci_dev *dev) | |||
2719 | outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */ | 2751 | outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */ |
2720 | synchronize_irq(s->irq); | 2752 | synchronize_irq(s->irq); |
2721 | free_irq(s->irq, s); | 2753 | free_irq(s->irq, s); |
2722 | if (s->gameport) { | 2754 | es1370_unregister_gameport(s); |
2723 | int gpio = s->gameport->io; | ||
2724 | gameport_unregister_port(s->gameport); | ||
2725 | release_region(gpio, JOY_EXTENT); | ||
2726 | } | ||
2727 | release_region(s->io, ES1370_EXTENT); | 2755 | release_region(s->io, ES1370_EXTENT); |
2728 | unregister_sound_dsp(s->dev_audio); | 2756 | unregister_sound_dsp(s->dev_audio); |
2729 | unregister_sound_mixer(s->dev_mixer); | 2757 | unregister_sound_mixer(s->dev_mixer); |
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c index 9266b777387b..12a56d5ab498 100644 --- a/sound/oss/es1371.c +++ b/sound/oss/es1371.c | |||
@@ -134,6 +134,10 @@ | |||
134 | #include <asm/page.h> | 134 | #include <asm/page.h> |
135 | #include <asm/uaccess.h> | 135 | #include <asm/uaccess.h> |
136 | 136 | ||
137 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
138 | #define SUPPORT_JOYSTICK | ||
139 | #endif | ||
140 | |||
137 | /* --------------------------------------------------------------------- */ | 141 | /* --------------------------------------------------------------------- */ |
138 | 142 | ||
139 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS | 143 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS |
@@ -454,7 +458,10 @@ struct es1371_state { | |||
454 | unsigned char obuf[MIDIOUTBUF]; | 458 | unsigned char obuf[MIDIOUTBUF]; |
455 | } midi; | 459 | } midi; |
456 | 460 | ||
461 | #ifdef SUPPORT_JOYSTICK | ||
457 | struct gameport *gameport; | 462 | struct gameport *gameport; |
463 | #endif | ||
464 | |||
458 | struct semaphore sem; | 465 | struct semaphore sem; |
459 | }; | 466 | }; |
460 | 467 | ||
@@ -2787,12 +2794,63 @@ static struct | |||
2787 | { PCI_ANY_ID, PCI_ANY_ID } | 2794 | { PCI_ANY_ID, PCI_ANY_ID } |
2788 | }; | 2795 | }; |
2789 | 2796 | ||
2797 | #ifdef SUPPORT_JOYSTICK | ||
2798 | |||
2799 | static int __devinit es1371_register_gameport(struct es1371_state *s) | ||
2800 | { | ||
2801 | struct gameport *gp; | ||
2802 | int gpio; | ||
2803 | |||
2804 | for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) | ||
2805 | if (request_region(gpio, JOY_EXTENT, "es1371")) | ||
2806 | break; | ||
2807 | |||
2808 | if (gpio < 0x200) { | ||
2809 | printk(KERN_ERR PFX "no free joystick address found\n"); | ||
2810 | return -EBUSY; | ||
2811 | } | ||
2812 | |||
2813 | s->gameport = gp = gameport_allocate_port(); | ||
2814 | if (!gp) { | ||
2815 | printk(KERN_ERR PFX "can not allocate memory for gameport\n"); | ||
2816 | release_region(gpio, JOY_EXTENT); | ||
2817 | return -ENOMEM; | ||
2818 | } | ||
2819 | |||
2820 | gameport_set_name(gp, "ESS1371 Gameport"); | ||
2821 | gameport_set_phys(gp, "isa%04x/gameport0", gpio); | ||
2822 | gp->dev.parent = &s->dev->dev; | ||
2823 | gp->io = gpio; | ||
2824 | |||
2825 | s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); | ||
2826 | outl(s->ctrl, s->io + ES1371_REG_CONTROL); | ||
2827 | |||
2828 | gameport_register_port(gp); | ||
2829 | |||
2830 | return 0; | ||
2831 | } | ||
2832 | |||
2833 | static inline void es1371_unregister_gameport(struct es1371_state *s) | ||
2834 | { | ||
2835 | if (s->gameport) { | ||
2836 | int gpio = s->gameport->io; | ||
2837 | gameport_unregister_port(s->gameport); | ||
2838 | release_region(gpio, JOY_EXTENT); | ||
2839 | |||
2840 | } | ||
2841 | } | ||
2842 | |||
2843 | #else | ||
2844 | static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; } | ||
2845 | static inline void es1371_unregister_gameport(struct es1371_state *s) { } | ||
2846 | #endif /* SUPPORT_JOYSTICK */ | ||
2847 | |||
2848 | |||
2790 | static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2849 | static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
2791 | { | 2850 | { |
2792 | struct es1371_state *s; | 2851 | struct es1371_state *s; |
2793 | struct gameport *gp; | ||
2794 | mm_segment_t fs; | 2852 | mm_segment_t fs; |
2795 | int i, gpio, val, res = -1; | 2853 | int i, val, res = -1; |
2796 | int idx; | 2854 | int idx; |
2797 | unsigned long tmo; | 2855 | unsigned long tmo; |
2798 | signed long tmo2; | 2856 | signed long tmo2; |
@@ -2883,23 +2941,6 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2883 | } | 2941 | } |
2884 | } | 2942 | } |
2885 | 2943 | ||
2886 | for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) | ||
2887 | if (request_region(gpio, JOY_EXTENT, "es1371")) | ||
2888 | break; | ||
2889 | |||
2890 | if (gpio < 0x200) { | ||
2891 | printk(KERN_ERR PFX "no free joystick address found\n"); | ||
2892 | } else if (!(s->gameport = gp = gameport_allocate_port())) { | ||
2893 | printk(KERN_ERR PFX "can not allocate memory for gameport\n"); | ||
2894 | release_region(gpio, JOY_EXTENT); | ||
2895 | } else { | ||
2896 | gameport_set_name(gp, "ESS1371 Gameport"); | ||
2897 | gameport_set_phys(gp, "isa%04x/gameport0", gpio); | ||
2898 | gp->dev.parent = &s->dev->dev; | ||
2899 | gp->io = gpio; | ||
2900 | s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); | ||
2901 | } | ||
2902 | |||
2903 | s->sctrl = 0; | 2944 | s->sctrl = 0; |
2904 | cssr = 0; | 2945 | cssr = 0; |
2905 | s->spdif_volume = -1; | 2946 | s->spdif_volume = -1; |
@@ -2969,9 +3010,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2969 | /* turn on S/PDIF output driver if requested */ | 3010 | /* turn on S/PDIF output driver if requested */ |
2970 | outl(cssr, s->io+ES1371_REG_STATUS); | 3011 | outl(cssr, s->io+ES1371_REG_STATUS); |
2971 | 3012 | ||
2972 | /* register gameport */ | 3013 | es1371_register_gameport(s); |
2973 | if (s->gameport) | ||
2974 | gameport_register_port(s->gameport); | ||
2975 | 3014 | ||
2976 | /* store it in the driver field */ | 3015 | /* store it in the driver field */ |
2977 | pci_set_drvdata(pcidev, s); | 3016 | pci_set_drvdata(pcidev, s); |
@@ -2980,13 +3019,9 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2980 | /* increment devindex */ | 3019 | /* increment devindex */ |
2981 | if (devindex < NR_DEVICE-1) | 3020 | if (devindex < NR_DEVICE-1) |
2982 | devindex++; | 3021 | devindex++; |
2983 | return 0; | 3022 | return 0; |
2984 | 3023 | ||
2985 | err_gp: | 3024 | err_gp: |
2986 | if (s->gameport) { | ||
2987 | release_region(s->gameport->io, JOY_EXTENT); | ||
2988 | gameport_free_port(s->gameport); | ||
2989 | } | ||
2990 | #ifdef ES1371_DEBUG | 3025 | #ifdef ES1371_DEBUG |
2991 | if (s->ps) | 3026 | if (s->ps) |
2992 | remove_proc_entry("es1371", NULL); | 3027 | remove_proc_entry("es1371", NULL); |
@@ -3025,11 +3060,7 @@ static void __devexit es1371_remove(struct pci_dev *dev) | |||
3025 | outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */ | 3060 | outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */ |
3026 | synchronize_irq(s->irq); | 3061 | synchronize_irq(s->irq); |
3027 | free_irq(s->irq, s); | 3062 | free_irq(s->irq, s); |
3028 | if (s->gameport) { | 3063 | es1371_unregister_gameport(s); |
3029 | int gpio = s->gameport->io; | ||
3030 | gameport_unregister_port(s->gameport); | ||
3031 | release_region(gpio, JOY_EXTENT); | ||
3032 | } | ||
3033 | release_region(s->io, ES1371_EXTENT); | 3064 | release_region(s->io, ES1371_EXTENT); |
3034 | unregister_sound_dsp(s->dev_audio); | 3065 | unregister_sound_dsp(s->dev_audio); |
3035 | unregister_sound_mixer(s->codec->dev_mixer); | 3066 | unregister_sound_mixer(s->codec->dev_mixer); |
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c index fb09065d07c8..a4ecab2f0522 100644 --- a/sound/oss/esssolo1.c +++ b/sound/oss/esssolo1.c | |||
@@ -150,6 +150,10 @@ | |||
150 | 150 | ||
151 | #define FMODE_DMFM 0x10 | 151 | #define FMODE_DMFM 0x10 |
152 | 152 | ||
153 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
154 | #define SUPPORT_JOYSTICK 1 | ||
155 | #endif | ||
156 | |||
153 | static struct pci_driver solo1_driver; | 157 | static struct pci_driver solo1_driver; |
154 | 158 | ||
155 | /* --------------------------------------------------------------------- */ | 159 | /* --------------------------------------------------------------------- */ |
@@ -227,7 +231,9 @@ struct solo1_state { | |||
227 | unsigned char obuf[MIDIOUTBUF]; | 231 | unsigned char obuf[MIDIOUTBUF]; |
228 | } midi; | 232 | } midi; |
229 | 233 | ||
234 | #if SUPPORT_JOYSTICK | ||
230 | struct gameport *gameport; | 235 | struct gameport *gameport; |
236 | #endif | ||
231 | }; | 237 | }; |
232 | 238 | ||
233 | /* --------------------------------------------------------------------- */ | 239 | /* --------------------------------------------------------------------- */ |
@@ -2281,6 +2287,7 @@ solo1_resume(struct pci_dev *pci_dev) { | |||
2281 | return 0; | 2287 | return 0; |
2282 | } | 2288 | } |
2283 | 2289 | ||
2290 | #ifdef SUPPORT_JOYSTICK | ||
2284 | static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) | 2291 | static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) |
2285 | { | 2292 | { |
2286 | struct gameport *gp; | 2293 | struct gameport *gp; |
@@ -2307,6 +2314,19 @@ static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) | |||
2307 | return 0; | 2314 | return 0; |
2308 | } | 2315 | } |
2309 | 2316 | ||
2317 | static inline void solo1_unregister_gameport(struct solo1_state *s) | ||
2318 | { | ||
2319 | if (s->gameport) { | ||
2320 | int gpio = s->gameport->io; | ||
2321 | gameport_unregister_port(s->gameport); | ||
2322 | release_region(gpio, GAMEPORT_EXTENT); | ||
2323 | } | ||
2324 | } | ||
2325 | #else | ||
2326 | static inline int solo1_register_gameport(struct solo1_state *s, int io_port) { return -ENOSYS; } | ||
2327 | static inline void solo1_unregister_gameport(struct solo1_state *s) { } | ||
2328 | #endif /* SUPPORT_JOYSTICK */ | ||
2329 | |||
2310 | static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2330 | static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
2311 | { | 2331 | { |
2312 | struct solo1_state *s; | 2332 | struct solo1_state *s; |
@@ -2438,11 +2458,7 @@ static void __devexit solo1_remove(struct pci_dev *dev) | |||
2438 | synchronize_irq(s->irq); | 2458 | synchronize_irq(s->irq); |
2439 | pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */ | 2459 | pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */ |
2440 | free_irq(s->irq, s); | 2460 | free_irq(s->irq, s); |
2441 | if (s->gameport) { | 2461 | solo1_unregister_gameport(s); |
2442 | int gpio = s->gameport->io; | ||
2443 | gameport_unregister_port(s->gameport); | ||
2444 | release_region(gpio, GAMEPORT_EXTENT); | ||
2445 | } | ||
2446 | release_region(s->iobase, IOBASE_EXTENT); | 2462 | release_region(s->iobase, IOBASE_EXTENT); |
2447 | release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT); | 2463 | release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT); |
2448 | release_region(s->ddmabase, DDMABASE_EXTENT); | 2464 | release_region(s->ddmabase, DDMABASE_EXTENT); |
diff --git a/sound/oss/mad16.c b/sound/oss/mad16.c index a7067f169919..aa3c50db66c4 100644 --- a/sound/oss/mad16.c +++ b/sound/oss/mad16.c | |||
@@ -50,9 +50,12 @@ | |||
50 | #include "sb.h" | 50 | #include "sb.h" |
51 | #include "mpu401.h" | 51 | #include "mpu401.h" |
52 | 52 | ||
53 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
54 | #define SUPPORT_JOYSTICK 1 | ||
55 | #endif | ||
56 | |||
53 | static int mad16_conf; | 57 | static int mad16_conf; |
54 | static int mad16_cdsel; | 58 | static int mad16_cdsel; |
55 | static struct gameport *gameport; | ||
56 | static DEFINE_SPINLOCK(lock); | 59 | static DEFINE_SPINLOCK(lock); |
57 | 60 | ||
58 | #define C928 1 | 61 | #define C928 1 |
@@ -902,6 +905,10 @@ static int __initdata irq_map[16] = | |||
902 | -1, -1, -1, -1 | 905 | -1, -1, -1, -1 |
903 | }; | 906 | }; |
904 | 907 | ||
908 | #ifdef SUPPORT_JOYSTICK | ||
909 | |||
910 | static struct gameport *gameport; | ||
911 | |||
905 | static int __devinit mad16_register_gameport(int io_port) | 912 | static int __devinit mad16_register_gameport(int io_port) |
906 | { | 913 | { |
907 | if (!request_region(io_port, 1, "mad16 gameport")) { | 914 | if (!request_region(io_port, 1, "mad16 gameport")) { |
@@ -925,6 +932,20 @@ static int __devinit mad16_register_gameport(int io_port) | |||
925 | return 0; | 932 | return 0; |
926 | } | 933 | } |
927 | 934 | ||
935 | static inline void mad16_unregister_gameport(void) | ||
936 | { | ||
937 | if (gameport) { | ||
938 | /* the gameport was initialized so we must free it up */ | ||
939 | gameport_unregister_port(gameport); | ||
940 | gameport = NULL; | ||
941 | release_region(0x201, 1); | ||
942 | } | ||
943 | } | ||
944 | #else | ||
945 | static inline int mad16_register_gameport(int io_port) { return -ENOSYS; } | ||
946 | static inline void mad16_unregister_gameport(void) { } | ||
947 | #endif | ||
948 | |||
928 | static int __devinit init_mad16(void) | 949 | static int __devinit init_mad16(void) |
929 | { | 950 | { |
930 | int dmatype = 0; | 951 | int dmatype = 0; |
@@ -1060,12 +1081,7 @@ static void __exit cleanup_mad16(void) | |||
1060 | { | 1081 | { |
1061 | if (found_mpu) | 1082 | if (found_mpu) |
1062 | unload_mad16_mpu(&cfg_mpu); | 1083 | unload_mad16_mpu(&cfg_mpu); |
1063 | if (gameport) { | 1084 | mad16_unregister_gameport(); |
1064 | /* the gameport was initialized so we must free it up */ | ||
1065 | gameport_unregister_port(gameport); | ||
1066 | gameport = NULL; | ||
1067 | release_region(0x201, 1); | ||
1068 | } | ||
1069 | unload_mad16(&cfg); | 1085 | unload_mad16(&cfg); |
1070 | release_region(MC0_PORT, 12); | 1086 | release_region(MC0_PORT, 12); |
1071 | } | 1087 | } |
diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c index 06047e7979af..17d0e461f8d8 100644 --- a/sound/oss/sonicvibes.c +++ b/sound/oss/sonicvibes.c | |||
@@ -122,6 +122,9 @@ | |||
122 | 122 | ||
123 | #include "dm.h" | 123 | #include "dm.h" |
124 | 124 | ||
125 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
126 | #define SUPPORT_JOYSTICK 1 | ||
127 | #endif | ||
125 | 128 | ||
126 | /* --------------------------------------------------------------------- */ | 129 | /* --------------------------------------------------------------------- */ |
127 | 130 | ||
@@ -365,7 +368,9 @@ struct sv_state { | |||
365 | unsigned char obuf[MIDIOUTBUF]; | 368 | unsigned char obuf[MIDIOUTBUF]; |
366 | } midi; | 369 | } midi; |
367 | 370 | ||
371 | #if SUPPORT_JOYSTICK | ||
368 | struct gameport *gameport; | 372 | struct gameport *gameport; |
373 | #endif | ||
369 | }; | 374 | }; |
370 | 375 | ||
371 | /* --------------------------------------------------------------------- */ | 376 | /* --------------------------------------------------------------------- */ |
@@ -2485,6 +2490,7 @@ static struct initvol { | |||
2485 | #define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ | 2490 | #define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ |
2486 | (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) | 2491 | (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) |
2487 | 2492 | ||
2493 | #ifdef SUPPORT_JOYSTICK | ||
2488 | static int __devinit sv_register_gameport(struct sv_state *s, int io_port) | 2494 | static int __devinit sv_register_gameport(struct sv_state *s, int io_port) |
2489 | { | 2495 | { |
2490 | struct gameport *gp; | 2496 | struct gameport *gp; |
@@ -2511,6 +2517,19 @@ static int __devinit sv_register_gameport(struct sv_state *s, int io_port) | |||
2511 | return 0; | 2517 | return 0; |
2512 | } | 2518 | } |
2513 | 2519 | ||
2520 | static inline void sv_unregister_gameport(struct sv_state *s) | ||
2521 | { | ||
2522 | if (s->gameport) { | ||
2523 | int gpio = s->gameport->io; | ||
2524 | gameport_unregister_port(s->gameport); | ||
2525 | release_region(gpio, SV_EXTENT_GAME); | ||
2526 | } | ||
2527 | } | ||
2528 | #else | ||
2529 | static inline int sv_register_gameport(struct sv_state *s, int io_port) { return -ENOSYS; } | ||
2530 | static inline void sv_unregister_gameport(struct sv_state *s) { } | ||
2531 | #endif /* SUPPORT_JOYSTICK */ | ||
2532 | |||
2514 | static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2533 | static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
2515 | { | 2534 | { |
2516 | static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller"; | 2535 | static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller"; |
@@ -2711,11 +2730,7 @@ static void __devexit sv_remove(struct pci_dev *dev) | |||
2711 | /*outb(0, s->iodmaa + SV_DMA_RESET);*/ | 2730 | /*outb(0, s->iodmaa + SV_DMA_RESET);*/ |
2712 | /*outb(0, s->iodmac + SV_DMA_RESET);*/ | 2731 | /*outb(0, s->iodmac + SV_DMA_RESET);*/ |
2713 | free_irq(s->irq, s); | 2732 | free_irq(s->irq, s); |
2714 | if (s->gameport) { | 2733 | sv_unregister_gameport(s); |
2715 | int gpio = s->gameport->io; | ||
2716 | gameport_unregister_port(s->gameport); | ||
2717 | release_region(gpio, SV_EXTENT_GAME); | ||
2718 | } | ||
2719 | release_region(s->iodmac, SV_EXTENT_DMA); | 2734 | release_region(s->iodmac, SV_EXTENT_DMA); |
2720 | release_region(s->iodmaa, SV_EXTENT_DMA); | 2735 | release_region(s->iodmaa, SV_EXTENT_DMA); |
2721 | release_region(s->ioenh, SV_EXTENT_ENH); | 2736 | release_region(s->ioenh, SV_EXTENT_ENH); |
diff --git a/sound/oss/trident.c b/sound/oss/trident.c index 47537f0a5b05..5f0ad6bb43b9 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c | |||
@@ -228,6 +228,10 @@ | |||
228 | 228 | ||
229 | #define DRIVER_VERSION "0.14.10j-2.6" | 229 | #define DRIVER_VERSION "0.14.10j-2.6" |
230 | 230 | ||
231 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
232 | #define SUPPORT_JOYSTICK 1 | ||
233 | #endif | ||
234 | |||
231 | /* magic numbers to protect our data structures */ | 235 | /* magic numbers to protect our data structures */ |
232 | #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ | 236 | #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ |
233 | #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ | 237 | #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ |
@@ -4252,24 +4256,25 @@ trident_ac97_init(struct trident_card *card) | |||
4252 | return num_ac97 + 1; | 4256 | return num_ac97 + 1; |
4253 | } | 4257 | } |
4254 | 4258 | ||
4259 | #ifdef SUPPORT_JOYSTICK | ||
4255 | /* Gameport functions for the cards ADC gameport */ | 4260 | /* Gameport functions for the cards ADC gameport */ |
4256 | 4261 | ||
4257 | static unsigned char | 4262 | static unsigned char trident_game_read(struct gameport *gameport) |
4258 | trident_game_read(struct gameport *gameport) | ||
4259 | { | 4263 | { |
4260 | struct trident_card *card = gameport->port_data; | 4264 | struct trident_card *card = gameport->port_data; |
4265 | |||
4261 | return inb(TRID_REG(card, T4D_GAME_LEG)); | 4266 | return inb(TRID_REG(card, T4D_GAME_LEG)); |
4262 | } | 4267 | } |
4263 | 4268 | ||
4264 | static void | 4269 | static void trident_game_trigger(struct gameport *gameport) |
4265 | trident_game_trigger(struct gameport *gameport) | ||
4266 | { | 4270 | { |
4267 | struct trident_card *card = gameport->port_data; | 4271 | struct trident_card *card = gameport->port_data; |
4272 | |||
4268 | outb(0xff, TRID_REG(card, T4D_GAME_LEG)); | 4273 | outb(0xff, TRID_REG(card, T4D_GAME_LEG)); |
4269 | } | 4274 | } |
4270 | 4275 | ||
4271 | static int | 4276 | static int trident_game_cooked_read(struct gameport *gameport, |
4272 | trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) | 4277 | int *axes, int *buttons) |
4273 | { | 4278 | { |
4274 | struct trident_card *card = gameport->port_data; | 4279 | struct trident_card *card = gameport->port_data; |
4275 | int i; | 4280 | int i; |
@@ -4285,8 +4290,7 @@ trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) | |||
4285 | return 0; | 4290 | return 0; |
4286 | } | 4291 | } |
4287 | 4292 | ||
4288 | static int | 4293 | static int trident_game_open(struct gameport *gameport, int mode) |
4289 | trident_game_open(struct gameport *gameport, int mode) | ||
4290 | { | 4294 | { |
4291 | struct trident_card *card = gameport->port_data; | 4295 | struct trident_card *card = gameport->port_data; |
4292 | 4296 | ||
@@ -4305,8 +4309,7 @@ trident_game_open(struct gameport *gameport, int mode) | |||
4305 | return 0; | 4309 | return 0; |
4306 | } | 4310 | } |
4307 | 4311 | ||
4308 | static int __devinit | 4312 | static int __devinit trident_register_gameport(struct trident_card *card) |
4309 | trident_register_gameport(struct trident_card *card) | ||
4310 | { | 4313 | { |
4311 | struct gameport *gp; | 4314 | struct gameport *gp; |
4312 | 4315 | ||
@@ -4330,6 +4333,17 @@ trident_register_gameport(struct trident_card *card) | |||
4330 | return 0; | 4333 | return 0; |
4331 | } | 4334 | } |
4332 | 4335 | ||
4336 | static inline void trident_unregister_gameport(struct trident_card *card) | ||
4337 | { | ||
4338 | if (card->gameport) | ||
4339 | gameport_unregister_port(card->gameport); | ||
4340 | } | ||
4341 | |||
4342 | #else | ||
4343 | static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; } | ||
4344 | static inline void trident_unregister_gameport(struct trident_card *card) { } | ||
4345 | #endif /* SUPPORT_JOYSTICK */ | ||
4346 | |||
4333 | /* install the driver, we do not allocate hardware channel nor DMA buffer */ | 4347 | /* install the driver, we do not allocate hardware channel nor DMA buffer */ |
4334 | /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ | 4348 | /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ |
4335 | /* open/read/write/ioctl/mmap) */ | 4349 | /* open/read/write/ioctl/mmap) */ |
@@ -4569,8 +4583,7 @@ trident_remove(struct pci_dev *pci_dev) | |||
4569 | } | 4583 | } |
4570 | 4584 | ||
4571 | /* Unregister gameport */ | 4585 | /* Unregister gameport */ |
4572 | if (card->gameport) | 4586 | trident_unregister_gameport(card); |
4573 | gameport_unregister_port(card->gameport); | ||
4574 | 4587 | ||
4575 | /* Kill interrupts, and SP/DIF */ | 4588 | /* Kill interrupts, and SP/DIF */ |
4576 | trident_disable_loop_interrupts(card); | 4589 | trident_disable_loop_interrupts(card); |
diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c index b387e1e52485..83edda93f0b4 100644 --- a/sound/oss/via82cxxx_audio.c +++ b/sound/oss/via82cxxx_audio.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/smp_lock.h> | 35 | #include <linux/smp_lock.h> |
36 | #include <linux/ioport.h> | 36 | #include <linux/ioport.h> |
37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
38 | #include <linux/dma-mapping.h> | ||
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/semaphore.h> | 41 | #include <asm/semaphore.h> |
@@ -3391,10 +3392,10 @@ static int __devinit via_init_one (struct pci_dev *pdev, const struct pci_device | |||
3391 | if (rc) | 3392 | if (rc) |
3392 | goto err_out_disable; | 3393 | goto err_out_disable; |
3393 | 3394 | ||
3394 | rc = pci_set_dma_mask(pdev, 0xffffffffULL); | 3395 | rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
3395 | if (rc) | 3396 | if (rc) |
3396 | goto err_out_res; | 3397 | goto err_out_res; |
3397 | rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL); | 3398 | rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); |
3398 | if (rc) | 3399 | if (rc) |
3399 | goto err_out_res; | 3400 | goto err_out_res; |
3400 | 3401 | ||
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index b6e1854e9389..eb3c52b03af3 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -1338,11 +1338,6 @@ static inline int snd_cs4281_create_gameport(cs4281_t *chip) { return -ENOSYS; } | |||
1338 | static inline void snd_cs4281_free_gameport(cs4281_t *chip) { } | 1338 | static inline void snd_cs4281_free_gameport(cs4281_t *chip) { } |
1339 | #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ | 1339 | #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ |
1340 | 1340 | ||
1341 | |||
1342 | /* | ||
1343 | |||
1344 | */ | ||
1345 | |||
1346 | static int snd_cs4281_free(cs4281_t *chip) | 1341 | static int snd_cs4281_free(cs4281_t *chip) |
1347 | { | 1342 | { |
1348 | snd_cs4281_free_gameport(chip); | 1343 | snd_cs4281_free_gameport(chip); |
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index e052bd071e5b..061e52d3d771 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c | |||
@@ -90,7 +90,7 @@ snd_pmac_awacs_write_noreg(pmac_t *chip, int reg, int val) | |||
90 | snd_pmac_awacs_write(chip, val | (reg << 12)); | 90 | snd_pmac_awacs_write(chip, val | (reg << 12)); |
91 | } | 91 | } |
92 | 92 | ||
93 | #ifdef CONFIG_PMAC_PBOOK | 93 | #ifdef CONFIG_PM |
94 | /* Recalibrate chip */ | 94 | /* Recalibrate chip */ |
95 | static void screamer_recalibrate(pmac_t *chip) | 95 | static void screamer_recalibrate(pmac_t *chip) |
96 | { | 96 | { |
@@ -642,7 +642,7 @@ static void awacs_restore_all_regs(pmac_t *chip) | |||
642 | } | 642 | } |
643 | } | 643 | } |
644 | 644 | ||
645 | #ifdef CONFIG_PMAC_PBOOK | 645 | #ifdef CONFIG_PM |
646 | static void snd_pmac_awacs_suspend(pmac_t *chip) | 646 | static void snd_pmac_awacs_suspend(pmac_t *chip) |
647 | { | 647 | { |
648 | snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1] | 648 | snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1] |
@@ -676,7 +676,7 @@ static void snd_pmac_awacs_resume(pmac_t *chip) | |||
676 | } | 676 | } |
677 | #endif | 677 | #endif |
678 | } | 678 | } |
679 | #endif /* CONFIG_PMAC_PBOOK */ | 679 | #endif /* CONFIG_PM */ |
680 | 680 | ||
681 | #ifdef PMAC_SUPPORT_AUTOMUTE | 681 | #ifdef PMAC_SUPPORT_AUTOMUTE |
682 | /* | 682 | /* |
@@ -883,7 +883,7 @@ snd_pmac_awacs_init(pmac_t *chip) | |||
883 | * set lowlevel callbacks | 883 | * set lowlevel callbacks |
884 | */ | 884 | */ |
885 | chip->set_format = snd_pmac_awacs_set_format; | 885 | chip->set_format = snd_pmac_awacs_set_format; |
886 | #ifdef CONFIG_PMAC_PBOOK | 886 | #ifdef CONFIG_PM |
887 | chip->suspend = snd_pmac_awacs_suspend; | 887 | chip->suspend = snd_pmac_awacs_suspend; |
888 | chip->resume = snd_pmac_awacs_resume; | 888 | chip->resume = snd_pmac_awacs_resume; |
889 | #endif | 889 | #endif |
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index f24a91693616..a737f298e77d 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c | |||
@@ -218,7 +218,7 @@ static snd_kcontrol_new_t daca_mixers[] = { | |||
218 | }; | 218 | }; |
219 | 219 | ||
220 | 220 | ||
221 | #ifdef CONFIG_PMAC_PBOOK | 221 | #ifdef CONFIG_PM |
222 | static void daca_resume(pmac_t *chip) | 222 | static void daca_resume(pmac_t *chip) |
223 | { | 223 | { |
224 | pmac_daca_t *mix = chip->mixer_data; | 224 | pmac_daca_t *mix = chip->mixer_data; |
@@ -227,7 +227,7 @@ static void daca_resume(pmac_t *chip) | |||
227 | mix->amp_on ? 0x05 : 0x04); | 227 | mix->amp_on ? 0x05 : 0x04); |
228 | daca_set_volume(mix); | 228 | daca_set_volume(mix); |
229 | } | 229 | } |
230 | #endif /* CONFIG_PMAC_PBOOK */ | 230 | #endif /* CONFIG_PM */ |
231 | 231 | ||
232 | 232 | ||
233 | static void daca_cleanup(pmac_t *chip) | 233 | static void daca_cleanup(pmac_t *chip) |
@@ -275,7 +275,7 @@ int __init snd_pmac_daca_init(pmac_t *chip) | |||
275 | return err; | 275 | return err; |
276 | } | 276 | } |
277 | 277 | ||
278 | #ifdef CONFIG_PMAC_PBOOK | 278 | #ifdef CONFIG_PM |
279 | chip->resume = daca_resume; | 279 | chip->resume = daca_resume; |
280 | #endif | 280 | #endif |
281 | 281 | ||
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 080ef3928465..75b8b7423036 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <asm/pci-bridge.h> | 36 | #include <asm/pci-bridge.h> |
37 | 37 | ||
38 | 38 | ||
39 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | 39 | #ifdef CONFIG_PM |
40 | static int snd_pmac_register_sleep_notifier(pmac_t *chip); | 40 | static int snd_pmac_register_sleep_notifier(pmac_t *chip); |
41 | static int snd_pmac_unregister_sleep_notifier(pmac_t *chip); | 41 | static int snd_pmac_unregister_sleep_notifier(pmac_t *chip); |
42 | static int snd_pmac_suspend(snd_card_t *card, pm_message_t state); | 42 | static int snd_pmac_suspend(snd_card_t *card, pm_message_t state); |
@@ -782,7 +782,7 @@ static int snd_pmac_free(pmac_t *chip) | |||
782 | } | 782 | } |
783 | 783 | ||
784 | snd_pmac_sound_feature(chip, 0); | 784 | snd_pmac_sound_feature(chip, 0); |
785 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | 785 | #ifdef CONFIG_PM |
786 | snd_pmac_unregister_sleep_notifier(chip); | 786 | snd_pmac_unregister_sleep_notifier(chip); |
787 | #endif | 787 | #endif |
788 | 788 | ||
@@ -1292,7 +1292,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) | |||
1292 | /* Reset dbdma channels */ | 1292 | /* Reset dbdma channels */ |
1293 | snd_pmac_dbdma_reset(chip); | 1293 | snd_pmac_dbdma_reset(chip); |
1294 | 1294 | ||
1295 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | 1295 | #ifdef CONFIG_PM |
1296 | /* add sleep notifier */ | 1296 | /* add sleep notifier */ |
1297 | if (! snd_pmac_register_sleep_notifier(chip)) | 1297 | if (! snd_pmac_register_sleep_notifier(chip)) |
1298 | snd_card_set_pm_callback(chip->card, snd_pmac_suspend, snd_pmac_resume, chip); | 1298 | snd_card_set_pm_callback(chip->card, snd_pmac_suspend, snd_pmac_resume, chip); |
@@ -1316,7 +1316,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) | |||
1316 | * sleep notify for powerbook | 1316 | * sleep notify for powerbook |
1317 | */ | 1317 | */ |
1318 | 1318 | ||
1319 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | 1319 | #ifdef CONFIG_PM |
1320 | 1320 | ||
1321 | /* | 1321 | /* |
1322 | * Save state when going to sleep, restore it afterwards. | 1322 | * Save state when going to sleep, restore it afterwards. |
@@ -1414,4 +1414,5 @@ static int snd_pmac_unregister_sleep_notifier(pmac_t *chip) | |||
1414 | return 0; | 1414 | return 0; |
1415 | } | 1415 | } |
1416 | 1416 | ||
1417 | #endif /* CONFIG_PM && CONFIG_PMAC_PBOOK */ | 1417 | #endif /* CONFIG_PM */ |
1418 | |||
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index 0a84c05f714b..582db5220119 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h | |||
@@ -167,7 +167,7 @@ struct snd_pmac { | |||
167 | void (*set_format)(pmac_t *chip); | 167 | void (*set_format)(pmac_t *chip); |
168 | void (*update_automute)(pmac_t *chip, int do_notify); | 168 | void (*update_automute)(pmac_t *chip, int do_notify); |
169 | int (*detect_headphone)(pmac_t *chip); | 169 | int (*detect_headphone)(pmac_t *chip); |
170 | #ifdef CONFIG_PMAC_PBOOK | 170 | #ifdef CONFIG_PM |
171 | void (*suspend)(pmac_t *chip); | 171 | void (*suspend)(pmac_t *chip); |
172 | void (*resume)(pmac_t *chip); | 172 | void (*resume)(pmac_t *chip); |
173 | #endif | 173 | #endif |
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 9332237cb6a4..36c5d5d45bb1 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -1128,7 +1128,7 @@ static void tumbler_reset_audio(pmac_t *chip) | |||
1128 | } | 1128 | } |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | #ifdef CONFIG_PMAC_PBOOK | 1131 | #ifdef CONFIG_PM |
1132 | /* suspend mixer */ | 1132 | /* suspend mixer */ |
1133 | static void tumbler_suspend(pmac_t *chip) | 1133 | static void tumbler_suspend(pmac_t *chip) |
1134 | { | 1134 | { |
@@ -1370,7 +1370,7 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) | |||
1370 | if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) | 1370 | if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) |
1371 | return err; | 1371 | return err; |
1372 | 1372 | ||
1373 | #ifdef CONFIG_PMAC_PBOOK | 1373 | #ifdef CONFIG_PM |
1374 | chip->suspend = tumbler_suspend; | 1374 | chip->suspend = tumbler_suspend; |
1375 | chip->resume = tumbler_resume; | 1375 | chip->resume = tumbler_resume; |
1376 | #endif | 1376 | #endif |