diff options
229 files changed, 10027 insertions, 9710 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/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/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/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/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/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/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 b1078baa1d5e..aabcdc2be05e 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 <asm/uaccess.h> | 97 | #include <asm/uaccess.h> |
468 | #include <asm/io.h> | 98 | #include <asm/io.h> |
@@ -496,6 +126,10 @@ static int ignore_disconnect; /* = 0 */ | |||
496 | module_param(ignore_disconnect, int, 0644); | 126 | module_param(ignore_disconnect, int, 0644); |
497 | MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer"); | 127 | MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer"); |
498 | 128 | ||
129 | static int force_monitor; /* = 0 */ | ||
130 | module_param(force_monitor, int, 0644); | ||
131 | MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); | ||
132 | |||
499 | /********************************************************************/ | 133 | /********************************************************************/ |
500 | /* Compile time configuration and compatibility stuff */ | 134 | /* Compile time configuration and compatibility stuff */ |
501 | /********************************************************************/ | 135 | /********************************************************************/ |
@@ -511,6 +145,10 @@ MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer | |||
511 | /* Internal constants */ | 145 | /* Internal constants */ |
512 | /********************************************************************/ | 146 | /********************************************************************/ |
513 | 147 | ||
148 | /* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ | ||
149 | static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | ||
150 | #define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) | ||
151 | |||
514 | #define ORINOCO_MIN_MTU 256 | 152 | #define ORINOCO_MIN_MTU 256 |
515 | #define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD) | 153 | #define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD) |
516 | 154 | ||
@@ -537,6 +175,11 @@ MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer | |||
537 | | HERMES_EV_WTERR | HERMES_EV_INFO \ | 175 | | HERMES_EV_WTERR | HERMES_EV_INFO \ |
538 | | HERMES_EV_INFDROP ) | 176 | | HERMES_EV_INFDROP ) |
539 | 177 | ||
178 | #define MAX_RID_LEN 1024 | ||
179 | |||
180 | static const struct iw_handler_def orinoco_handler_def; | ||
181 | static struct ethtool_ops orinoco_ethtool_ops; | ||
182 | |||
540 | /********************************************************************/ | 183 | /********************************************************************/ |
541 | /* Data tables */ | 184 | /* Data tables */ |
542 | /********************************************************************/ | 185 | /********************************************************************/ |
@@ -571,26 +214,45 @@ static struct { | |||
571 | /* Data types */ | 214 | /* Data types */ |
572 | /********************************************************************/ | 215 | /********************************************************************/ |
573 | 216 | ||
574 | struct header_struct { | 217 | /* Used in Event handling. |
575 | /* 802.3 */ | 218 | * We avoid nested structres as they break on ARM -- Moustafa */ |
576 | u8 dest[ETH_ALEN]; | 219 | struct hermes_tx_descriptor_802_11 { |
577 | u8 src[ETH_ALEN]; | 220 | /* hermes_tx_descriptor */ |
578 | u16 len; | 221 | u16 status; |
579 | /* 802.2 */ | 222 | u16 reserved1; |
223 | u16 reserved2; | ||
224 | u32 sw_support; | ||
225 | u8 retry_count; | ||
226 | u8 tx_rate; | ||
227 | u16 tx_control; | ||
228 | |||
229 | /* ieee802_11_hdr */ | ||
230 | u16 frame_ctl; | ||
231 | u16 duration_id; | ||
232 | u8 addr1[ETH_ALEN]; | ||
233 | u8 addr2[ETH_ALEN]; | ||
234 | u8 addr3[ETH_ALEN]; | ||
235 | u16 seq_ctl; | ||
236 | u8 addr4[ETH_ALEN]; | ||
237 | u16 data_len; | ||
238 | |||
239 | /* ethhdr */ | ||
240 | unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ | ||
241 | unsigned char h_source[ETH_ALEN]; /* source ether addr */ | ||
242 | unsigned short h_proto; /* packet type ID field */ | ||
243 | |||
244 | /* p8022_hdr */ | ||
580 | u8 dsap; | 245 | u8 dsap; |
581 | u8 ssap; | 246 | u8 ssap; |
582 | u8 ctrl; | 247 | u8 ctrl; |
583 | /* SNAP */ | ||
584 | u8 oui[3]; | 248 | u8 oui[3]; |
249 | |||
585 | u16 ethertype; | 250 | u16 ethertype; |
586 | } __attribute__ ((packed)); | 251 | } __attribute__ ((packed)); |
587 | 252 | ||
588 | /* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ | 253 | /* Rx frame header except compatibility 802.3 header */ |
589 | u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | ||
590 | |||
591 | #define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) | ||
592 | |||
593 | struct hermes_rx_descriptor { | 254 | struct hermes_rx_descriptor { |
255 | /* Control */ | ||
594 | u16 status; | 256 | u16 status; |
595 | u32 time; | 257 | u32 time; |
596 | u8 silence; | 258 | u8 silence; |
@@ -598,13 +260,24 @@ struct hermes_rx_descriptor { | |||
598 | u8 rate; | 260 | u8 rate; |
599 | u8 rxflow; | 261 | u8 rxflow; |
600 | u32 reserved; | 262 | u32 reserved; |
263 | |||
264 | /* 802.11 header */ | ||
265 | u16 frame_ctl; | ||
266 | u16 duration_id; | ||
267 | u8 addr1[ETH_ALEN]; | ||
268 | u8 addr2[ETH_ALEN]; | ||
269 | u8 addr3[ETH_ALEN]; | ||
270 | u16 seq_ctl; | ||
271 | u8 addr4[ETH_ALEN]; | ||
272 | |||
273 | /* Data length */ | ||
274 | u16 data_len; | ||
601 | } __attribute__ ((packed)); | 275 | } __attribute__ ((packed)); |
602 | 276 | ||
603 | /********************************************************************/ | 277 | /********************************************************************/ |
604 | /* Function prototypes */ | 278 | /* Function prototypes */ |
605 | /********************************************************************/ | 279 | /********************************************************************/ |
606 | 280 | ||
607 | static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
608 | static int __orinoco_program_rids(struct net_device *dev); | 281 | static int __orinoco_program_rids(struct net_device *dev); |
609 | static void __orinoco_set_multicast_list(struct net_device *dev); | 282 | static void __orinoco_set_multicast_list(struct net_device *dev); |
610 | 283 | ||
@@ -628,6 +301,10 @@ static inline void set_port_type(struct orinoco_private *priv) | |||
628 | priv->createibss = 1; | 301 | priv->createibss = 1; |
629 | } | 302 | } |
630 | break; | 303 | break; |
304 | case IW_MODE_MONITOR: | ||
305 | priv->port_type = 3; | ||
306 | priv->createibss = 0; | ||
307 | break; | ||
631 | default: | 308 | default: |
632 | printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", | 309 | printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", |
633 | priv->ndev->name); | 310 | priv->ndev->name); |
@@ -814,7 +491,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
814 | return 1; | 491 | return 1; |
815 | } | 492 | } |
816 | 493 | ||
817 | if (! netif_carrier_ok(dev)) { | 494 | if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) { |
818 | /* Oops, the firmware hasn't established a connection, | 495 | /* Oops, the firmware hasn't established a connection, |
819 | silently drop the packet (this seems to be the | 496 | silently drop the packet (this seems to be the |
820 | safest approach). */ | 497 | safest approach). */ |
@@ -951,26 +628,55 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) | |||
951 | struct orinoco_private *priv = netdev_priv(dev); | 628 | struct orinoco_private *priv = netdev_priv(dev); |
952 | struct net_device_stats *stats = &priv->stats; | 629 | struct net_device_stats *stats = &priv->stats; |
953 | u16 fid = hermes_read_regn(hw, TXCOMPLFID); | 630 | u16 fid = hermes_read_regn(hw, TXCOMPLFID); |
954 | struct hermes_tx_descriptor desc; | 631 | struct hermes_tx_descriptor_802_11 hdr; |
955 | int err = 0; | 632 | int err = 0; |
956 | 633 | ||
957 | if (fid == DUMMY_FID) | 634 | if (fid == DUMMY_FID) |
958 | return; /* Nothing's really happened */ | 635 | return; /* Nothing's really happened */ |
959 | 636 | ||
960 | err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0); | 637 | /* Read the frame header */ |
638 | err = hermes_bap_pread(hw, IRQ_BAP, &hdr, | ||
639 | sizeof(struct hermes_tx_descriptor) + | ||
640 | sizeof(struct ieee80211_hdr), | ||
641 | fid, 0); | ||
642 | |||
643 | hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); | ||
644 | stats->tx_errors++; | ||
645 | |||
961 | if (err) { | 646 | if (err) { |
962 | printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " | 647 | printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " |
963 | "(FID=%04X error %d)\n", | 648 | "(FID=%04X error %d)\n", |
964 | dev->name, fid, err); | 649 | dev->name, fid, err); |
965 | } else { | 650 | return; |
966 | DEBUG(1, "%s: Tx error, status %d\n", | ||
967 | dev->name, le16_to_cpu(desc.status)); | ||
968 | } | 651 | } |
969 | 652 | ||
970 | stats->tx_errors++; | 653 | DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name, |
654 | err, fid); | ||
655 | |||
656 | /* We produce a TXDROP event only for retry or lifetime | ||
657 | * exceeded, because that's the only status that really mean | ||
658 | * that this particular node went away. | ||
659 | * Other errors means that *we* screwed up. - Jean II */ | ||
660 | hdr.status = le16_to_cpu(hdr.status); | ||
661 | if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { | ||
662 | union iwreq_data wrqu; | ||
663 | |||
664 | /* Copy 802.11 dest address. | ||
665 | * We use the 802.11 header because the frame may | ||
666 | * not be 802.3 or may be mangled... | ||
667 | * In Ad-Hoc mode, it will be the node address. | ||
668 | * In managed mode, it will be most likely the AP addr | ||
669 | * User space will figure out how to convert it to | ||
670 | * whatever it needs (IP address or else). | ||
671 | * - Jean II */ | ||
672 | memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN); | ||
673 | wrqu.addr.sa_family = ARPHRD_ETHER; | ||
674 | |||
675 | /* Send event to user space */ | ||
676 | wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL); | ||
677 | } | ||
971 | 678 | ||
972 | netif_wake_queue(dev); | 679 | netif_wake_queue(dev); |
973 | hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); | ||
974 | } | 680 | } |
975 | 681 | ||
976 | static void orinoco_tx_timeout(struct net_device *dev) | 682 | static void orinoco_tx_timeout(struct net_device *dev) |
@@ -1047,18 +753,127 @@ static void orinoco_stat_gather(struct net_device *dev, | |||
1047 | } | 753 | } |
1048 | } | 754 | } |
1049 | 755 | ||
756 | /* | ||
757 | * orinoco_rx_monitor - handle received monitor frames. | ||
758 | * | ||
759 | * Arguments: | ||
760 | * dev network device | ||
761 | * rxfid received FID | ||
762 | * desc rx descriptor of the frame | ||
763 | * | ||
764 | * Call context: interrupt | ||
765 | */ | ||
766 | static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, | ||
767 | struct hermes_rx_descriptor *desc) | ||
768 | { | ||
769 | u32 hdrlen = 30; /* return full header by default */ | ||
770 | u32 datalen = 0; | ||
771 | u16 fc; | ||
772 | int err; | ||
773 | int len; | ||
774 | struct sk_buff *skb; | ||
775 | struct orinoco_private *priv = netdev_priv(dev); | ||
776 | struct net_device_stats *stats = &priv->stats; | ||
777 | hermes_t *hw = &priv->hw; | ||
778 | |||
779 | len = le16_to_cpu(desc->data_len); | ||
780 | |||
781 | /* Determine the size of the header and the data */ | ||
782 | fc = le16_to_cpu(desc->frame_ctl); | ||
783 | switch (fc & IEEE80211_FCTL_FTYPE) { | ||
784 | case IEEE80211_FTYPE_DATA: | ||
785 | if ((fc & IEEE80211_FCTL_TODS) | ||
786 | && (fc & IEEE80211_FCTL_FROMDS)) | ||
787 | hdrlen = 30; | ||
788 | else | ||
789 | hdrlen = 24; | ||
790 | datalen = len; | ||
791 | break; | ||
792 | case IEEE80211_FTYPE_MGMT: | ||
793 | hdrlen = 24; | ||
794 | datalen = len; | ||
795 | break; | ||
796 | case IEEE80211_FTYPE_CTL: | ||
797 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
798 | case IEEE80211_STYPE_PSPOLL: | ||
799 | case IEEE80211_STYPE_RTS: | ||
800 | case IEEE80211_STYPE_CFEND: | ||
801 | case IEEE80211_STYPE_CFENDACK: | ||
802 | hdrlen = 16; | ||
803 | break; | ||
804 | case IEEE80211_STYPE_CTS: | ||
805 | case IEEE80211_STYPE_ACK: | ||
806 | hdrlen = 10; | ||
807 | break; | ||
808 | } | ||
809 | break; | ||
810 | default: | ||
811 | /* Unknown frame type */ | ||
812 | break; | ||
813 | } | ||
814 | |||
815 | /* sanity check the length */ | ||
816 | if (datalen > IEEE80211_DATA_LEN + 12) { | ||
817 | printk(KERN_DEBUG "%s: oversized monitor frame, " | ||
818 | "data length = %d\n", dev->name, datalen); | ||
819 | err = -EIO; | ||
820 | stats->rx_length_errors++; | ||
821 | goto update_stats; | ||
822 | } | ||
823 | |||
824 | skb = dev_alloc_skb(hdrlen + datalen); | ||
825 | if (!skb) { | ||
826 | printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n", | ||
827 | dev->name); | ||
828 | err = -ENOMEM; | ||
829 | goto drop; | ||
830 | } | ||
831 | |||
832 | /* Copy the 802.11 header to the skb */ | ||
833 | memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen); | ||
834 | skb->mac.raw = skb->data; | ||
835 | |||
836 | /* If any, copy the data from the card to the skb */ | ||
837 | if (datalen > 0) { | ||
838 | err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), | ||
839 | ALIGN(datalen, 2), rxfid, | ||
840 | HERMES_802_2_OFFSET); | ||
841 | if (err) { | ||
842 | printk(KERN_ERR "%s: error %d reading monitor frame\n", | ||
843 | dev->name, err); | ||
844 | goto drop; | ||
845 | } | ||
846 | } | ||
847 | |||
848 | skb->dev = dev; | ||
849 | skb->ip_summed = CHECKSUM_NONE; | ||
850 | skb->pkt_type = PACKET_OTHERHOST; | ||
851 | skb->protocol = __constant_htons(ETH_P_802_2); | ||
852 | |||
853 | dev->last_rx = jiffies; | ||
854 | stats->rx_packets++; | ||
855 | stats->rx_bytes += skb->len; | ||
856 | |||
857 | netif_rx(skb); | ||
858 | return; | ||
859 | |||
860 | drop: | ||
861 | dev_kfree_skb_irq(skb); | ||
862 | update_stats: | ||
863 | stats->rx_errors++; | ||
864 | stats->rx_dropped++; | ||
865 | } | ||
866 | |||
1050 | static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) | 867 | static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) |
1051 | { | 868 | { |
1052 | struct orinoco_private *priv = netdev_priv(dev); | 869 | struct orinoco_private *priv = netdev_priv(dev); |
1053 | struct net_device_stats *stats = &priv->stats; | 870 | struct net_device_stats *stats = &priv->stats; |
1054 | struct iw_statistics *wstats = &priv->wstats; | 871 | struct iw_statistics *wstats = &priv->wstats; |
1055 | struct sk_buff *skb = NULL; | 872 | struct sk_buff *skb = NULL; |
1056 | u16 rxfid, status; | 873 | u16 rxfid, status, fc; |
1057 | int length, data_len, data_off; | 874 | int length; |
1058 | char *p; | ||
1059 | struct hermes_rx_descriptor desc; | 875 | struct hermes_rx_descriptor desc; |
1060 | struct header_struct hdr; | 876 | struct ethhdr *hdr; |
1061 | struct ethhdr *eh; | ||
1062 | int err; | 877 | int err; |
1063 | 878 | ||
1064 | rxfid = hermes_read_regn(hw, RXFID); | 879 | rxfid = hermes_read_regn(hw, RXFID); |
@@ -1068,53 +883,46 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) | |||
1068 | if (err) { | 883 | if (err) { |
1069 | printk(KERN_ERR "%s: error %d reading Rx descriptor. " | 884 | printk(KERN_ERR "%s: error %d reading Rx descriptor. " |
1070 | "Frame dropped.\n", dev->name, err); | 885 | "Frame dropped.\n", dev->name, err); |
1071 | stats->rx_errors++; | 886 | goto update_stats; |
1072 | goto drop; | ||
1073 | } | 887 | } |
1074 | 888 | ||
1075 | status = le16_to_cpu(desc.status); | 889 | status = le16_to_cpu(desc.status); |
1076 | 890 | ||
1077 | if (status & HERMES_RXSTAT_ERR) { | 891 | if (status & HERMES_RXSTAT_BADCRC) { |
1078 | if (status & HERMES_RXSTAT_UNDECRYPTABLE) { | 892 | DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", |
1079 | wstats->discard.code++; | 893 | dev->name); |
1080 | DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", | 894 | stats->rx_crc_errors++; |
1081 | dev->name); | 895 | goto update_stats; |
1082 | } else { | ||
1083 | stats->rx_crc_errors++; | ||
1084 | DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); | ||
1085 | } | ||
1086 | stats->rx_errors++; | ||
1087 | goto drop; | ||
1088 | } | 896 | } |
1089 | 897 | ||
1090 | /* For now we ignore the 802.11 header completely, assuming | 898 | /* Handle frames in monitor mode */ |
1091 | that the card's firmware has handled anything vital */ | 899 | if (priv->iw_mode == IW_MODE_MONITOR) { |
900 | orinoco_rx_monitor(dev, rxfid, &desc); | ||
901 | return; | ||
902 | } | ||
1092 | 903 | ||
1093 | err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), | 904 | if (status & HERMES_RXSTAT_UNDECRYPTABLE) { |
1094 | rxfid, HERMES_802_3_OFFSET); | 905 | DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", |
1095 | if (err) { | 906 | dev->name); |
1096 | printk(KERN_ERR "%s: error %d reading frame header. " | 907 | wstats->discard.code++; |
1097 | "Frame dropped.\n", dev->name, err); | 908 | goto update_stats; |
1098 | stats->rx_errors++; | ||
1099 | goto drop; | ||
1100 | } | 909 | } |
1101 | 910 | ||
1102 | length = ntohs(hdr.len); | 911 | length = le16_to_cpu(desc.data_len); |
1103 | 912 | fc = le16_to_cpu(desc.frame_ctl); | |
913 | |||
1104 | /* Sanity checks */ | 914 | /* Sanity checks */ |
1105 | if (length < 3) { /* No for even an 802.2 LLC header */ | 915 | if (length < 3) { /* No for even an 802.2 LLC header */ |
1106 | /* At least on Symbol firmware with PCF we get quite a | 916 | /* At least on Symbol firmware with PCF we get quite a |
1107 | lot of these legitimately - Poll frames with no | 917 | lot of these legitimately - Poll frames with no |
1108 | data. */ | 918 | data. */ |
1109 | stats->rx_dropped++; | 919 | return; |
1110 | goto drop; | ||
1111 | } | 920 | } |
1112 | if (length > IEEE802_11_DATA_LEN) { | 921 | if (length > IEEE802_11_DATA_LEN) { |
1113 | printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", | 922 | printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", |
1114 | dev->name, length); | 923 | dev->name, length); |
1115 | stats->rx_length_errors++; | 924 | stats->rx_length_errors++; |
1116 | stats->rx_errors++; | 925 | goto update_stats; |
1117 | goto drop; | ||
1118 | } | 926 | } |
1119 | 927 | ||
1120 | /* We need space for the packet data itself, plus an ethernet | 928 | /* We need space for the packet data itself, plus an ethernet |
@@ -1126,60 +934,53 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) | |||
1126 | if (!skb) { | 934 | if (!skb) { |
1127 | printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", | 935 | printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", |
1128 | dev->name); | 936 | dev->name); |
1129 | goto drop; | 937 | goto update_stats; |
1130 | } | 938 | } |
1131 | 939 | ||
1132 | skb_reserve(skb, 2); /* This way the IP header is aligned */ | 940 | /* We'll prepend the header, so reserve space for it. The worst |
941 | case is no decapsulation, when 802.3 header is prepended and | ||
942 | nothing is removed. 2 is for aligning the IP header. */ | ||
943 | skb_reserve(skb, ETH_HLEN + 2); | ||
944 | |||
945 | err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length), | ||
946 | ALIGN(length, 2), rxfid, | ||
947 | HERMES_802_2_OFFSET); | ||
948 | if (err) { | ||
949 | printk(KERN_ERR "%s: error %d reading frame. " | ||
950 | "Frame dropped.\n", dev->name, err); | ||
951 | goto drop; | ||
952 | } | ||
1133 | 953 | ||
1134 | /* Handle decapsulation | 954 | /* Handle decapsulation |
1135 | * In most cases, the firmware tell us about SNAP frames. | 955 | * In most cases, the firmware tell us about SNAP frames. |
1136 | * For some reason, the SNAP frames sent by LinkSys APs | 956 | * For some reason, the SNAP frames sent by LinkSys APs |
1137 | * are not properly recognised by most firmwares. | 957 | * are not properly recognised by most firmwares. |
1138 | * So, check ourselves */ | 958 | * So, check ourselves */ |
1139 | if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || | 959 | if (length >= ENCAPS_OVERHEAD && |
1140 | ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || | 960 | (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || |
1141 | is_ethersnap(&hdr)) { | 961 | ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || |
962 | is_ethersnap(skb->data))) { | ||
1142 | /* These indicate a SNAP within 802.2 LLC within | 963 | /* These indicate a SNAP within 802.2 LLC within |
1143 | 802.11 frame which we'll need to de-encapsulate to | 964 | 802.11 frame which we'll need to de-encapsulate to |
1144 | the original EthernetII frame. */ | 965 | the original EthernetII frame. */ |
1145 | 966 | hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD); | |
1146 | if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */ | ||
1147 | stats->rx_length_errors++; | ||
1148 | goto drop; | ||
1149 | } | ||
1150 | |||
1151 | /* Remove SNAP header, reconstruct EthernetII frame */ | ||
1152 | data_len = length - ENCAPS_OVERHEAD; | ||
1153 | data_off = HERMES_802_3_OFFSET + sizeof(hdr); | ||
1154 | |||
1155 | eh = (struct ethhdr *)skb_put(skb, ETH_HLEN); | ||
1156 | |||
1157 | memcpy(eh, &hdr, 2 * ETH_ALEN); | ||
1158 | eh->h_proto = hdr.ethertype; | ||
1159 | } else { | 967 | } else { |
1160 | /* All other cases indicate a genuine 802.3 frame. No | 968 | /* 802.3 frame - prepend 802.3 header as is */ |
1161 | decapsulation needed. We just throw the whole | 969 | hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN); |
1162 | thing in, and hope the protocol layer can deal with | 970 | hdr->h_proto = htons(length); |
1163 | it as 802.3 */ | ||
1164 | data_len = length; | ||
1165 | data_off = HERMES_802_3_OFFSET; | ||
1166 | /* FIXME: we re-read from the card data we already read here */ | ||
1167 | } | ||
1168 | |||
1169 | p = skb_put(skb, data_len); | ||
1170 | err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2), | ||
1171 | rxfid, data_off); | ||
1172 | if (err) { | ||
1173 | printk(KERN_ERR "%s: error %d reading frame. " | ||
1174 | "Frame dropped.\n", dev->name, err); | ||
1175 | stats->rx_errors++; | ||
1176 | goto drop; | ||
1177 | } | 971 | } |
972 | memcpy(hdr->h_dest, desc.addr1, ETH_ALEN); | ||
973 | if (fc & IEEE80211_FCTL_FROMDS) | ||
974 | memcpy(hdr->h_source, desc.addr3, ETH_ALEN); | ||
975 | else | ||
976 | memcpy(hdr->h_source, desc.addr2, ETH_ALEN); | ||
1178 | 977 | ||
1179 | dev->last_rx = jiffies; | 978 | dev->last_rx = jiffies; |
1180 | skb->dev = dev; | 979 | skb->dev = dev; |
1181 | skb->protocol = eth_type_trans(skb, dev); | 980 | skb->protocol = eth_type_trans(skb, dev); |
1182 | skb->ip_summed = CHECKSUM_NONE; | 981 | skb->ip_summed = CHECKSUM_NONE; |
982 | if (fc & IEEE80211_FCTL_TODS) | ||
983 | skb->pkt_type = PACKET_OTHERHOST; | ||
1183 | 984 | ||
1184 | /* Process the wireless stats if needed */ | 985 | /* Process the wireless stats if needed */ |
1185 | orinoco_stat_gather(dev, skb, &desc); | 986 | orinoco_stat_gather(dev, skb, &desc); |
@@ -1192,11 +993,10 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) | |||
1192 | return; | 993 | return; |
1193 | 994 | ||
1194 | drop: | 995 | drop: |
996 | dev_kfree_skb_irq(skb); | ||
997 | update_stats: | ||
998 | stats->rx_errors++; | ||
1195 | stats->rx_dropped++; | 999 | stats->rx_dropped++; |
1196 | |||
1197 | if (skb) | ||
1198 | dev_kfree_skb_irq(skb); | ||
1199 | return; | ||
1200 | } | 1000 | } |
1201 | 1001 | ||
1202 | /********************************************************************/ | 1002 | /********************************************************************/ |
@@ -1240,6 +1040,99 @@ static void print_linkstatus(struct net_device *dev, u16 status) | |||
1240 | dev->name, s, status); | 1040 | dev->name, s, status); |
1241 | } | 1041 | } |
1242 | 1042 | ||
1043 | /* Search scan results for requested BSSID, join it if found */ | ||
1044 | static void orinoco_join_ap(struct net_device *dev) | ||
1045 | { | ||
1046 | struct orinoco_private *priv = netdev_priv(dev); | ||
1047 | struct hermes *hw = &priv->hw; | ||
1048 | int err; | ||
1049 | unsigned long flags; | ||
1050 | struct join_req { | ||
1051 | u8 bssid[ETH_ALEN]; | ||
1052 | u16 channel; | ||
1053 | } __attribute__ ((packed)) req; | ||
1054 | const int atom_len = offsetof(struct prism2_scan_apinfo, atim); | ||
1055 | struct prism2_scan_apinfo *atom; | ||
1056 | int offset = 4; | ||
1057 | u8 *buf; | ||
1058 | u16 len; | ||
1059 | |||
1060 | /* Allocate buffer for scan results */ | ||
1061 | buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL); | ||
1062 | if (! buf) | ||
1063 | return; | ||
1064 | |||
1065 | if (orinoco_lock(priv, &flags) != 0) | ||
1066 | goto out; | ||
1067 | |||
1068 | /* Sanity checks in case user changed something in the meantime */ | ||
1069 | if (! priv->bssid_fixed) | ||
1070 | goto out; | ||
1071 | |||
1072 | if (strlen(priv->desired_essid) == 0) | ||
1073 | goto out; | ||
1074 | |||
1075 | /* Read scan results from the firmware */ | ||
1076 | err = hermes_read_ltv(hw, USER_BAP, | ||
1077 | HERMES_RID_SCANRESULTSTABLE, | ||
1078 | MAX_SCAN_LEN, &len, buf); | ||
1079 | if (err) { | ||
1080 | printk(KERN_ERR "%s: Cannot read scan results\n", | ||
1081 | dev->name); | ||
1082 | goto out; | ||
1083 | } | ||
1084 | |||
1085 | len = HERMES_RECLEN_TO_BYTES(len); | ||
1086 | |||
1087 | /* Go through the scan results looking for the channel of the AP | ||
1088 | * we were requested to join */ | ||
1089 | for (; offset + atom_len <= len; offset += atom_len) { | ||
1090 | atom = (struct prism2_scan_apinfo *) (buf + offset); | ||
1091 | if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) | ||
1092 | goto found; | ||
1093 | } | ||
1094 | |||
1095 | DEBUG(1, "%s: Requested AP not found in scan results\n", | ||
1096 | dev->name); | ||
1097 | goto out; | ||
1098 | |||
1099 | found: | ||
1100 | memcpy(req.bssid, priv->desired_bssid, ETH_ALEN); | ||
1101 | req.channel = atom->channel; /* both are little-endian */ | ||
1102 | err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST, | ||
1103 | &req); | ||
1104 | if (err) | ||
1105 | printk(KERN_ERR "%s: Error issuing join request\n", dev->name); | ||
1106 | |||
1107 | out: | ||
1108 | kfree(buf); | ||
1109 | orinoco_unlock(priv, &flags); | ||
1110 | } | ||
1111 | |||
1112 | /* Send new BSSID to userspace */ | ||
1113 | static void orinoco_send_wevents(struct net_device *dev) | ||
1114 | { | ||
1115 | struct orinoco_private *priv = netdev_priv(dev); | ||
1116 | struct hermes *hw = &priv->hw; | ||
1117 | union iwreq_data wrqu; | ||
1118 | int err; | ||
1119 | unsigned long flags; | ||
1120 | |||
1121 | if (orinoco_lock(priv, &flags) != 0) | ||
1122 | return; | ||
1123 | |||
1124 | err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID, | ||
1125 | ETH_ALEN, NULL, wrqu.ap_addr.sa_data); | ||
1126 | if (err != 0) | ||
1127 | return; | ||
1128 | |||
1129 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
1130 | |||
1131 | /* Send event to user space */ | ||
1132 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | ||
1133 | orinoco_unlock(priv, &flags); | ||
1134 | } | ||
1135 | |||
1243 | static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | 1136 | static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) |
1244 | { | 1137 | { |
1245 | struct orinoco_private *priv = netdev_priv(dev); | 1138 | struct orinoco_private *priv = netdev_priv(dev); |
@@ -1307,6 +1200,9 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | |||
1307 | u16 newstatus; | 1200 | u16 newstatus; |
1308 | int connected; | 1201 | int connected; |
1309 | 1202 | ||
1203 | if (priv->iw_mode == IW_MODE_MONITOR) | ||
1204 | break; | ||
1205 | |||
1310 | if (len != sizeof(linkstatus)) { | 1206 | if (len != sizeof(linkstatus)) { |
1311 | printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", | 1207 | printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", |
1312 | dev->name, len); | 1208 | dev->name, len); |
@@ -1319,6 +1215,15 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | |||
1319 | break; | 1215 | break; |
1320 | newstatus = le16_to_cpu(linkstatus.linkstatus); | 1216 | newstatus = le16_to_cpu(linkstatus.linkstatus); |
1321 | 1217 | ||
1218 | /* Symbol firmware uses "out of range" to signal that | ||
1219 | * the hostscan frame can be requested. */ | ||
1220 | if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE && | ||
1221 | priv->firmware_type == FIRMWARE_TYPE_SYMBOL && | ||
1222 | priv->has_hostscan && priv->scan_inprogress) { | ||
1223 | hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL); | ||
1224 | break; | ||
1225 | } | ||
1226 | |||
1322 | connected = (newstatus == HERMES_LINKSTATUS_CONNECTED) | 1227 | connected = (newstatus == HERMES_LINKSTATUS_CONNECTED) |
1323 | || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) | 1228 | || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) |
1324 | || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE); | 1229 | || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE); |
@@ -1328,12 +1233,89 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | |||
1328 | else if (!ignore_disconnect) | 1233 | else if (!ignore_disconnect) |
1329 | netif_carrier_off(dev); | 1234 | netif_carrier_off(dev); |
1330 | 1235 | ||
1331 | if (newstatus != priv->last_linkstatus) | 1236 | if (newstatus != priv->last_linkstatus) { |
1237 | priv->last_linkstatus = newstatus; | ||
1332 | print_linkstatus(dev, newstatus); | 1238 | print_linkstatus(dev, newstatus); |
1239 | /* The info frame contains only one word which is the | ||
1240 | * status (see hermes.h). The status is pretty boring | ||
1241 | * in itself, that's why we export the new BSSID... | ||
1242 | * Jean II */ | ||
1243 | schedule_work(&priv->wevent_work); | ||
1244 | } | ||
1245 | } | ||
1246 | break; | ||
1247 | case HERMES_INQ_SCAN: | ||
1248 | if (!priv->scan_inprogress && priv->bssid_fixed && | ||
1249 | priv->firmware_type == FIRMWARE_TYPE_INTERSIL) { | ||
1250 | schedule_work(&priv->join_work); | ||
1251 | break; | ||
1252 | } | ||
1253 | /* fall through */ | ||
1254 | case HERMES_INQ_HOSTSCAN: | ||
1255 | case HERMES_INQ_HOSTSCAN_SYMBOL: { | ||
1256 | /* Result of a scanning. Contains information about | ||
1257 | * cells in the vicinity - Jean II */ | ||
1258 | union iwreq_data wrqu; | ||
1259 | unsigned char *buf; | ||
1260 | |||
1261 | /* Sanity check */ | ||
1262 | if (len > 4096) { | ||
1263 | printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n", | ||
1264 | dev->name, len); | ||
1265 | break; | ||
1266 | } | ||
1333 | 1267 | ||
1334 | priv->last_linkstatus = newstatus; | 1268 | /* We are a strict producer. If the previous scan results |
1269 | * have not been consumed, we just have to drop this | ||
1270 | * frame. We can't remove the previous results ourselves, | ||
1271 | * that would be *very* racy... Jean II */ | ||
1272 | if (priv->scan_result != NULL) { | ||
1273 | printk(KERN_WARNING "%s: Previous scan results not consumed, dropping info frame.\n", dev->name); | ||
1274 | break; | ||
1275 | } | ||
1276 | |||
1277 | /* Allocate buffer for results */ | ||
1278 | buf = kmalloc(len, GFP_ATOMIC); | ||
1279 | if (buf == NULL) | ||
1280 | /* No memory, so can't printk()... */ | ||
1281 | break; | ||
1282 | |||
1283 | /* Read scan data */ | ||
1284 | err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, | ||
1285 | infofid, sizeof(info)); | ||
1286 | if (err) | ||
1287 | break; | ||
1288 | |||
1289 | #ifdef ORINOCO_DEBUG | ||
1290 | { | ||
1291 | int i; | ||
1292 | printk(KERN_DEBUG "Scan result [%02X", buf[0]); | ||
1293 | for(i = 1; i < (len * 2); i++) | ||
1294 | printk(":%02X", buf[i]); | ||
1295 | printk("]\n"); | ||
1296 | } | ||
1297 | #endif /* ORINOCO_DEBUG */ | ||
1298 | |||
1299 | /* Allow the clients to access the results */ | ||
1300 | priv->scan_len = len; | ||
1301 | priv->scan_result = buf; | ||
1302 | |||
1303 | /* Send an empty event to user space. | ||
1304 | * We don't send the received data on the event because | ||
1305 | * it would require us to do complex transcoding, and | ||
1306 | * we want to minimise the work done in the irq handler | ||
1307 | * Use a request to extract the data - Jean II */ | ||
1308 | wrqu.data.length = 0; | ||
1309 | wrqu.data.flags = 0; | ||
1310 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); | ||
1335 | } | 1311 | } |
1336 | break; | 1312 | break; |
1313 | case HERMES_INQ_SEC_STAT_AGERE: | ||
1314 | /* Security status (Agere specific) */ | ||
1315 | /* Ignore this frame for now */ | ||
1316 | if (priv->firmware_type == FIRMWARE_TYPE_AGERE) | ||
1317 | break; | ||
1318 | /* fall through */ | ||
1337 | default: | 1319 | default: |
1338 | printk(KERN_DEBUG "%s: Unknown information frame received: " | 1320 | printk(KERN_DEBUG "%s: Unknown information frame received: " |
1339 | "type 0x%04x, length %d\n", dev->name, type, len); | 1321 | "type 0x%04x, length %d\n", dev->name, type, len); |
@@ -1470,6 +1452,36 @@ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) | |||
1470 | return err; | 1452 | return err; |
1471 | } | 1453 | } |
1472 | 1454 | ||
1455 | /* Set fixed AP address */ | ||
1456 | static int __orinoco_hw_set_wap(struct orinoco_private *priv) | ||
1457 | { | ||
1458 | int roaming_flag; | ||
1459 | int err = 0; | ||
1460 | hermes_t *hw = &priv->hw; | ||
1461 | |||
1462 | switch (priv->firmware_type) { | ||
1463 | case FIRMWARE_TYPE_AGERE: | ||
1464 | /* not supported */ | ||
1465 | break; | ||
1466 | case FIRMWARE_TYPE_INTERSIL: | ||
1467 | if (priv->bssid_fixed) | ||
1468 | roaming_flag = 2; | ||
1469 | else | ||
1470 | roaming_flag = 1; | ||
1471 | |||
1472 | err = hermes_write_wordrec(hw, USER_BAP, | ||
1473 | HERMES_RID_CNFROAMINGMODE, | ||
1474 | roaming_flag); | ||
1475 | break; | ||
1476 | case FIRMWARE_TYPE_SYMBOL: | ||
1477 | err = HERMES_WRITE_RECORD(hw, USER_BAP, | ||
1478 | HERMES_RID_CNFMANDATORYBSSID_SYMBOL, | ||
1479 | &priv->desired_bssid); | ||
1480 | break; | ||
1481 | } | ||
1482 | return err; | ||
1483 | } | ||
1484 | |||
1473 | /* Change the WEP keys and/or the current keys. Can be called | 1485 | /* Change the WEP keys and/or the current keys. Can be called |
1474 | * either from __orinoco_hw_setup_wep() or directly from | 1486 | * either from __orinoco_hw_setup_wep() or directly from |
1475 | * orinoco_ioctl_setiwencode(). In the later case the association | 1487 | * orinoco_ioctl_setiwencode(). In the later case the association |
@@ -1655,6 +1667,13 @@ static int __orinoco_program_rids(struct net_device *dev) | |||
1655 | } | 1667 | } |
1656 | } | 1668 | } |
1657 | 1669 | ||
1670 | /* Set the desired BSSID */ | ||
1671 | err = __orinoco_hw_set_wap(priv); | ||
1672 | if (err) { | ||
1673 | printk(KERN_ERR "%s: Error %d setting AP address\n", | ||
1674 | dev->name, err); | ||
1675 | return err; | ||
1676 | } | ||
1658 | /* Set the desired ESSID */ | 1677 | /* Set the desired ESSID */ |
1659 | idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); | 1678 | idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); |
1660 | memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); | 1679 | memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); |
@@ -1793,6 +1812,20 @@ static int __orinoco_program_rids(struct net_device *dev) | |||
1793 | } | 1812 | } |
1794 | } | 1813 | } |
1795 | 1814 | ||
1815 | if (priv->iw_mode == IW_MODE_MONITOR) { | ||
1816 | /* Enable monitor mode */ | ||
1817 | dev->type = ARPHRD_IEEE80211; | ||
1818 | err = hermes_docmd_wait(hw, HERMES_CMD_TEST | | ||
1819 | HERMES_TEST_MONITOR, 0, NULL); | ||
1820 | } else { | ||
1821 | /* Disable monitor mode */ | ||
1822 | dev->type = ARPHRD_ETHER; | ||
1823 | err = hermes_docmd_wait(hw, HERMES_CMD_TEST | | ||
1824 | HERMES_TEST_STOP, 0, NULL); | ||
1825 | } | ||
1826 | if (err) | ||
1827 | return err; | ||
1828 | |||
1796 | /* Set promiscuity / multicast*/ | 1829 | /* Set promiscuity / multicast*/ |
1797 | priv->promiscuous = 0; | 1830 | priv->promiscuous = 0; |
1798 | priv->mc_count = 0; | 1831 | priv->mc_count = 0; |
@@ -1869,55 +1902,6 @@ __orinoco_set_multicast_list(struct net_device *dev) | |||
1869 | dev->flags &= ~IFF_PROMISC; | 1902 | dev->flags &= ~IFF_PROMISC; |
1870 | } | 1903 | } |
1871 | 1904 | ||
1872 | static int orinoco_reconfigure(struct net_device *dev) | ||
1873 | { | ||
1874 | struct orinoco_private *priv = netdev_priv(dev); | ||
1875 | struct hermes *hw = &priv->hw; | ||
1876 | unsigned long flags; | ||
1877 | int err = 0; | ||
1878 | |||
1879 | if (priv->broken_disableport) { | ||
1880 | schedule_work(&priv->reset_work); | ||
1881 | return 0; | ||
1882 | } | ||
1883 | |||
1884 | if (orinoco_lock(priv, &flags) != 0) | ||
1885 | return -EBUSY; | ||
1886 | |||
1887 | err = hermes_disable_port(hw, 0); | ||
1888 | if (err) { | ||
1889 | printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n", | ||
1890 | dev->name); | ||
1891 | priv->broken_disableport = 1; | ||
1892 | goto out; | ||
1893 | } | ||
1894 | |||
1895 | err = __orinoco_program_rids(dev); | ||
1896 | if (err) { | ||
1897 | printk(KERN_WARNING "%s: Unable to reconfigure card\n", | ||
1898 | dev->name); | ||
1899 | goto out; | ||
1900 | } | ||
1901 | |||
1902 | err = hermes_enable_port(hw, 0); | ||
1903 | if (err) { | ||
1904 | printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", | ||
1905 | dev->name); | ||
1906 | goto out; | ||
1907 | } | ||
1908 | |||
1909 | out: | ||
1910 | if (err) { | ||
1911 | printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); | ||
1912 | schedule_work(&priv->reset_work); | ||
1913 | err = 0; | ||
1914 | } | ||
1915 | |||
1916 | orinoco_unlock(priv, &flags); | ||
1917 | return err; | ||
1918 | |||
1919 | } | ||
1920 | |||
1921 | /* This must be called from user context, without locks held - use | 1905 | /* This must be called from user context, without locks held - use |
1922 | * schedule_work() */ | 1906 | * schedule_work() */ |
1923 | static void orinoco_reset(struct net_device *dev) | 1907 | static void orinoco_reset(struct net_device *dev) |
@@ -1946,6 +1930,11 @@ static void orinoco_reset(struct net_device *dev) | |||
1946 | 1930 | ||
1947 | orinoco_unlock(priv, &flags); | 1931 | orinoco_unlock(priv, &flags); |
1948 | 1932 | ||
1933 | /* Scanning support: Cleanup of driver struct */ | ||
1934 | kfree(priv->scan_result); | ||
1935 | priv->scan_result = NULL; | ||
1936 | priv->scan_inprogress = 0; | ||
1937 | |||
1949 | if (priv->hard_reset) { | 1938 | if (priv->hard_reset) { |
1950 | err = (*priv->hard_reset)(priv); | 1939 | err = (*priv->hard_reset)(priv); |
1951 | if (err) { | 1940 | if (err) { |
@@ -2184,6 +2173,8 @@ static int determine_firmware(struct net_device *dev) | |||
2184 | priv->has_mwo = (firmver >= 0x60000); | 2173 | priv->has_mwo = (firmver >= 0x60000); |
2185 | priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ | 2174 | priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ |
2186 | priv->ibss_port = 1; | 2175 | priv->ibss_port = 1; |
2176 | priv->has_hostscan = (firmver >= 0x8000a); | ||
2177 | priv->broken_monitor = (firmver >= 0x80000); | ||
2187 | 2178 | ||
2188 | /* Tested with Agere firmware : | 2179 | /* Tested with Agere firmware : |
2189 | * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II | 2180 | * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II |
@@ -2229,6 +2220,8 @@ static int determine_firmware(struct net_device *dev) | |||
2229 | priv->ibss_port = 4; | 2220 | priv->ibss_port = 4; |
2230 | priv->broken_disableport = (firmver == 0x25013) || | 2221 | priv->broken_disableport = (firmver == 0x25013) || |
2231 | (firmver >= 0x30000 && firmver <= 0x31000); | 2222 | (firmver >= 0x30000 && firmver <= 0x31000); |
2223 | priv->has_hostscan = (firmver >= 0x31001) || | ||
2224 | (firmver >= 0x29057 && firmver < 0x30000); | ||
2232 | /* Tested with Intel firmware : 0x20015 => Jean II */ | 2225 | /* Tested with Intel firmware : 0x20015 => Jean II */ |
2233 | /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */ | 2226 | /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */ |
2234 | break; | 2227 | break; |
@@ -2248,6 +2241,7 @@ static int determine_firmware(struct net_device *dev) | |||
2248 | priv->has_ibss = (firmver >= 0x000700); /* FIXME */ | 2241 | priv->has_ibss = (firmver >= 0x000700); /* FIXME */ |
2249 | priv->has_big_wep = priv->has_wep = (firmver >= 0x000800); | 2242 | priv->has_big_wep = priv->has_wep = (firmver >= 0x000800); |
2250 | priv->has_pm = (firmver >= 0x000700); | 2243 | priv->has_pm = (firmver >= 0x000700); |
2244 | priv->has_hostscan = (firmver >= 0x010301); | ||
2251 | 2245 | ||
2252 | if (firmver >= 0x000800) | 2246 | if (firmver >= 0x000800) |
2253 | priv->ibss_port = 0; | 2247 | priv->ibss_port = 0; |
@@ -2456,8 +2450,9 @@ struct net_device *alloc_orinocodev(int sizeof_card, | |||
2456 | dev->tx_timeout = orinoco_tx_timeout; | 2450 | dev->tx_timeout = orinoco_tx_timeout; |
2457 | dev->watchdog_timeo = HZ; /* 1 second timeout */ | 2451 | dev->watchdog_timeo = HZ; /* 1 second timeout */ |
2458 | dev->get_stats = orinoco_get_stats; | 2452 | dev->get_stats = orinoco_get_stats; |
2453 | dev->ethtool_ops = &orinoco_ethtool_ops; | ||
2459 | dev->get_wireless_stats = orinoco_get_wireless_stats; | 2454 | dev->get_wireless_stats = orinoco_get_wireless_stats; |
2460 | dev->do_ioctl = orinoco_ioctl; | 2455 | dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; |
2461 | dev->change_mtu = orinoco_change_mtu; | 2456 | dev->change_mtu = orinoco_change_mtu; |
2462 | dev->set_multicast_list = orinoco_set_multicast_list; | 2457 | dev->set_multicast_list = orinoco_set_multicast_list; |
2463 | /* we use the default eth_mac_addr for setting the MAC addr */ | 2458 | /* we use the default eth_mac_addr for setting the MAC addr */ |
@@ -2473,6 +2468,8 @@ struct net_device *alloc_orinocodev(int sizeof_card, | |||
2473 | * before anything else touches the | 2468 | * before anything else touches the |
2474 | * hardware */ | 2469 | * hardware */ |
2475 | INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); | 2470 | INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); |
2471 | INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev); | ||
2472 | INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev); | ||
2476 | 2473 | ||
2477 | netif_carrier_off(dev); | 2474 | netif_carrier_off(dev); |
2478 | priv->last_linkstatus = 0xffff; | 2475 | priv->last_linkstatus = 0xffff; |
@@ -2483,6 +2480,9 @@ struct net_device *alloc_orinocodev(int sizeof_card, | |||
2483 | 2480 | ||
2484 | void free_orinocodev(struct net_device *dev) | 2481 | void free_orinocodev(struct net_device *dev) |
2485 | { | 2482 | { |
2483 | struct orinoco_private *priv = netdev_priv(dev); | ||
2484 | |||
2485 | kfree(priv->scan_result); | ||
2486 | free_netdev(dev); | 2486 | free_netdev(dev); |
2487 | } | 2487 | } |
2488 | 2488 | ||
@@ -2490,24 +2490,6 @@ void free_orinocodev(struct net_device *dev) | |||
2490 | /* Wireless extensions */ | 2490 | /* Wireless extensions */ |
2491 | /********************************************************************/ | 2491 | /********************************************************************/ |
2492 | 2492 | ||
2493 | static int orinoco_hw_get_bssid(struct orinoco_private *priv, | ||
2494 | char buf[ETH_ALEN]) | ||
2495 | { | ||
2496 | hermes_t *hw = &priv->hw; | ||
2497 | int err = 0; | ||
2498 | unsigned long flags; | ||
2499 | |||
2500 | if (orinoco_lock(priv, &flags) != 0) | ||
2501 | return -EBUSY; | ||
2502 | |||
2503 | err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, | ||
2504 | ETH_ALEN, NULL, buf); | ||
2505 | |||
2506 | orinoco_unlock(priv, &flags); | ||
2507 | |||
2508 | return err; | ||
2509 | } | ||
2510 | |||
2511 | static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, | 2493 | static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, |
2512 | char buf[IW_ESSID_MAX_SIZE+1]) | 2494 | char buf[IW_ESSID_MAX_SIZE+1]) |
2513 | { | 2495 | { |
@@ -2633,140 +2615,271 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, | |||
2633 | return 0; | 2615 | return 0; |
2634 | } | 2616 | } |
2635 | 2617 | ||
2636 | static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq) | 2618 | static int orinoco_ioctl_getname(struct net_device *dev, |
2619 | struct iw_request_info *info, | ||
2620 | char *name, | ||
2621 | char *extra) | ||
2637 | { | 2622 | { |
2638 | struct orinoco_private *priv = netdev_priv(dev); | 2623 | struct orinoco_private *priv = netdev_priv(dev); |
2639 | int err = 0; | ||
2640 | int mode; | ||
2641 | struct iw_range range; | ||
2642 | int numrates; | 2624 | int numrates; |
2643 | int i, k; | 2625 | int err; |
2626 | |||
2627 | err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0); | ||
2628 | |||
2629 | if (!err && (numrates > 2)) | ||
2630 | strcpy(name, "IEEE 802.11b"); | ||
2631 | else | ||
2632 | strcpy(name, "IEEE 802.11-DS"); | ||
2633 | |||
2634 | return 0; | ||
2635 | } | ||
2636 | |||
2637 | static int orinoco_ioctl_setwap(struct net_device *dev, | ||
2638 | struct iw_request_info *info, | ||
2639 | struct sockaddr *ap_addr, | ||
2640 | char *extra) | ||
2641 | { | ||
2642 | struct orinoco_private *priv = netdev_priv(dev); | ||
2643 | int err = -EINPROGRESS; /* Call commit handler */ | ||
2644 | unsigned long flags; | 2644 | unsigned long flags; |
2645 | static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
2646 | static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
2645 | 2647 | ||
2646 | TRACE_ENTER(dev->name); | 2648 | if (orinoco_lock(priv, &flags) != 0) |
2649 | return -EBUSY; | ||
2650 | |||
2651 | /* Enable automatic roaming - no sanity checks are needed */ | ||
2652 | if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 || | ||
2653 | memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) { | ||
2654 | priv->bssid_fixed = 0; | ||
2655 | memset(priv->desired_bssid, 0, ETH_ALEN); | ||
2656 | |||
2657 | /* "off" means keep existing connection */ | ||
2658 | if (ap_addr->sa_data[0] == 0) { | ||
2659 | __orinoco_hw_set_wap(priv); | ||
2660 | err = 0; | ||
2661 | } | ||
2662 | goto out; | ||
2663 | } | ||
2664 | |||
2665 | if (priv->firmware_type == FIRMWARE_TYPE_AGERE) { | ||
2666 | printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't " | ||
2667 | "support manual roaming\n", | ||
2668 | dev->name); | ||
2669 | err = -EOPNOTSUPP; | ||
2670 | goto out; | ||
2671 | } | ||
2672 | |||
2673 | if (priv->iw_mode != IW_MODE_INFRA) { | ||
2674 | printk(KERN_WARNING "%s: Manual roaming supported only in " | ||
2675 | "managed mode\n", dev->name); | ||
2676 | err = -EOPNOTSUPP; | ||
2677 | goto out; | ||
2678 | } | ||
2679 | |||
2680 | /* Intersil firmware hangs without Desired ESSID */ | ||
2681 | if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL && | ||
2682 | strlen(priv->desired_essid) == 0) { | ||
2683 | printk(KERN_WARNING "%s: Desired ESSID must be set for " | ||
2684 | "manual roaming\n", dev->name); | ||
2685 | err = -EOPNOTSUPP; | ||
2686 | goto out; | ||
2687 | } | ||
2688 | |||
2689 | /* Finally, enable manual roaming */ | ||
2690 | priv->bssid_fixed = 1; | ||
2691 | memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN); | ||
2692 | |||
2693 | out: | ||
2694 | orinoco_unlock(priv, &flags); | ||
2695 | return err; | ||
2696 | } | ||
2697 | |||
2698 | static int orinoco_ioctl_getwap(struct net_device *dev, | ||
2699 | struct iw_request_info *info, | ||
2700 | struct sockaddr *ap_addr, | ||
2701 | char *extra) | ||
2702 | { | ||
2703 | struct orinoco_private *priv = netdev_priv(dev); | ||
2704 | |||
2705 | hermes_t *hw = &priv->hw; | ||
2706 | int err = 0; | ||
2707 | unsigned long flags; | ||
2708 | |||
2709 | if (orinoco_lock(priv, &flags) != 0) | ||
2710 | return -EBUSY; | ||
2711 | |||
2712 | ap_addr->sa_family = ARPHRD_ETHER; | ||
2713 | err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, | ||
2714 | ETH_ALEN, NULL, ap_addr->sa_data); | ||
2715 | |||
2716 | orinoco_unlock(priv, &flags); | ||
2717 | |||
2718 | return err; | ||
2719 | } | ||
2647 | 2720 | ||
2648 | if (!access_ok(VERIFY_WRITE, rrq->pointer, sizeof(range))) | 2721 | static int orinoco_ioctl_setmode(struct net_device *dev, |
2649 | return -EFAULT; | 2722 | struct iw_request_info *info, |
2723 | u32 *mode, | ||
2724 | char *extra) | ||
2725 | { | ||
2726 | struct orinoco_private *priv = netdev_priv(dev); | ||
2727 | int err = -EINPROGRESS; /* Call commit handler */ | ||
2728 | unsigned long flags; | ||
2650 | 2729 | ||
2651 | rrq->length = sizeof(range); | 2730 | if (priv->iw_mode == *mode) |
2731 | return 0; | ||
2652 | 2732 | ||
2653 | if (orinoco_lock(priv, &flags) != 0) | 2733 | if (orinoco_lock(priv, &flags) != 0) |
2654 | return -EBUSY; | 2734 | return -EBUSY; |
2655 | 2735 | ||
2656 | mode = priv->iw_mode; | 2736 | switch (*mode) { |
2737 | case IW_MODE_ADHOC: | ||
2738 | if (!priv->has_ibss && !priv->has_port3) | ||
2739 | err = -EOPNOTSUPP; | ||
2740 | break; | ||
2741 | |||
2742 | case IW_MODE_INFRA: | ||
2743 | break; | ||
2744 | |||
2745 | case IW_MODE_MONITOR: | ||
2746 | if (priv->broken_monitor && !force_monitor) { | ||
2747 | printk(KERN_WARNING "%s: Monitor mode support is " | ||
2748 | "buggy in this firmware, not enabling\n", | ||
2749 | dev->name); | ||
2750 | err = -EOPNOTSUPP; | ||
2751 | } | ||
2752 | break; | ||
2753 | |||
2754 | default: | ||
2755 | err = -EOPNOTSUPP; | ||
2756 | break; | ||
2757 | } | ||
2758 | |||
2759 | if (err == -EINPROGRESS) { | ||
2760 | priv->iw_mode = *mode; | ||
2761 | set_port_type(priv); | ||
2762 | } | ||
2763 | |||
2657 | orinoco_unlock(priv, &flags); | 2764 | orinoco_unlock(priv, &flags); |
2658 | 2765 | ||
2659 | memset(&range, 0, sizeof(range)); | 2766 | return err; |
2767 | } | ||
2768 | |||
2769 | static int orinoco_ioctl_getmode(struct net_device *dev, | ||
2770 | struct iw_request_info *info, | ||
2771 | u32 *mode, | ||
2772 | char *extra) | ||
2773 | { | ||
2774 | struct orinoco_private *priv = netdev_priv(dev); | ||
2775 | |||
2776 | *mode = priv->iw_mode; | ||
2777 | return 0; | ||
2778 | } | ||
2779 | |||
2780 | static int orinoco_ioctl_getiwrange(struct net_device *dev, | ||
2781 | struct iw_request_info *info, | ||
2782 | struct iw_point *rrq, | ||
2783 | char *extra) | ||
2784 | { | ||
2785 | struct orinoco_private *priv = netdev_priv(dev); | ||
2786 | int err = 0; | ||
2787 | struct iw_range *range = (struct iw_range *) extra; | ||
2788 | int numrates; | ||
2789 | int i, k; | ||
2790 | |||
2791 | TRACE_ENTER(dev->name); | ||
2660 | 2792 | ||
2661 | /* Much of this shamelessly taken from wvlan_cs.c. No idea | 2793 | rrq->length = sizeof(struct iw_range); |
2662 | * what it all means -dgibson */ | 2794 | memset(range, 0, sizeof(struct iw_range)); |
2663 | range.we_version_compiled = WIRELESS_EXT; | ||
2664 | range.we_version_source = 11; | ||
2665 | 2795 | ||
2666 | range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ | 2796 | range->we_version_compiled = WIRELESS_EXT; |
2797 | range->we_version_source = 14; | ||
2667 | 2798 | ||
2668 | /* Set available channels/frequencies */ | 2799 | /* Set available channels/frequencies */ |
2669 | range.num_channels = NUM_CHANNELS; | 2800 | range->num_channels = NUM_CHANNELS; |
2670 | k = 0; | 2801 | k = 0; |
2671 | for (i = 0; i < NUM_CHANNELS; i++) { | 2802 | for (i = 0; i < NUM_CHANNELS; i++) { |
2672 | if (priv->channel_mask & (1 << i)) { | 2803 | if (priv->channel_mask & (1 << i)) { |
2673 | range.freq[k].i = i + 1; | 2804 | range->freq[k].i = i + 1; |
2674 | range.freq[k].m = channel_frequency[i] * 100000; | 2805 | range->freq[k].m = channel_frequency[i] * 100000; |
2675 | range.freq[k].e = 1; | 2806 | range->freq[k].e = 1; |
2676 | k++; | 2807 | k++; |
2677 | } | 2808 | } |
2678 | 2809 | ||
2679 | if (k >= IW_MAX_FREQUENCIES) | 2810 | if (k >= IW_MAX_FREQUENCIES) |
2680 | break; | 2811 | break; |
2681 | } | 2812 | } |
2682 | range.num_frequency = k; | 2813 | range->num_frequency = k; |
2814 | range->sensitivity = 3; | ||
2683 | 2815 | ||
2684 | range.sensitivity = 3; | 2816 | if (priv->has_wep) { |
2817 | range->max_encoding_tokens = ORINOCO_MAX_KEYS; | ||
2818 | range->encoding_size[0] = SMALL_KEY_SIZE; | ||
2819 | range->num_encoding_sizes = 1; | ||
2685 | 2820 | ||
2686 | if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ | 2821 | if (priv->has_big_wep) { |
2822 | range->encoding_size[1] = LARGE_KEY_SIZE; | ||
2823 | range->num_encoding_sizes = 2; | ||
2824 | } | ||
2825 | } | ||
2826 | |||
2827 | if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ | ||
2687 | /* Quality stats meaningless in ad-hoc mode */ | 2828 | /* Quality stats meaningless in ad-hoc mode */ |
2688 | range.max_qual.qual = 0; | ||
2689 | range.max_qual.level = 0; | ||
2690 | range.max_qual.noise = 0; | ||
2691 | range.avg_qual.qual = 0; | ||
2692 | range.avg_qual.level = 0; | ||
2693 | range.avg_qual.noise = 0; | ||
2694 | } else { | 2829 | } else { |
2695 | range.max_qual.qual = 0x8b - 0x2f; | 2830 | range->max_qual.qual = 0x8b - 0x2f; |
2696 | range.max_qual.level = 0x2f - 0x95 - 1; | 2831 | range->max_qual.level = 0x2f - 0x95 - 1; |
2697 | range.max_qual.noise = 0x2f - 0x95 - 1; | 2832 | range->max_qual.noise = 0x2f - 0x95 - 1; |
2698 | /* Need to get better values */ | 2833 | /* Need to get better values */ |
2699 | range.avg_qual.qual = 0x24; | 2834 | range->avg_qual.qual = 0x24; |
2700 | range.avg_qual.level = 0xC2; | 2835 | range->avg_qual.level = 0xC2; |
2701 | range.avg_qual.noise = 0x9E; | 2836 | range->avg_qual.noise = 0x9E; |
2702 | } | 2837 | } |
2703 | 2838 | ||
2704 | err = orinoco_hw_get_bitratelist(priv, &numrates, | 2839 | err = orinoco_hw_get_bitratelist(priv, &numrates, |
2705 | range.bitrate, IW_MAX_BITRATES); | 2840 | range->bitrate, IW_MAX_BITRATES); |
2706 | if (err) | 2841 | if (err) |
2707 | return err; | 2842 | return err; |
2708 | range.num_bitrates = numrates; | 2843 | range->num_bitrates = numrates; |
2709 | 2844 | ||
2710 | /* Set an indication of the max TCP throughput in bit/s that we can | 2845 | /* Set an indication of the max TCP throughput in bit/s that we can |
2711 | * expect using this interface. May be use for QoS stuff... | 2846 | * expect using this interface. May be use for QoS stuff... |
2712 | * Jean II */ | 2847 | * Jean II */ |
2713 | if(numrates > 2) | 2848 | if (numrates > 2) |
2714 | range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ | 2849 | range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ |
2715 | else | 2850 | else |
2716 | range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ | 2851 | range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ |
2717 | 2852 | ||
2718 | range.min_rts = 0; | 2853 | range->min_rts = 0; |
2719 | range.max_rts = 2347; | 2854 | range->max_rts = 2347; |
2720 | range.min_frag = 256; | 2855 | range->min_frag = 256; |
2721 | range.max_frag = 2346; | 2856 | range->max_frag = 2346; |
2722 | 2857 | ||
2723 | if (orinoco_lock(priv, &flags) != 0) | 2858 | range->min_pmp = 0; |
2724 | return -EBUSY; | 2859 | range->max_pmp = 65535000; |
2725 | if (priv->has_wep) { | 2860 | range->min_pmt = 0; |
2726 | range.max_encoding_tokens = ORINOCO_MAX_KEYS; | 2861 | range->max_pmt = 65535 * 1000; /* ??? */ |
2727 | 2862 | range->pmp_flags = IW_POWER_PERIOD; | |
2728 | range.encoding_size[0] = SMALL_KEY_SIZE; | 2863 | range->pmt_flags = IW_POWER_TIMEOUT; |
2729 | range.num_encoding_sizes = 1; | 2864 | range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; |
2730 | 2865 | ||
2731 | if (priv->has_big_wep) { | 2866 | range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; |
2732 | range.encoding_size[1] = LARGE_KEY_SIZE; | 2867 | range->retry_flags = IW_RETRY_LIMIT; |
2733 | range.num_encoding_sizes = 2; | 2868 | range->r_time_flags = IW_RETRY_LIFETIME; |
2734 | } | 2869 | range->min_retry = 0; |
2735 | } else { | 2870 | range->max_retry = 65535; /* ??? */ |
2736 | range.num_encoding_sizes = 0; | 2871 | range->min_r_time = 0; |
2737 | range.max_encoding_tokens = 0; | 2872 | range->max_r_time = 65535 * 1000; /* ??? */ |
2738 | } | ||
2739 | orinoco_unlock(priv, &flags); | ||
2740 | |||
2741 | range.min_pmp = 0; | ||
2742 | range.max_pmp = 65535000; | ||
2743 | range.min_pmt = 0; | ||
2744 | range.max_pmt = 65535 * 1000; /* ??? */ | ||
2745 | range.pmp_flags = IW_POWER_PERIOD; | ||
2746 | range.pmt_flags = IW_POWER_TIMEOUT; | ||
2747 | range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; | ||
2748 | |||
2749 | range.num_txpower = 1; | ||
2750 | range.txpower[0] = 15; /* 15dBm */ | ||
2751 | range.txpower_capa = IW_TXPOW_DBM; | ||
2752 | |||
2753 | range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; | ||
2754 | range.retry_flags = IW_RETRY_LIMIT; | ||
2755 | range.r_time_flags = IW_RETRY_LIFETIME; | ||
2756 | range.min_retry = 0; | ||
2757 | range.max_retry = 65535; /* ??? */ | ||
2758 | range.min_r_time = 0; | ||
2759 | range.max_r_time = 65535 * 1000; /* ??? */ | ||
2760 | |||
2761 | if (copy_to_user(rrq->pointer, &range, sizeof(range))) | ||
2762 | return -EFAULT; | ||
2763 | 2873 | ||
2764 | TRACE_EXIT(dev->name); | 2874 | TRACE_EXIT(dev->name); |
2765 | 2875 | ||
2766 | return 0; | 2876 | return 0; |
2767 | } | 2877 | } |
2768 | 2878 | ||
2769 | static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq) | 2879 | static int orinoco_ioctl_setiwencode(struct net_device *dev, |
2880 | struct iw_request_info *info, | ||
2881 | struct iw_point *erq, | ||
2882 | char *keybuf) | ||
2770 | { | 2883 | { |
2771 | struct orinoco_private *priv = netdev_priv(dev); | 2884 | struct orinoco_private *priv = netdev_priv(dev); |
2772 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; | 2885 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; |
@@ -2774,8 +2887,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er | |||
2774 | int enable = priv->wep_on; | 2887 | int enable = priv->wep_on; |
2775 | int restricted = priv->wep_restrict; | 2888 | int restricted = priv->wep_restrict; |
2776 | u16 xlen = 0; | 2889 | u16 xlen = 0; |
2777 | int err = 0; | 2890 | int err = -EINPROGRESS; /* Call commit handler */ |
2778 | char keybuf[ORINOCO_MAX_KEY_SIZE]; | ||
2779 | unsigned long flags; | 2891 | unsigned long flags; |
2780 | 2892 | ||
2781 | if (! priv->has_wep) | 2893 | if (! priv->has_wep) |
@@ -2788,9 +2900,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er | |||
2788 | 2900 | ||
2789 | if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) | 2901 | if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) |
2790 | return -E2BIG; | 2902 | return -E2BIG; |
2791 | |||
2792 | if (copy_from_user(keybuf, erq->pointer, erq->length)) | ||
2793 | return -EFAULT; | ||
2794 | } | 2903 | } |
2795 | 2904 | ||
2796 | if (orinoco_lock(priv, &flags) != 0) | 2905 | if (orinoco_lock(priv, &flags) != 0) |
@@ -2864,12 +2973,14 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er | |||
2864 | return err; | 2973 | return err; |
2865 | } | 2974 | } |
2866 | 2975 | ||
2867 | static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq) | 2976 | static int orinoco_ioctl_getiwencode(struct net_device *dev, |
2977 | struct iw_request_info *info, | ||
2978 | struct iw_point *erq, | ||
2979 | char *keybuf) | ||
2868 | { | 2980 | { |
2869 | struct orinoco_private *priv = netdev_priv(dev); | 2981 | struct orinoco_private *priv = netdev_priv(dev); |
2870 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; | 2982 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; |
2871 | u16 xlen = 0; | 2983 | u16 xlen = 0; |
2872 | char keybuf[ORINOCO_MAX_KEY_SIZE]; | ||
2873 | unsigned long flags; | 2984 | unsigned long flags; |
2874 | 2985 | ||
2875 | if (! priv->has_wep) | 2986 | if (! priv->has_wep) |
@@ -2898,51 +3009,47 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er | |||
2898 | memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); | 3009 | memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); |
2899 | 3010 | ||
2900 | orinoco_unlock(priv, &flags); | 3011 | orinoco_unlock(priv, &flags); |
2901 | |||
2902 | if (erq->pointer) { | ||
2903 | if (copy_to_user(erq->pointer, keybuf, xlen)) | ||
2904 | return -EFAULT; | ||
2905 | } | ||
2906 | |||
2907 | return 0; | 3012 | return 0; |
2908 | } | 3013 | } |
2909 | 3014 | ||
2910 | static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq) | 3015 | static int orinoco_ioctl_setessid(struct net_device *dev, |
3016 | struct iw_request_info *info, | ||
3017 | struct iw_point *erq, | ||
3018 | char *essidbuf) | ||
2911 | { | 3019 | { |
2912 | struct orinoco_private *priv = netdev_priv(dev); | 3020 | struct orinoco_private *priv = netdev_priv(dev); |
2913 | char essidbuf[IW_ESSID_MAX_SIZE+1]; | ||
2914 | unsigned long flags; | 3021 | unsigned long flags; |
2915 | 3022 | ||
2916 | /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it | 3023 | /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it |
2917 | * anyway... - Jean II */ | 3024 | * anyway... - Jean II */ |
2918 | 3025 | ||
2919 | memset(&essidbuf, 0, sizeof(essidbuf)); | 3026 | /* Hum... Should not use Wireless Extension constant (may change), |
2920 | 3027 | * should use our own... - Jean II */ | |
2921 | if (erq->flags) { | 3028 | if (erq->length > IW_ESSID_MAX_SIZE) |
2922 | /* iwconfig includes the NUL in the specified length */ | 3029 | return -E2BIG; |
2923 | if (erq->length > IW_ESSID_MAX_SIZE+1) | ||
2924 | return -E2BIG; | ||
2925 | |||
2926 | if (copy_from_user(&essidbuf, erq->pointer, erq->length)) | ||
2927 | return -EFAULT; | ||
2928 | |||
2929 | essidbuf[IW_ESSID_MAX_SIZE] = '\0'; | ||
2930 | } | ||
2931 | 3030 | ||
2932 | if (orinoco_lock(priv, &flags) != 0) | 3031 | if (orinoco_lock(priv, &flags) != 0) |
2933 | return -EBUSY; | 3032 | return -EBUSY; |
2934 | 3033 | ||
2935 | memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid)); | 3034 | /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */ |
3035 | memset(priv->desired_essid, 0, sizeof(priv->desired_essid)); | ||
3036 | |||
3037 | /* If not ANY, get the new ESSID */ | ||
3038 | if (erq->flags) { | ||
3039 | memcpy(priv->desired_essid, essidbuf, erq->length); | ||
3040 | } | ||
2936 | 3041 | ||
2937 | orinoco_unlock(priv, &flags); | 3042 | orinoco_unlock(priv, &flags); |
2938 | 3043 | ||
2939 | return 0; | 3044 | return -EINPROGRESS; /* Call commit handler */ |
2940 | } | 3045 | } |
2941 | 3046 | ||
2942 | static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) | 3047 | static int orinoco_ioctl_getessid(struct net_device *dev, |
3048 | struct iw_request_info *info, | ||
3049 | struct iw_point *erq, | ||
3050 | char *essidbuf) | ||
2943 | { | 3051 | { |
2944 | struct orinoco_private *priv = netdev_priv(dev); | 3052 | struct orinoco_private *priv = netdev_priv(dev); |
2945 | char essidbuf[IW_ESSID_MAX_SIZE+1]; | ||
2946 | int active; | 3053 | int active; |
2947 | int err = 0; | 3054 | int err = 0; |
2948 | unsigned long flags; | 3055 | unsigned long flags; |
@@ -2956,51 +3063,46 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) | |||
2956 | } else { | 3063 | } else { |
2957 | if (orinoco_lock(priv, &flags) != 0) | 3064 | if (orinoco_lock(priv, &flags) != 0) |
2958 | return -EBUSY; | 3065 | return -EBUSY; |
2959 | memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf)); | 3066 | memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1); |
2960 | orinoco_unlock(priv, &flags); | 3067 | orinoco_unlock(priv, &flags); |
2961 | } | 3068 | } |
2962 | 3069 | ||
2963 | erq->flags = 1; | 3070 | erq->flags = 1; |
2964 | erq->length = strlen(essidbuf) + 1; | 3071 | erq->length = strlen(essidbuf) + 1; |
2965 | if (erq->pointer) | ||
2966 | if (copy_to_user(erq->pointer, essidbuf, erq->length)) | ||
2967 | return -EFAULT; | ||
2968 | 3072 | ||
2969 | TRACE_EXIT(dev->name); | 3073 | TRACE_EXIT(dev->name); |
2970 | 3074 | ||
2971 | return 0; | 3075 | return 0; |
2972 | } | 3076 | } |
2973 | 3077 | ||
2974 | static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq) | 3078 | static int orinoco_ioctl_setnick(struct net_device *dev, |
3079 | struct iw_request_info *info, | ||
3080 | struct iw_point *nrq, | ||
3081 | char *nickbuf) | ||
2975 | { | 3082 | { |
2976 | struct orinoco_private *priv = netdev_priv(dev); | 3083 | struct orinoco_private *priv = netdev_priv(dev); |
2977 | char nickbuf[IW_ESSID_MAX_SIZE+1]; | ||
2978 | unsigned long flags; | 3084 | unsigned long flags; |
2979 | 3085 | ||
2980 | if (nrq->length > IW_ESSID_MAX_SIZE) | 3086 | if (nrq->length > IW_ESSID_MAX_SIZE) |
2981 | return -E2BIG; | 3087 | return -E2BIG; |
2982 | 3088 | ||
2983 | memset(nickbuf, 0, sizeof(nickbuf)); | ||
2984 | |||
2985 | if (copy_from_user(nickbuf, nrq->pointer, nrq->length)) | ||
2986 | return -EFAULT; | ||
2987 | |||
2988 | nickbuf[nrq->length] = '\0'; | ||
2989 | |||
2990 | if (orinoco_lock(priv, &flags) != 0) | 3089 | if (orinoco_lock(priv, &flags) != 0) |
2991 | return -EBUSY; | 3090 | return -EBUSY; |
2992 | 3091 | ||
2993 | memcpy(priv->nick, nickbuf, sizeof(priv->nick)); | 3092 | memset(priv->nick, 0, sizeof(priv->nick)); |
3093 | memcpy(priv->nick, nickbuf, nrq->length); | ||
2994 | 3094 | ||
2995 | orinoco_unlock(priv, &flags); | 3095 | orinoco_unlock(priv, &flags); |
2996 | 3096 | ||
2997 | return 0; | 3097 | return -EINPROGRESS; /* Call commit handler */ |
2998 | } | 3098 | } |
2999 | 3099 | ||
3000 | static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) | 3100 | static int orinoco_ioctl_getnick(struct net_device *dev, |
3101 | struct iw_request_info *info, | ||
3102 | struct iw_point *nrq, | ||
3103 | char *nickbuf) | ||
3001 | { | 3104 | { |
3002 | struct orinoco_private *priv = netdev_priv(dev); | 3105 | struct orinoco_private *priv = netdev_priv(dev); |
3003 | char nickbuf[IW_ESSID_MAX_SIZE+1]; | ||
3004 | unsigned long flags; | 3106 | unsigned long flags; |
3005 | 3107 | ||
3006 | if (orinoco_lock(priv, &flags) != 0) | 3108 | if (orinoco_lock(priv, &flags) != 0) |
@@ -3011,23 +3113,22 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) | |||
3011 | 3113 | ||
3012 | nrq->length = strlen(nickbuf)+1; | 3114 | nrq->length = strlen(nickbuf)+1; |
3013 | 3115 | ||
3014 | if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf))) | ||
3015 | return -EFAULT; | ||
3016 | |||
3017 | return 0; | 3116 | return 0; |
3018 | } | 3117 | } |
3019 | 3118 | ||
3020 | static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) | 3119 | static int orinoco_ioctl_setfreq(struct net_device *dev, |
3120 | struct iw_request_info *info, | ||
3121 | struct iw_freq *frq, | ||
3122 | char *extra) | ||
3021 | { | 3123 | { |
3022 | struct orinoco_private *priv = netdev_priv(dev); | 3124 | struct orinoco_private *priv = netdev_priv(dev); |
3023 | int chan = -1; | 3125 | int chan = -1; |
3024 | unsigned long flags; | 3126 | unsigned long flags; |
3127 | int err = -EINPROGRESS; /* Call commit handler */ | ||
3025 | 3128 | ||
3026 | /* We can only use this in Ad-Hoc demo mode to set the operating | 3129 | /* In infrastructure mode the AP sets the channel */ |
3027 | * frequency, or in IBSS mode to set the frequency where the IBSS | 3130 | if (priv->iw_mode == IW_MODE_INFRA) |
3028 | * will be created - Jean II */ | 3131 | return -EBUSY; |
3029 | if (priv->iw_mode != IW_MODE_ADHOC) | ||
3030 | return -EOPNOTSUPP; | ||
3031 | 3132 | ||
3032 | if ( (frq->e == 0) && (frq->m <= 1000) ) { | 3133 | if ( (frq->e == 0) && (frq->m <= 1000) ) { |
3033 | /* Setting by channel number */ | 3134 | /* Setting by channel number */ |
@@ -3051,13 +3152,44 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) | |||
3051 | 3152 | ||
3052 | if (orinoco_lock(priv, &flags) != 0) | 3153 | if (orinoco_lock(priv, &flags) != 0) |
3053 | return -EBUSY; | 3154 | return -EBUSY; |
3155 | |||
3054 | priv->channel = chan; | 3156 | priv->channel = chan; |
3157 | if (priv->iw_mode == IW_MODE_MONITOR) { | ||
3158 | /* Fast channel change - no commit if successful */ | ||
3159 | hermes_t *hw = &priv->hw; | ||
3160 | err = hermes_docmd_wait(hw, HERMES_CMD_TEST | | ||
3161 | HERMES_TEST_SET_CHANNEL, | ||
3162 | chan, NULL); | ||
3163 | } | ||
3055 | orinoco_unlock(priv, &flags); | 3164 | orinoco_unlock(priv, &flags); |
3056 | 3165 | ||
3166 | return err; | ||
3167 | } | ||
3168 | |||
3169 | static int orinoco_ioctl_getfreq(struct net_device *dev, | ||
3170 | struct iw_request_info *info, | ||
3171 | struct iw_freq *frq, | ||
3172 | char *extra) | ||
3173 | { | ||
3174 | struct orinoco_private *priv = netdev_priv(dev); | ||
3175 | int tmp; | ||
3176 | |||
3177 | /* Locking done in there */ | ||
3178 | tmp = orinoco_hw_get_freq(priv); | ||
3179 | if (tmp < 0) { | ||
3180 | return tmp; | ||
3181 | } | ||
3182 | |||
3183 | frq->m = tmp; | ||
3184 | frq->e = 1; | ||
3185 | |||
3057 | return 0; | 3186 | return 0; |
3058 | } | 3187 | } |
3059 | 3188 | ||
3060 | static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) | 3189 | static int orinoco_ioctl_getsens(struct net_device *dev, |
3190 | struct iw_request_info *info, | ||
3191 | struct iw_param *srq, | ||
3192 | char *extra) | ||
3061 | { | 3193 | { |
3062 | struct orinoco_private *priv = netdev_priv(dev); | 3194 | struct orinoco_private *priv = netdev_priv(dev); |
3063 | hermes_t *hw = &priv->hw; | 3195 | hermes_t *hw = &priv->hw; |
@@ -3083,7 +3215,10 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) | |||
3083 | return 0; | 3215 | return 0; |
3084 | } | 3216 | } |
3085 | 3217 | ||
3086 | static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) | 3218 | static int orinoco_ioctl_setsens(struct net_device *dev, |
3219 | struct iw_request_info *info, | ||
3220 | struct iw_param *srq, | ||
3221 | char *extra) | ||
3087 | { | 3222 | { |
3088 | struct orinoco_private *priv = netdev_priv(dev); | 3223 | struct orinoco_private *priv = netdev_priv(dev); |
3089 | int val = srq->value; | 3224 | int val = srq->value; |
@@ -3100,10 +3235,13 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) | |||
3100 | priv->ap_density = val; | 3235 | priv->ap_density = val; |
3101 | orinoco_unlock(priv, &flags); | 3236 | orinoco_unlock(priv, &flags); |
3102 | 3237 | ||
3103 | return 0; | 3238 | return -EINPROGRESS; /* Call commit handler */ |
3104 | } | 3239 | } |
3105 | 3240 | ||
3106 | static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) | 3241 | static int orinoco_ioctl_setrts(struct net_device *dev, |
3242 | struct iw_request_info *info, | ||
3243 | struct iw_param *rrq, | ||
3244 | char *extra) | ||
3107 | { | 3245 | { |
3108 | struct orinoco_private *priv = netdev_priv(dev); | 3246 | struct orinoco_private *priv = netdev_priv(dev); |
3109 | int val = rrq->value; | 3247 | int val = rrq->value; |
@@ -3121,13 +3259,30 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) | |||
3121 | priv->rts_thresh = val; | 3259 | priv->rts_thresh = val; |
3122 | orinoco_unlock(priv, &flags); | 3260 | orinoco_unlock(priv, &flags); |
3123 | 3261 | ||
3262 | return -EINPROGRESS; /* Call commit handler */ | ||
3263 | } | ||
3264 | |||
3265 | static int orinoco_ioctl_getrts(struct net_device *dev, | ||
3266 | struct iw_request_info *info, | ||
3267 | struct iw_param *rrq, | ||
3268 | char *extra) | ||
3269 | { | ||
3270 | struct orinoco_private *priv = netdev_priv(dev); | ||
3271 | |||
3272 | rrq->value = priv->rts_thresh; | ||
3273 | rrq->disabled = (rrq->value == 2347); | ||
3274 | rrq->fixed = 1; | ||
3275 | |||
3124 | return 0; | 3276 | return 0; |
3125 | } | 3277 | } |
3126 | 3278 | ||
3127 | static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) | 3279 | static int orinoco_ioctl_setfrag(struct net_device *dev, |
3280 | struct iw_request_info *info, | ||
3281 | struct iw_param *frq, | ||
3282 | char *extra) | ||
3128 | { | 3283 | { |
3129 | struct orinoco_private *priv = netdev_priv(dev); | 3284 | struct orinoco_private *priv = netdev_priv(dev); |
3130 | int err = 0; | 3285 | int err = -EINPROGRESS; /* Call commit handler */ |
3131 | unsigned long flags; | 3286 | unsigned long flags; |
3132 | 3287 | ||
3133 | if (orinoco_lock(priv, &flags) != 0) | 3288 | if (orinoco_lock(priv, &flags) != 0) |
@@ -3159,11 +3314,14 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) | |||
3159 | return err; | 3314 | return err; |
3160 | } | 3315 | } |
3161 | 3316 | ||
3162 | static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) | 3317 | static int orinoco_ioctl_getfrag(struct net_device *dev, |
3318 | struct iw_request_info *info, | ||
3319 | struct iw_param *frq, | ||
3320 | char *extra) | ||
3163 | { | 3321 | { |
3164 | struct orinoco_private *priv = netdev_priv(dev); | 3322 | struct orinoco_private *priv = netdev_priv(dev); |
3165 | hermes_t *hw = &priv->hw; | 3323 | hermes_t *hw = &priv->hw; |
3166 | int err = 0; | 3324 | int err; |
3167 | u16 val; | 3325 | u16 val; |
3168 | unsigned long flags; | 3326 | unsigned long flags; |
3169 | 3327 | ||
@@ -3196,10 +3354,12 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) | |||
3196 | return err; | 3354 | return err; |
3197 | } | 3355 | } |
3198 | 3356 | ||
3199 | static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) | 3357 | static int orinoco_ioctl_setrate(struct net_device *dev, |
3358 | struct iw_request_info *info, | ||
3359 | struct iw_param *rrq, | ||
3360 | char *extra) | ||
3200 | { | 3361 | { |
3201 | struct orinoco_private *priv = netdev_priv(dev); | 3362 | struct orinoco_private *priv = netdev_priv(dev); |
3202 | int err = 0; | ||
3203 | int ratemode = -1; | 3363 | int ratemode = -1; |
3204 | int bitrate; /* 100s of kilobits */ | 3364 | int bitrate; /* 100s of kilobits */ |
3205 | int i; | 3365 | int i; |
@@ -3235,10 +3395,13 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) | |||
3235 | priv->bitratemode = ratemode; | 3395 | priv->bitratemode = ratemode; |
3236 | orinoco_unlock(priv, &flags); | 3396 | orinoco_unlock(priv, &flags); |
3237 | 3397 | ||
3238 | return err; | 3398 | return -EINPROGRESS; |
3239 | } | 3399 | } |
3240 | 3400 | ||
3241 | static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) | 3401 | static int orinoco_ioctl_getrate(struct net_device *dev, |
3402 | struct iw_request_info *info, | ||
3403 | struct iw_param *rrq, | ||
3404 | char *extra) | ||
3242 | { | 3405 | { |
3243 | struct orinoco_private *priv = netdev_priv(dev); | 3406 | struct orinoco_private *priv = netdev_priv(dev); |
3244 | hermes_t *hw = &priv->hw; | 3407 | hermes_t *hw = &priv->hw; |
@@ -3303,10 +3466,13 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) | |||
3303 | return err; | 3466 | return err; |
3304 | } | 3467 | } |
3305 | 3468 | ||
3306 | static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) | 3469 | static int orinoco_ioctl_setpower(struct net_device *dev, |
3470 | struct iw_request_info *info, | ||
3471 | struct iw_param *prq, | ||
3472 | char *extra) | ||
3307 | { | 3473 | { |
3308 | struct orinoco_private *priv = netdev_priv(dev); | 3474 | struct orinoco_private *priv = netdev_priv(dev); |
3309 | int err = 0; | 3475 | int err = -EINPROGRESS; /* Call commit handler */ |
3310 | unsigned long flags; | 3476 | unsigned long flags; |
3311 | 3477 | ||
3312 | if (orinoco_lock(priv, &flags) != 0) | 3478 | if (orinoco_lock(priv, &flags) != 0) |
@@ -3355,7 +3521,10 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) | |||
3355 | return err; | 3521 | return err; |
3356 | } | 3522 | } |
3357 | 3523 | ||
3358 | static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) | 3524 | static int orinoco_ioctl_getpower(struct net_device *dev, |
3525 | struct iw_request_info *info, | ||
3526 | struct iw_param *prq, | ||
3527 | char *extra) | ||
3359 | { | 3528 | { |
3360 | struct orinoco_private *priv = netdev_priv(dev); | 3529 | struct orinoco_private *priv = netdev_priv(dev); |
3361 | hermes_t *hw = &priv->hw; | 3530 | hermes_t *hw = &priv->hw; |
@@ -3403,7 +3572,10 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) | |||
3403 | return err; | 3572 | return err; |
3404 | } | 3573 | } |
3405 | 3574 | ||
3406 | static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) | 3575 | static int orinoco_ioctl_getretry(struct net_device *dev, |
3576 | struct iw_request_info *info, | ||
3577 | struct iw_param *rrq, | ||
3578 | char *extra) | ||
3407 | { | 3579 | { |
3408 | struct orinoco_private *priv = netdev_priv(dev); | 3580 | struct orinoco_private *priv = netdev_priv(dev); |
3409 | hermes_t *hw = &priv->hw; | 3581 | hermes_t *hw = &priv->hw; |
@@ -3454,10 +3626,38 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) | |||
3454 | return err; | 3626 | return err; |
3455 | } | 3627 | } |
3456 | 3628 | ||
3457 | static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) | 3629 | static int orinoco_ioctl_reset(struct net_device *dev, |
3630 | struct iw_request_info *info, | ||
3631 | void *wrqu, | ||
3632 | char *extra) | ||
3458 | { | 3633 | { |
3459 | struct orinoco_private *priv = netdev_priv(dev); | 3634 | struct orinoco_private *priv = netdev_priv(dev); |
3460 | int val = *( (int *) wrq->u.name ); | 3635 | |
3636 | if (! capable(CAP_NET_ADMIN)) | ||
3637 | return -EPERM; | ||
3638 | |||
3639 | if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) { | ||
3640 | printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); | ||
3641 | |||
3642 | /* Firmware reset */ | ||
3643 | orinoco_reset(dev); | ||
3644 | } else { | ||
3645 | printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); | ||
3646 | |||
3647 | schedule_work(&priv->reset_work); | ||
3648 | } | ||
3649 | |||
3650 | return 0; | ||
3651 | } | ||
3652 | |||
3653 | static int orinoco_ioctl_setibssport(struct net_device *dev, | ||
3654 | struct iw_request_info *info, | ||
3655 | void *wrqu, | ||
3656 | char *extra) | ||
3657 | |||
3658 | { | ||
3659 | struct orinoco_private *priv = netdev_priv(dev); | ||
3660 | int val = *( (int *) extra ); | ||
3461 | unsigned long flags; | 3661 | unsigned long flags; |
3462 | 3662 | ||
3463 | if (orinoco_lock(priv, &flags) != 0) | 3663 | if (orinoco_lock(priv, &flags) != 0) |
@@ -3469,28 +3669,28 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) | |||
3469 | set_port_type(priv); | 3669 | set_port_type(priv); |
3470 | 3670 | ||
3471 | orinoco_unlock(priv, &flags); | 3671 | orinoco_unlock(priv, &flags); |
3472 | return 0; | 3672 | return -EINPROGRESS; /* Call commit handler */ |
3473 | } | 3673 | } |
3474 | 3674 | ||
3475 | static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq) | 3675 | static int orinoco_ioctl_getibssport(struct net_device *dev, |
3676 | struct iw_request_info *info, | ||
3677 | void *wrqu, | ||
3678 | char *extra) | ||
3476 | { | 3679 | { |
3477 | struct orinoco_private *priv = netdev_priv(dev); | 3680 | struct orinoco_private *priv = netdev_priv(dev); |
3478 | int *val = (int *)wrq->u.name; | 3681 | int *val = (int *) extra; |
3479 | unsigned long flags; | ||
3480 | |||
3481 | if (orinoco_lock(priv, &flags) != 0) | ||
3482 | return -EBUSY; | ||
3483 | 3682 | ||
3484 | *val = priv->ibss_port; | 3683 | *val = priv->ibss_port; |
3485 | orinoco_unlock(priv, &flags); | ||
3486 | |||
3487 | return 0; | 3684 | return 0; |
3488 | } | 3685 | } |
3489 | 3686 | ||
3490 | static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) | 3687 | static int orinoco_ioctl_setport3(struct net_device *dev, |
3688 | struct iw_request_info *info, | ||
3689 | void *wrqu, | ||
3690 | char *extra) | ||
3491 | { | 3691 | { |
3492 | struct orinoco_private *priv = netdev_priv(dev); | 3692 | struct orinoco_private *priv = netdev_priv(dev); |
3493 | int val = *( (int *) wrq->u.name ); | 3693 | int val = *( (int *) extra ); |
3494 | int err = 0; | 3694 | int err = 0; |
3495 | unsigned long flags; | 3695 | unsigned long flags; |
3496 | 3696 | ||
@@ -3519,51 +3719,131 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) | |||
3519 | err = -EINVAL; | 3719 | err = -EINVAL; |
3520 | } | 3720 | } |
3521 | 3721 | ||
3522 | if (! err) | 3722 | if (! err) { |
3523 | /* Actually update the mode we are using */ | 3723 | /* Actually update the mode we are using */ |
3524 | set_port_type(priv); | 3724 | set_port_type(priv); |
3725 | err = -EINPROGRESS; | ||
3726 | } | ||
3525 | 3727 | ||
3526 | orinoco_unlock(priv, &flags); | 3728 | orinoco_unlock(priv, &flags); |
3527 | 3729 | ||
3528 | return err; | 3730 | return err; |
3529 | } | 3731 | } |
3530 | 3732 | ||
3531 | static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq) | 3733 | static int orinoco_ioctl_getport3(struct net_device *dev, |
3734 | struct iw_request_info *info, | ||
3735 | void *wrqu, | ||
3736 | char *extra) | ||
3737 | { | ||
3738 | struct orinoco_private *priv = netdev_priv(dev); | ||
3739 | int *val = (int *) extra; | ||
3740 | |||
3741 | *val = priv->prefer_port3; | ||
3742 | return 0; | ||
3743 | } | ||
3744 | |||
3745 | static int orinoco_ioctl_setpreamble(struct net_device *dev, | ||
3746 | struct iw_request_info *info, | ||
3747 | void *wrqu, | ||
3748 | char *extra) | ||
3532 | { | 3749 | { |
3533 | struct orinoco_private *priv = netdev_priv(dev); | 3750 | struct orinoco_private *priv = netdev_priv(dev); |
3534 | int *val = (int *)wrq->u.name; | ||
3535 | unsigned long flags; | 3751 | unsigned long flags; |
3752 | int val; | ||
3753 | |||
3754 | if (! priv->has_preamble) | ||
3755 | return -EOPNOTSUPP; | ||
3756 | |||
3757 | /* 802.11b has recently defined some short preamble. | ||
3758 | * Basically, the Phy header has been reduced in size. | ||
3759 | * This increase performance, especially at high rates | ||
3760 | * (the preamble is transmitted at 1Mb/s), unfortunately | ||
3761 | * this give compatibility troubles... - Jean II */ | ||
3762 | val = *( (int *) extra ); | ||
3536 | 3763 | ||
3537 | if (orinoco_lock(priv, &flags) != 0) | 3764 | if (orinoco_lock(priv, &flags) != 0) |
3538 | return -EBUSY; | 3765 | return -EBUSY; |
3539 | 3766 | ||
3540 | *val = priv->prefer_port3; | 3767 | if (val) |
3768 | priv->preamble = 1; | ||
3769 | else | ||
3770 | priv->preamble = 0; | ||
3771 | |||
3541 | orinoco_unlock(priv, &flags); | 3772 | orinoco_unlock(priv, &flags); |
3773 | |||
3774 | return -EINPROGRESS; /* Call commit handler */ | ||
3775 | } | ||
3776 | |||
3777 | static int orinoco_ioctl_getpreamble(struct net_device *dev, | ||
3778 | struct iw_request_info *info, | ||
3779 | void *wrqu, | ||
3780 | char *extra) | ||
3781 | { | ||
3782 | struct orinoco_private *priv = netdev_priv(dev); | ||
3783 | int *val = (int *) extra; | ||
3784 | |||
3785 | if (! priv->has_preamble) | ||
3786 | return -EOPNOTSUPP; | ||
3787 | |||
3788 | *val = priv->preamble; | ||
3542 | return 0; | 3789 | return 0; |
3543 | } | 3790 | } |
3544 | 3791 | ||
3792 | /* ioctl interface to hermes_read_ltv() | ||
3793 | * To use with iwpriv, pass the RID as the token argument, e.g. | ||
3794 | * iwpriv get_rid [0xfc00] | ||
3795 | * At least Wireless Tools 25 is required to use iwpriv. | ||
3796 | * For Wireless Tools 25 and 26 append "dummy" are the end. */ | ||
3797 | static int orinoco_ioctl_getrid(struct net_device *dev, | ||
3798 | struct iw_request_info *info, | ||
3799 | struct iw_point *data, | ||
3800 | char *extra) | ||
3801 | { | ||
3802 | struct orinoco_private *priv = netdev_priv(dev); | ||
3803 | hermes_t *hw = &priv->hw; | ||
3804 | int rid = data->flags; | ||
3805 | u16 length; | ||
3806 | int err; | ||
3807 | unsigned long flags; | ||
3808 | |||
3809 | /* It's a "get" function, but we don't want users to access the | ||
3810 | * WEP key and other raw firmware data */ | ||
3811 | if (! capable(CAP_NET_ADMIN)) | ||
3812 | return -EPERM; | ||
3813 | |||
3814 | if (rid < 0xfc00 || rid > 0xffff) | ||
3815 | return -EINVAL; | ||
3816 | |||
3817 | if (orinoco_lock(priv, &flags) != 0) | ||
3818 | return -EBUSY; | ||
3819 | |||
3820 | err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, | ||
3821 | extra); | ||
3822 | if (err) | ||
3823 | goto out; | ||
3824 | |||
3825 | data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length), | ||
3826 | MAX_RID_LEN); | ||
3827 | |||
3828 | out: | ||
3829 | orinoco_unlock(priv, &flags); | ||
3830 | return err; | ||
3831 | } | ||
3832 | |||
3545 | /* Spy is used for link quality/strength measurements in Ad-Hoc mode | 3833 | /* Spy is used for link quality/strength measurements in Ad-Hoc mode |
3546 | * Jean II */ | 3834 | * Jean II */ |
3547 | static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) | 3835 | static int orinoco_ioctl_setspy(struct net_device *dev, |
3836 | struct iw_request_info *info, | ||
3837 | struct iw_point *srq, | ||
3838 | char *extra) | ||
3839 | |||
3548 | { | 3840 | { |
3549 | struct orinoco_private *priv = netdev_priv(dev); | 3841 | struct orinoco_private *priv = netdev_priv(dev); |
3550 | struct sockaddr address[IW_MAX_SPY]; | 3842 | struct sockaddr *address = (struct sockaddr *) extra; |
3551 | int number = srq->length; | 3843 | int number = srq->length; |
3552 | int i; | 3844 | int i; |
3553 | int err = 0; | ||
3554 | unsigned long flags; | 3845 | unsigned long flags; |
3555 | 3846 | ||
3556 | /* Check the number of addresses */ | ||
3557 | if (number > IW_MAX_SPY) | ||
3558 | return -E2BIG; | ||
3559 | |||
3560 | /* Get the data in the driver */ | ||
3561 | if (srq->pointer) { | ||
3562 | if (copy_from_user(address, srq->pointer, | ||
3563 | sizeof(struct sockaddr) * number)) | ||
3564 | return -EFAULT; | ||
3565 | } | ||
3566 | |||
3567 | /* Make sure nobody mess with the structure while we do */ | 3847 | /* Make sure nobody mess with the structure while we do */ |
3568 | if (orinoco_lock(priv, &flags) != 0) | 3848 | if (orinoco_lock(priv, &flags) != 0) |
3569 | return -EBUSY; | 3849 | return -EBUSY; |
@@ -3587,14 +3867,17 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) | |||
3587 | /* Now, let the others play */ | 3867 | /* Now, let the others play */ |
3588 | orinoco_unlock(priv, &flags); | 3868 | orinoco_unlock(priv, &flags); |
3589 | 3869 | ||
3590 | return err; | 3870 | /* Do NOT call commit handler */ |
3871 | return 0; | ||
3591 | } | 3872 | } |
3592 | 3873 | ||
3593 | static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) | 3874 | static int orinoco_ioctl_getspy(struct net_device *dev, |
3875 | struct iw_request_info *info, | ||
3876 | struct iw_point *srq, | ||
3877 | char *extra) | ||
3594 | { | 3878 | { |
3595 | struct orinoco_private *priv = netdev_priv(dev); | 3879 | struct orinoco_private *priv = netdev_priv(dev); |
3596 | struct sockaddr address[IW_MAX_SPY]; | 3880 | struct sockaddr *address = (struct sockaddr *) extra; |
3597 | struct iw_quality spy_stat[IW_MAX_SPY]; | ||
3598 | int number; | 3881 | int number; |
3599 | int i; | 3882 | int i; |
3600 | unsigned long flags; | 3883 | unsigned long flags; |
@@ -3603,7 +3886,12 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) | |||
3603 | return -EBUSY; | 3886 | return -EBUSY; |
3604 | 3887 | ||
3605 | number = priv->spy_number; | 3888 | number = priv->spy_number; |
3606 | if ((number > 0) && (srq->pointer)) { | 3889 | /* Create address struct */ |
3890 | for (i = 0; i < number; i++) { | ||
3891 | memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN); | ||
3892 | address[i].sa_family = AF_UNIX; | ||
3893 | } | ||
3894 | if (number > 0) { | ||
3607 | /* Create address struct */ | 3895 | /* Create address struct */ |
3608 | for (i = 0; i < number; i++) { | 3896 | for (i = 0; i < number; i++) { |
3609 | memcpy(address[i].sa_data, priv->spy_address[i], | 3897 | memcpy(address[i].sa_data, priv->spy_address[i], |
@@ -3614,344 +3902,503 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) | |||
3614 | /* In theory, we should disable irqs while copying the stats | 3902 | /* In theory, we should disable irqs while copying the stats |
3615 | * because the rx path might update it in the middle... | 3903 | * because the rx path might update it in the middle... |
3616 | * Bah, who care ? - Jean II */ | 3904 | * Bah, who care ? - Jean II */ |
3617 | memcpy(&spy_stat, priv->spy_stat, | 3905 | memcpy(extra + (sizeof(struct sockaddr) * number), |
3618 | sizeof(struct iw_quality) * IW_MAX_SPY); | 3906 | priv->spy_stat, sizeof(struct iw_quality) * number); |
3619 | for (i=0; i < number; i++) | ||
3620 | priv->spy_stat[i].updated = 0; | ||
3621 | } | 3907 | } |
3908 | /* Reset updated flags. */ | ||
3909 | for (i = 0; i < number; i++) | ||
3910 | priv->spy_stat[i].updated = 0; | ||
3622 | 3911 | ||
3623 | orinoco_unlock(priv, &flags); | 3912 | orinoco_unlock(priv, &flags); |
3624 | 3913 | ||
3625 | /* Push stuff to user space */ | ||
3626 | srq->length = number; | 3914 | srq->length = number; |
3627 | if(copy_to_user(srq->pointer, address, | ||
3628 | sizeof(struct sockaddr) * number)) | ||
3629 | return -EFAULT; | ||
3630 | if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number), | ||
3631 | &spy_stat, sizeof(struct iw_quality) * number)) | ||
3632 | return -EFAULT; | ||
3633 | 3915 | ||
3634 | return 0; | 3916 | return 0; |
3635 | } | 3917 | } |
3636 | 3918 | ||
3637 | static int | 3919 | /* Trigger a scan (look for other cells in the vicinity */ |
3638 | orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 3920 | static int orinoco_ioctl_setscan(struct net_device *dev, |
3921 | struct iw_request_info *info, | ||
3922 | struct iw_param *srq, | ||
3923 | char *extra) | ||
3639 | { | 3924 | { |
3640 | struct orinoco_private *priv = netdev_priv(dev); | 3925 | struct orinoco_private *priv = netdev_priv(dev); |
3641 | struct iwreq *wrq = (struct iwreq *)rq; | 3926 | hermes_t *hw = &priv->hw; |
3642 | int err = 0; | 3927 | int err = 0; |
3643 | int tmp; | ||
3644 | int changed = 0; | ||
3645 | unsigned long flags; | 3928 | unsigned long flags; |
3646 | 3929 | ||
3647 | TRACE_ENTER(dev->name); | 3930 | /* Note : you may have realised that, as this is a SET operation, |
3931 | * this is priviledged and therefore a normal user can't | ||
3932 | * perform scanning. | ||
3933 | * This is not an error, while the device perform scanning, | ||
3934 | * traffic doesn't flow, so it's a perfect DoS... | ||
3935 | * Jean II */ | ||
3648 | 3936 | ||
3649 | /* In theory, we could allow most of the the SET stuff to be | 3937 | if (orinoco_lock(priv, &flags) != 0) |
3650 | * done. In practice, the lapse of time at startup when the | 3938 | return -EBUSY; |
3651 | * card is not ready is very short, so why bother... Note | ||
3652 | * that netif_device_present is different from up/down | ||
3653 | * (ifconfig), when the device is not yet up, it is usually | ||
3654 | * already ready... Jean II */ | ||
3655 | if (! netif_device_present(dev)) | ||
3656 | return -ENODEV; | ||
3657 | 3939 | ||
3658 | switch (cmd) { | 3940 | /* Scanning with port 0 disabled would fail */ |
3659 | case SIOCGIWNAME: | 3941 | if (!netif_running(dev)) { |
3660 | strcpy(wrq->u.name, "IEEE 802.11-DS"); | 3942 | err = -ENETDOWN; |
3661 | break; | 3943 | goto out; |
3662 | 3944 | } | |
3663 | case SIOCGIWAP: | ||
3664 | wrq->u.ap_addr.sa_family = ARPHRD_ETHER; | ||
3665 | err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data); | ||
3666 | break; | ||
3667 | 3945 | ||
3668 | case SIOCGIWRANGE: | 3946 | /* In monitor mode, the scan results are always empty. |
3669 | err = orinoco_ioctl_getiwrange(dev, &wrq->u.data); | 3947 | * Probe responses are passed to the driver as received |
3670 | break; | 3948 | * frames and could be processed in software. */ |
3949 | if (priv->iw_mode == IW_MODE_MONITOR) { | ||
3950 | err = -EOPNOTSUPP; | ||
3951 | goto out; | ||
3952 | } | ||
3671 | 3953 | ||
3672 | case SIOCSIWMODE: | 3954 | /* Note : because we don't lock out the irq handler, the way |
3673 | if (orinoco_lock(priv, &flags) != 0) | 3955 | * we access scan variables in priv is critical. |
3674 | return -EBUSY; | 3956 | * o scan_inprogress : not touched by irq handler |
3675 | switch (wrq->u.mode) { | 3957 | * o scan_mode : not touched by irq handler |
3676 | case IW_MODE_ADHOC: | 3958 | * o scan_result : irq is strict producer, non-irq is strict |
3677 | if (! (priv->has_ibss || priv->has_port3) ) | 3959 | * consumer. |
3678 | err = -EINVAL; | 3960 | * o scan_len : synchronised with scan_result |
3679 | else { | 3961 | * Before modifying anything on those variables, please think hard ! |
3680 | priv->iw_mode = IW_MODE_ADHOC; | 3962 | * Jean II */ |
3681 | changed = 1; | ||
3682 | } | ||
3683 | break; | ||
3684 | 3963 | ||
3685 | case IW_MODE_INFRA: | 3964 | /* If there is still some left-over scan results, get rid of it */ |
3686 | priv->iw_mode = IW_MODE_INFRA; | 3965 | if (priv->scan_result != NULL) { |
3687 | changed = 1; | 3966 | /* What's likely is that a client did crash or was killed |
3688 | break; | 3967 | * between triggering the scan request and reading the |
3968 | * results, so we need to reset everything. | ||
3969 | * Some clients that are too slow may suffer from that... | ||
3970 | * Jean II */ | ||
3971 | kfree(priv->scan_result); | ||
3972 | priv->scan_result = NULL; | ||
3973 | } | ||
3689 | 3974 | ||
3690 | default: | 3975 | /* Save flags */ |
3691 | err = -EINVAL; | 3976 | priv->scan_mode = srq->flags; |
3692 | break; | ||
3693 | } | ||
3694 | set_port_type(priv); | ||
3695 | orinoco_unlock(priv, &flags); | ||
3696 | break; | ||
3697 | 3977 | ||
3698 | case SIOCGIWMODE: | 3978 | /* Always trigger scanning, even if it's in progress. |
3699 | if (orinoco_lock(priv, &flags) != 0) | 3979 | * This way, if the info frame get lost, we will recover somewhat |
3700 | return -EBUSY; | 3980 | * gracefully - Jean II */ |
3701 | wrq->u.mode = priv->iw_mode; | ||
3702 | orinoco_unlock(priv, &flags); | ||
3703 | break; | ||
3704 | 3981 | ||
3705 | case SIOCSIWENCODE: | 3982 | if (priv->has_hostscan) { |
3706 | err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding); | 3983 | switch (priv->firmware_type) { |
3707 | if (! err) | 3984 | case FIRMWARE_TYPE_SYMBOL: |
3708 | changed = 1; | 3985 | err = hermes_write_wordrec(hw, USER_BAP, |
3986 | HERMES_RID_CNFHOSTSCAN_SYMBOL, | ||
3987 | HERMES_HOSTSCAN_SYMBOL_ONCE | | ||
3988 | HERMES_HOSTSCAN_SYMBOL_BCAST); | ||
3989 | break; | ||
3990 | case FIRMWARE_TYPE_INTERSIL: { | ||
3991 | u16 req[3]; | ||
3992 | |||
3993 | req[0] = cpu_to_le16(0x3fff); /* All channels */ | ||
3994 | req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ | ||
3995 | req[2] = 0; /* Any ESSID */ | ||
3996 | err = HERMES_WRITE_RECORD(hw, USER_BAP, | ||
3997 | HERMES_RID_CNFHOSTSCAN, &req); | ||
3998 | } | ||
3709 | break; | 3999 | break; |
4000 | case FIRMWARE_TYPE_AGERE: | ||
4001 | err = hermes_write_wordrec(hw, USER_BAP, | ||
4002 | HERMES_RID_CNFSCANSSID_AGERE, | ||
4003 | 0); /* Any ESSID */ | ||
4004 | if (err) | ||
4005 | break; | ||
3710 | 4006 | ||
3711 | case SIOCGIWENCODE: | 4007 | err = hermes_inquire(hw, HERMES_INQ_SCAN); |
3712 | if (! capable(CAP_NET_ADMIN)) { | ||
3713 | err = -EPERM; | ||
3714 | break; | 4008 | break; |
3715 | } | 4009 | } |
4010 | } else | ||
4011 | err = hermes_inquire(hw, HERMES_INQ_SCAN); | ||
3716 | 4012 | ||
3717 | err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding); | 4013 | /* One more client */ |
3718 | break; | 4014 | if (! err) |
3719 | 4015 | priv->scan_inprogress = 1; | |
3720 | case SIOCSIWESSID: | ||
3721 | err = orinoco_ioctl_setessid(dev, &wrq->u.essid); | ||
3722 | if (! err) | ||
3723 | changed = 1; | ||
3724 | break; | ||
3725 | 4016 | ||
3726 | case SIOCGIWESSID: | 4017 | out: |
3727 | err = orinoco_ioctl_getessid(dev, &wrq->u.essid); | 4018 | orinoco_unlock(priv, &flags); |
3728 | break; | 4019 | return err; |
4020 | } | ||
3729 | 4021 | ||
3730 | case SIOCSIWNICKN: | 4022 | /* Translate scan data returned from the card to a card independant |
3731 | err = orinoco_ioctl_setnick(dev, &wrq->u.data); | 4023 | * format that the Wireless Tools will understand - Jean II */ |
3732 | if (! err) | 4024 | static inline int orinoco_translate_scan(struct net_device *dev, |
3733 | changed = 1; | 4025 | char *buffer, |
3734 | break; | 4026 | char *scan, |
4027 | int scan_len) | ||
4028 | { | ||
4029 | struct orinoco_private *priv = netdev_priv(dev); | ||
4030 | int offset; /* In the scan data */ | ||
4031 | union hermes_scan_info *atom; | ||
4032 | int atom_len; | ||
4033 | u16 capabilities; | ||
4034 | u16 channel; | ||
4035 | struct iw_event iwe; /* Temporary buffer */ | ||
4036 | char * current_ev = buffer; | ||
4037 | char * end_buf = buffer + IW_SCAN_MAX_DATA; | ||
3735 | 4038 | ||
3736 | case SIOCGIWNICKN: | 4039 | switch (priv->firmware_type) { |
3737 | err = orinoco_ioctl_getnick(dev, &wrq->u.data); | 4040 | case FIRMWARE_TYPE_AGERE: |
4041 | atom_len = sizeof(struct agere_scan_apinfo); | ||
4042 | offset = 0; | ||
3738 | break; | 4043 | break; |
3739 | 4044 | case FIRMWARE_TYPE_SYMBOL: | |
3740 | case SIOCGIWFREQ: | 4045 | /* Lack of documentation necessitates this hack. |
3741 | tmp = orinoco_hw_get_freq(priv); | 4046 | * Different firmwares have 68 or 76 byte long atoms. |
3742 | if (tmp < 0) { | 4047 | * We try modulo first. If the length divides by both, |
3743 | err = tmp; | 4048 | * we check what would be the channel in the second |
3744 | } else { | 4049 | * frame for a 68-byte atom. 76-byte atoms have 0 there. |
3745 | wrq->u.freq.m = tmp; | 4050 | * Valid channel cannot be 0. */ |
3746 | wrq->u.freq.e = 1; | 4051 | if (scan_len % 76) |
3747 | } | 4052 | atom_len = 68; |
4053 | else if (scan_len % 68) | ||
4054 | atom_len = 76; | ||
4055 | else if (scan_len >= 1292 && scan[68] == 0) | ||
4056 | atom_len = 76; | ||
4057 | else | ||
4058 | atom_len = 68; | ||
4059 | offset = 0; | ||
3748 | break; | 4060 | break; |
3749 | 4061 | case FIRMWARE_TYPE_INTERSIL: | |
3750 | case SIOCSIWFREQ: | 4062 | offset = 4; |
3751 | err = orinoco_ioctl_setfreq(dev, &wrq->u.freq); | 4063 | if (priv->has_hostscan) |
3752 | if (! err) | 4064 | atom_len = scan[0] + (scan[1] << 8); |
3753 | changed = 1; | 4065 | else |
4066 | atom_len = offsetof(struct prism2_scan_apinfo, atim); | ||
3754 | break; | 4067 | break; |
4068 | default: | ||
4069 | return 0; | ||
4070 | } | ||
3755 | 4071 | ||
3756 | case SIOCGIWSENS: | 4072 | /* Check that we got an whole number of atoms */ |
3757 | err = orinoco_ioctl_getsens(dev, &wrq->u.sens); | 4073 | if ((scan_len - offset) % atom_len) { |
3758 | break; | 4074 | printk(KERN_ERR "%s: Unexpected scan data length %d, " |
4075 | "atom_len %d, offset %d\n", dev->name, scan_len, | ||
4076 | atom_len, offset); | ||
4077 | return 0; | ||
4078 | } | ||
3759 | 4079 | ||
3760 | case SIOCSIWSENS: | 4080 | /* Read the entries one by one */ |
3761 | err = orinoco_ioctl_setsens(dev, &wrq->u.sens); | 4081 | for (; offset + atom_len <= scan_len; offset += atom_len) { |
3762 | if (! err) | 4082 | /* Get next atom */ |
3763 | changed = 1; | 4083 | atom = (union hermes_scan_info *) (scan + offset); |
3764 | break; | 4084 | |
4085 | /* First entry *MUST* be the AP MAC address */ | ||
4086 | iwe.cmd = SIOCGIWAP; | ||
4087 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
4088 | memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN); | ||
4089 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); | ||
4090 | |||
4091 | /* Other entries will be displayed in the order we give them */ | ||
4092 | |||
4093 | /* Add the ESSID */ | ||
4094 | iwe.u.data.length = le16_to_cpu(atom->a.essid_len); | ||
4095 | if (iwe.u.data.length > 32) | ||
4096 | iwe.u.data.length = 32; | ||
4097 | iwe.cmd = SIOCGIWESSID; | ||
4098 | iwe.u.data.flags = 1; | ||
4099 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid); | ||
4100 | |||
4101 | /* Add mode */ | ||
4102 | iwe.cmd = SIOCGIWMODE; | ||
4103 | capabilities = le16_to_cpu(atom->a.capabilities); | ||
4104 | if (capabilities & 0x3) { | ||
4105 | if (capabilities & 0x1) | ||
4106 | iwe.u.mode = IW_MODE_MASTER; | ||
4107 | else | ||
4108 | iwe.u.mode = IW_MODE_ADHOC; | ||
4109 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); | ||
4110 | } | ||
3765 | 4111 | ||
3766 | case SIOCGIWRTS: | 4112 | channel = atom->s.channel; |
3767 | wrq->u.rts.value = priv->rts_thresh; | 4113 | if ( (channel >= 1) && (channel <= NUM_CHANNELS) ) { |
3768 | wrq->u.rts.disabled = (wrq->u.rts.value == 2347); | 4114 | /* Add frequency */ |
3769 | wrq->u.rts.fixed = 1; | 4115 | iwe.cmd = SIOCGIWFREQ; |
3770 | break; | 4116 | iwe.u.freq.m = channel_frequency[channel-1] * 100000; |
4117 | iwe.u.freq.e = 1; | ||
4118 | current_ev = iwe_stream_add_event(current_ev, end_buf, | ||
4119 | &iwe, IW_EV_FREQ_LEN); | ||
4120 | } | ||
3771 | 4121 | ||
3772 | case SIOCSIWRTS: | 4122 | /* Add quality statistics */ |
3773 | err = orinoco_ioctl_setrts(dev, &wrq->u.rts); | 4123 | iwe.cmd = IWEVQUAL; |
3774 | if (! err) | 4124 | iwe.u.qual.updated = 0x10; /* no link quality */ |
3775 | changed = 1; | 4125 | iwe.u.qual.level = (__u8) le16_to_cpu(atom->a.level) - 0x95; |
3776 | break; | 4126 | iwe.u.qual.noise = (__u8) le16_to_cpu(atom->a.noise) - 0x95; |
4127 | /* Wireless tools prior to 27.pre22 will show link quality | ||
4128 | * anyway, so we provide a reasonable value. */ | ||
4129 | if (iwe.u.qual.level > iwe.u.qual.noise) | ||
4130 | iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; | ||
4131 | else | ||
4132 | iwe.u.qual.qual = 0; | ||
4133 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); | ||
3777 | 4134 | ||
3778 | case SIOCSIWFRAG: | 4135 | /* Add encryption capability */ |
3779 | err = orinoco_ioctl_setfrag(dev, &wrq->u.frag); | 4136 | iwe.cmd = SIOCGIWENCODE; |
3780 | if (! err) | 4137 | if (capabilities & 0x10) |
3781 | changed = 1; | 4138 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; |
3782 | break; | 4139 | else |
4140 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
4141 | iwe.u.data.length = 0; | ||
4142 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid); | ||
4143 | |||
4144 | /* Bit rate is not available in Lucent/Agere firmwares */ | ||
4145 | if (priv->firmware_type != FIRMWARE_TYPE_AGERE) { | ||
4146 | char * current_val = current_ev + IW_EV_LCP_LEN; | ||
4147 | int i; | ||
4148 | int step; | ||
4149 | |||
4150 | if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) | ||
4151 | step = 2; | ||
4152 | else | ||
4153 | step = 1; | ||
4154 | |||
4155 | iwe.cmd = SIOCGIWRATE; | ||
4156 | /* Those two flags are ignored... */ | ||
4157 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | ||
4158 | /* Max 10 values */ | ||
4159 | for (i = 0; i < 10; i += step) { | ||
4160 | /* NULL terminated */ | ||
4161 | if (atom->p.rates[i] == 0x0) | ||
4162 | break; | ||
4163 | /* Bit rate given in 500 kb/s units (+ 0x80) */ | ||
4164 | iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000); | ||
4165 | current_val = iwe_stream_add_value(current_ev, current_val, | ||
4166 | end_buf, &iwe, | ||
4167 | IW_EV_PARAM_LEN); | ||
4168 | } | ||
4169 | /* Check if we added any event */ | ||
4170 | if ((current_val - current_ev) > IW_EV_LCP_LEN) | ||
4171 | current_ev = current_val; | ||
4172 | } | ||
3783 | 4173 | ||
3784 | case SIOCGIWFRAG: | 4174 | /* The other data in the scan result are not really |
3785 | err = orinoco_ioctl_getfrag(dev, &wrq->u.frag); | 4175 | * interesting, so for now drop it - Jean II */ |
3786 | break; | 4176 | } |
4177 | return current_ev - buffer; | ||
4178 | } | ||
3787 | 4179 | ||
3788 | case SIOCSIWRATE: | 4180 | /* Return results of a scan */ |
3789 | err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate); | 4181 | static int orinoco_ioctl_getscan(struct net_device *dev, |
3790 | if (! err) | 4182 | struct iw_request_info *info, |
3791 | changed = 1; | 4183 | struct iw_point *srq, |
3792 | break; | 4184 | char *extra) |
4185 | { | ||
4186 | struct orinoco_private *priv = netdev_priv(dev); | ||
4187 | int err = 0; | ||
4188 | unsigned long flags; | ||
3793 | 4189 | ||
3794 | case SIOCGIWRATE: | 4190 | if (orinoco_lock(priv, &flags) != 0) |
3795 | err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate); | 4191 | return -EBUSY; |
3796 | break; | ||
3797 | 4192 | ||
3798 | case SIOCSIWPOWER: | 4193 | /* If no results yet, ask to try again later */ |
3799 | err = orinoco_ioctl_setpower(dev, &wrq->u.power); | 4194 | if (priv->scan_result == NULL) { |
3800 | if (! err) | 4195 | if (priv->scan_inprogress) |
3801 | changed = 1; | 4196 | /* Important note : we don't want to block the caller |
3802 | break; | 4197 | * until results are ready for various reasons. |
4198 | * First, managing wait queues is complex and racy. | ||
4199 | * Second, we grab some rtnetlink lock before comming | ||
4200 | * here (in dev_ioctl()). | ||
4201 | * Third, we generate an Wireless Event, so the | ||
4202 | * caller can wait itself on that - Jean II */ | ||
4203 | err = -EAGAIN; | ||
4204 | else | ||
4205 | /* Client error, no scan results... | ||
4206 | * The caller need to restart the scan. */ | ||
4207 | err = -ENODATA; | ||
4208 | } else { | ||
4209 | /* We have some results to push back to user space */ | ||
4210 | |||
4211 | /* Translate to WE format */ | ||
4212 | srq->length = orinoco_translate_scan(dev, extra, | ||
4213 | priv->scan_result, | ||
4214 | priv->scan_len); | ||
4215 | |||
4216 | /* Return flags */ | ||
4217 | srq->flags = (__u16) priv->scan_mode; | ||
4218 | |||
4219 | /* Results are here, so scan no longer in progress */ | ||
4220 | priv->scan_inprogress = 0; | ||
4221 | |||
4222 | /* In any case, Scan results will be cleaned up in the | ||
4223 | * reset function and when exiting the driver. | ||
4224 | * The person triggering the scanning may never come to | ||
4225 | * pick the results, so we need to do it in those places. | ||
4226 | * Jean II */ | ||
4227 | |||
4228 | #ifdef SCAN_SINGLE_READ | ||
4229 | /* If you enable this option, only one client (the first | ||
4230 | * one) will be able to read the result (and only one | ||
4231 | * time). If there is multiple concurent clients that | ||
4232 | * want to read scan results, this behavior is not | ||
4233 | * advisable - Jean II */ | ||
4234 | kfree(priv->scan_result); | ||
4235 | priv->scan_result = NULL; | ||
4236 | #endif /* SCAN_SINGLE_READ */ | ||
4237 | /* Here, if too much time has elapsed since last scan, | ||
4238 | * we may want to clean up scan results... - Jean II */ | ||
4239 | } | ||
4240 | |||
4241 | orinoco_unlock(priv, &flags); | ||
4242 | return err; | ||
4243 | } | ||
3803 | 4244 | ||
3804 | case SIOCGIWPOWER: | 4245 | /* Commit handler, called after set operations */ |
3805 | err = orinoco_ioctl_getpower(dev, &wrq->u.power); | 4246 | static int orinoco_ioctl_commit(struct net_device *dev, |
3806 | break; | 4247 | struct iw_request_info *info, |
4248 | void *wrqu, | ||
4249 | char *extra) | ||
4250 | { | ||
4251 | struct orinoco_private *priv = netdev_priv(dev); | ||
4252 | struct hermes *hw = &priv->hw; | ||
4253 | unsigned long flags; | ||
4254 | int err = 0; | ||
3807 | 4255 | ||
3808 | case SIOCGIWTXPOW: | 4256 | if (!priv->open) |
3809 | /* The card only supports one tx power, so this is easy */ | 4257 | return 0; |
3810 | wrq->u.txpower.value = 15; /* dBm */ | ||
3811 | wrq->u.txpower.fixed = 1; | ||
3812 | wrq->u.txpower.disabled = 0; | ||
3813 | wrq->u.txpower.flags = IW_TXPOW_DBM; | ||
3814 | break; | ||
3815 | 4258 | ||
3816 | case SIOCSIWRETRY: | 4259 | if (priv->broken_disableport) { |
3817 | err = -EOPNOTSUPP; | 4260 | orinoco_reset(dev); |
3818 | break; | 4261 | return 0; |
4262 | } | ||
3819 | 4263 | ||
3820 | case SIOCGIWRETRY: | 4264 | if (orinoco_lock(priv, &flags) != 0) |
3821 | err = orinoco_ioctl_getretry(dev, &wrq->u.retry); | 4265 | return err; |
3822 | break; | ||
3823 | 4266 | ||
3824 | case SIOCSIWSPY: | 4267 | err = hermes_disable_port(hw, 0); |
3825 | err = orinoco_ioctl_setspy(dev, &wrq->u.data); | 4268 | if (err) { |
3826 | break; | 4269 | printk(KERN_WARNING "%s: Unable to disable port " |
4270 | "while reconfiguring card\n", dev->name); | ||
4271 | priv->broken_disableport = 1; | ||
4272 | goto out; | ||
4273 | } | ||
3827 | 4274 | ||
3828 | case SIOCGIWSPY: | 4275 | err = __orinoco_program_rids(dev); |
3829 | err = orinoco_ioctl_getspy(dev, &wrq->u.data); | 4276 | if (err) { |
3830 | break; | 4277 | printk(KERN_WARNING "%s: Unable to reconfigure card\n", |
4278 | dev->name); | ||
4279 | goto out; | ||
4280 | } | ||
3831 | 4281 | ||
3832 | case SIOCGIWPRIV: | 4282 | err = hermes_enable_port(hw, 0); |
3833 | if (wrq->u.data.pointer) { | 4283 | if (err) { |
3834 | struct iw_priv_args privtab[] = { | 4284 | printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", |
3835 | { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, | 4285 | dev->name); |
3836 | { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, | 4286 | goto out; |
3837 | { SIOCIWFIRSTPRIV + 0x2, | 4287 | } |
3838 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3839 | 0, "set_port3" }, | ||
3840 | { SIOCIWFIRSTPRIV + 0x3, 0, | ||
3841 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3842 | "get_port3" }, | ||
3843 | { SIOCIWFIRSTPRIV + 0x4, | ||
3844 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3845 | 0, "set_preamble" }, | ||
3846 | { SIOCIWFIRSTPRIV + 0x5, 0, | ||
3847 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3848 | "get_preamble" }, | ||
3849 | { SIOCIWFIRSTPRIV + 0x6, | ||
3850 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3851 | 0, "set_ibssport" }, | ||
3852 | { SIOCIWFIRSTPRIV + 0x7, 0, | ||
3853 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
3854 | "get_ibssport" }, | ||
3855 | }; | ||
3856 | |||
3857 | wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); | ||
3858 | if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab))) | ||
3859 | err = -EFAULT; | ||
3860 | } | ||
3861 | break; | ||
3862 | |||
3863 | case SIOCIWFIRSTPRIV + 0x0: /* force_reset */ | ||
3864 | case SIOCIWFIRSTPRIV + 0x1: /* card_reset */ | ||
3865 | if (! capable(CAP_NET_ADMIN)) { | ||
3866 | err = -EPERM; | ||
3867 | break; | ||
3868 | } | ||
3869 | |||
3870 | printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); | ||
3871 | 4288 | ||
4289 | out: | ||
4290 | if (err) { | ||
4291 | printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); | ||
3872 | schedule_work(&priv->reset_work); | 4292 | schedule_work(&priv->reset_work); |
3873 | break; | 4293 | err = 0; |
3874 | 4294 | } | |
3875 | case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */ | ||
3876 | if (! capable(CAP_NET_ADMIN)) { | ||
3877 | err = -EPERM; | ||
3878 | break; | ||
3879 | } | ||
3880 | |||
3881 | err = orinoco_ioctl_setport3(dev, wrq); | ||
3882 | if (! err) | ||
3883 | changed = 1; | ||
3884 | break; | ||
3885 | 4295 | ||
3886 | case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */ | 4296 | orinoco_unlock(priv, &flags); |
3887 | err = orinoco_ioctl_getport3(dev, wrq); | 4297 | return err; |
3888 | break; | 4298 | } |
3889 | 4299 | ||
3890 | case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */ | 4300 | static const struct iw_priv_args orinoco_privtab[] = { |
3891 | if (! capable(CAP_NET_ADMIN)) { | 4301 | { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, |
3892 | err = -EPERM; | 4302 | { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, |
3893 | break; | 4303 | { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
3894 | } | 4304 | 0, "set_port3" }, |
4305 | { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4306 | "get_port3" }, | ||
4307 | { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4308 | 0, "set_preamble" }, | ||
4309 | { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4310 | "get_preamble" }, | ||
4311 | { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4312 | 0, "set_ibssport" }, | ||
4313 | { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
4314 | "get_ibssport" }, | ||
4315 | { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN, | ||
4316 | "get_rid" }, | ||
4317 | }; | ||
3895 | 4318 | ||
3896 | /* 802.11b has recently defined some short preamble. | ||
3897 | * Basically, the Phy header has been reduced in size. | ||
3898 | * This increase performance, especially at high rates | ||
3899 | * (the preamble is transmitted at 1Mb/s), unfortunately | ||
3900 | * this give compatibility troubles... - Jean II */ | ||
3901 | if(priv->has_preamble) { | ||
3902 | int val = *( (int *) wrq->u.name ); | ||
3903 | |||
3904 | if (orinoco_lock(priv, &flags) != 0) | ||
3905 | return -EBUSY; | ||
3906 | if (val) | ||
3907 | priv->preamble = 1; | ||
3908 | else | ||
3909 | priv->preamble = 0; | ||
3910 | orinoco_unlock(priv, &flags); | ||
3911 | changed = 1; | ||
3912 | } else | ||
3913 | err = -EOPNOTSUPP; | ||
3914 | break; | ||
3915 | 4319 | ||
3916 | case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */ | 4320 | /* |
3917 | if(priv->has_preamble) { | 4321 | * Structures to export the Wireless Handlers |
3918 | int *val = (int *)wrq->u.name; | 4322 | */ |
3919 | 4323 | ||
3920 | if (orinoco_lock(priv, &flags) != 0) | 4324 | static const iw_handler orinoco_handler[] = { |
3921 | return -EBUSY; | 4325 | [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit, |
3922 | *val = priv->preamble; | 4326 | [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname, |
3923 | orinoco_unlock(priv, &flags); | 4327 | [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq, |
3924 | } else | 4328 | [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq, |
3925 | err = -EOPNOTSUPP; | 4329 | [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode, |
3926 | break; | 4330 | [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode, |
3927 | case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */ | 4331 | [SIOCSIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens, |
3928 | if (! capable(CAP_NET_ADMIN)) { | 4332 | [SIOCGIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens, |
3929 | err = -EPERM; | 4333 | [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange, |
3930 | break; | 4334 | [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy, |
3931 | } | 4335 | [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy, |
4336 | [SIOCSIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setwap, | ||
4337 | [SIOCGIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap, | ||
4338 | [SIOCSIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setscan, | ||
4339 | [SIOCGIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getscan, | ||
4340 | [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid, | ||
4341 | [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid, | ||
4342 | [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick, | ||
4343 | [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick, | ||
4344 | [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate, | ||
4345 | [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate, | ||
4346 | [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts, | ||
4347 | [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts, | ||
4348 | [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag, | ||
4349 | [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag, | ||
4350 | [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry, | ||
4351 | [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode, | ||
4352 | [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode, | ||
4353 | [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower, | ||
4354 | [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower, | ||
4355 | }; | ||
3932 | 4356 | ||
3933 | err = orinoco_ioctl_setibssport(dev, wrq); | ||
3934 | if (! err) | ||
3935 | changed = 1; | ||
3936 | break; | ||
3937 | 4357 | ||
3938 | case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */ | 4358 | /* |
3939 | err = orinoco_ioctl_getibssport(dev, wrq); | 4359 | Added typecasting since we no longer use iwreq_data -- Moustafa |
3940 | break; | 4360 | */ |
4361 | static const iw_handler orinoco_private_handler[] = { | ||
4362 | [0] (iw_handler) orinoco_ioctl_reset, | ||
4363 | [1] (iw_handler) orinoco_ioctl_reset, | ||
4364 | [2] (iw_handler) orinoco_ioctl_setport3, | ||
4365 | [3] (iw_handler) orinoco_ioctl_getport3, | ||
4366 | [4] (iw_handler) orinoco_ioctl_setpreamble, | ||
4367 | [5] (iw_handler) orinoco_ioctl_getpreamble, | ||
4368 | [6] (iw_handler) orinoco_ioctl_setibssport, | ||
4369 | [7] (iw_handler) orinoco_ioctl_getibssport, | ||
4370 | [9] (iw_handler) orinoco_ioctl_getrid, | ||
4371 | }; | ||
3941 | 4372 | ||
3942 | default: | 4373 | static const struct iw_handler_def orinoco_handler_def = { |
3943 | err = -EOPNOTSUPP; | 4374 | .num_standard = ARRAY_SIZE(orinoco_handler), |
3944 | } | 4375 | .num_private = ARRAY_SIZE(orinoco_private_handler), |
3945 | 4376 | .num_private_args = ARRAY_SIZE(orinoco_privtab), | |
3946 | if (! err && changed && netif_running(dev)) { | 4377 | .standard = orinoco_handler, |
3947 | err = orinoco_reconfigure(dev); | 4378 | .private = orinoco_private_handler, |
3948 | } | 4379 | .private_args = orinoco_privtab, |
4380 | }; | ||
3949 | 4381 | ||
3950 | TRACE_EXIT(dev->name); | 4382 | static void orinoco_get_drvinfo(struct net_device *dev, |
4383 | struct ethtool_drvinfo *info) | ||
4384 | { | ||
4385 | struct orinoco_private *priv = netdev_priv(dev); | ||
3951 | 4386 | ||
3952 | return err; | 4387 | strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1); |
4388 | strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1); | ||
4389 | strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1); | ||
4390 | if (dev->class_dev.dev) | ||
4391 | strncpy(info->bus_info, dev->class_dev.dev->bus_id, | ||
4392 | sizeof(info->bus_info) - 1); | ||
4393 | else | ||
4394 | snprintf(info->bus_info, sizeof(info->bus_info) - 1, | ||
4395 | "PCMCIA %p", priv->hw.iobase); | ||
3953 | } | 4396 | } |
3954 | 4397 | ||
4398 | static struct ethtool_ops orinoco_ethtool_ops = { | ||
4399 | .get_drvinfo = orinoco_get_drvinfo, | ||
4400 | .get_link = ethtool_op_get_link, | ||
4401 | }; | ||
3955 | 4402 | ||
3956 | /********************************************************************/ | 4403 | /********************************************************************/ |
3957 | /* Debugging */ | 4404 | /* 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 c149c06388be..d79cd218a551 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -32,6 +32,7 @@ obj-$(CONFIG_USB_MOUSE) += input/ | |||
32 | obj-$(CONFIG_USB_MTOUCH) += input/ | 32 | obj-$(CONFIG_USB_MTOUCH) += input/ |
33 | obj-$(CONFIG_USB_POWERMATE) += input/ | 33 | obj-$(CONFIG_USB_POWERMATE) += input/ |
34 | obj-$(CONFIG_USB_WACOM) += input/ | 34 | obj-$(CONFIG_USB_WACOM) += input/ |
35 | obj-$(CONFIG_USB_ACECAD) += input/ | ||
35 | obj-$(CONFIG_USB_XPAD) += input/ | 36 | obj-$(CONFIG_USB_XPAD) += input/ |
36 | 37 | ||
37 | obj-$(CONFIG_USB_DABUSB) += media/ | 38 | obj-$(CONFIG_USB_DABUSB) += media/ |
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/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 7d30f55ad7bd..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,21 +621,21 @@ 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); |
@@ -661,27 +646,27 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) | |||
661 | { | 646 | { |
662 | struct usb_device *udev = ati_remote->udev; | 647 | struct usb_device *udev = ati_remote->udev; |
663 | int pipe, maxp; | 648 | int pipe, maxp; |
664 | 649 | ||
665 | init_waitqueue_head(&ati_remote->wait); | 650 | init_waitqueue_head(&ati_remote->wait); |
666 | 651 | ||
667 | /* Set up irq_urb */ | 652 | /* Set up irq_urb */ |
668 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); | 653 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); |
669 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 654 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
670 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | 655 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; |
671 | 656 | ||
672 | 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, |
673 | maxp, ati_remote_irq_in, ati_remote, | 658 | maxp, ati_remote_irq_in, ati_remote, |
674 | ati_remote->endpoint_in->bInterval); | 659 | ati_remote->endpoint_in->bInterval); |
675 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; | 660 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; |
676 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 661 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
677 | 662 | ||
678 | /* Set up out_urb */ | 663 | /* Set up out_urb */ |
679 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); | 664 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); |
680 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 665 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
681 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | 666 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; |
682 | 667 | ||
683 | 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, |
684 | maxp, ati_remote_irq_out, ati_remote, | 669 | maxp, ati_remote_irq_out, ati_remote, |
685 | ati_remote->endpoint_out->bInterval); | 670 | ati_remote->endpoint_out->bInterval); |
686 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; | 671 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; |
687 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 672 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
@@ -689,11 +674,11 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) | |||
689 | /* send initialization strings */ | 674 | /* send initialization strings */ |
690 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || | 675 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || |
691 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { | 676 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { |
692 | dev_err(&ati_remote->interface->dev, | 677 | dev_err(&ati_remote->interface->dev, |
693 | "Initializing ati_remote hardware failed.\n"); | 678 | "Initializing ati_remote hardware failed.\n"); |
694 | return 1; | 679 | return 1; |
695 | } | 680 | } |
696 | 681 | ||
697 | return 0; | 682 | return 0; |
698 | } | 683 | } |
699 | 684 | ||
@@ -770,7 +755,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
770 | 755 | ||
771 | if (!strlen(ati_remote->name)) | 756 | if (!strlen(ati_remote->name)) |
772 | sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", | 757 | sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", |
773 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), | 758 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), |
774 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); | 759 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); |
775 | 760 | ||
776 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ | 761 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ |
@@ -782,11 +767,11 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
782 | ati_remote_input_init(ati_remote); | 767 | ati_remote_input_init(ati_remote); |
783 | input_register_device(&ati_remote->idev); | 768 | input_register_device(&ati_remote->idev); |
784 | 769 | ||
785 | 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", |
786 | ati_remote->name, path); | 771 | ati_remote->name, path); |
787 | 772 | ||
788 | usb_set_intfdata(interface, ati_remote); | 773 | usb_set_intfdata(interface, ati_remote); |
789 | 774 | ||
790 | error: | 775 | error: |
791 | if (retval) | 776 | if (retval) |
792 | ati_remote_delete(ati_remote); | 777 | ati_remote_delete(ati_remote); |
@@ -801,18 +786,14 @@ static void ati_remote_disconnect(struct usb_interface *interface) | |||
801 | { | 786 | { |
802 | struct ati_remote *ati_remote; | 787 | struct ati_remote *ati_remote; |
803 | 788 | ||
804 | down(&disconnect_sem); | ||
805 | |||
806 | ati_remote = usb_get_intfdata(interface); | 789 | ati_remote = usb_get_intfdata(interface); |
807 | usb_set_intfdata(interface, NULL); | 790 | usb_set_intfdata(interface, NULL); |
808 | if (!ati_remote) { | 791 | if (!ati_remote) { |
809 | warn("%s - null device?\n", __FUNCTION__); | 792 | warn("%s - null device?\n", __FUNCTION__); |
810 | return; | 793 | return; |
811 | } | 794 | } |
812 | |||
813 | ati_remote_delete(ati_remote); | ||
814 | 795 | ||
815 | up(&disconnect_sem); | 796 | ati_remote_delete(ati_remote); |
816 | } | 797 | } |
817 | 798 | ||
818 | /* | 799 | /* |
@@ -821,7 +802,7 @@ static void ati_remote_disconnect(struct usb_interface *interface) | |||
821 | static int __init ati_remote_init(void) | 802 | static int __init ati_remote_init(void) |
822 | { | 803 | { |
823 | int result; | 804 | int result; |
824 | 805 | ||
825 | result = usb_register(&ati_remote_driver); | 806 | result = usb_register(&ati_remote_driver); |
826 | if (result) | 807 | if (result) |
827 | err("usb_register error #%d\n", result); | 808 | err("usb_register error #%d\n", result); |
@@ -839,8 +820,8 @@ static void __exit ati_remote_exit(void) | |||
839 | usb_deregister(&ati_remote_driver); | 820 | usb_deregister(&ati_remote_driver); |
840 | } | 821 | } |
841 | 822 | ||
842 | /* | 823 | /* |
843 | * module specification | 824 | * module specification |
844 | */ | 825 | */ |
845 | 826 | ||
846 | 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/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/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/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/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-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/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/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/include/net/ieee80211.h b/include/net/ieee80211.h new file mode 100644 index 000000000000..7fe57f957a51 --- /dev/null +++ b/include/net/ieee80211.h | |||
@@ -0,0 +1,882 @@ | |||
1 | /* | ||
2 | * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11 | ||
3 | * remains copyright by the original authors | ||
4 | * | ||
5 | * Portions of the merged code are based on Host AP (software wireless | ||
6 | * LAN access point) driver for Intersil Prism2/2.5/3. | ||
7 | * | ||
8 | * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen | ||
9 | * <jkmaline@cc.hut.fi> | ||
10 | * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
11 | * | ||
12 | * Adaption to a generic IEEE 802.11 stack by James Ketrenos | ||
13 | * <jketreno@linux.intel.com> | ||
14 | * Copyright (c) 2004, Intel Corporation | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License version 2 as | ||
18 | * published by the Free Software Foundation. See README and COPYING for | ||
19 | * more details. | ||
20 | */ | ||
21 | #ifndef IEEE80211_H | ||
22 | #define IEEE80211_H | ||
23 | |||
24 | #include <linux/if_ether.h> /* ETH_ALEN */ | ||
25 | #include <linux/kernel.h> /* ARRAY_SIZE */ | ||
26 | |||
27 | #if WIRELESS_EXT < 17 | ||
28 | #define IW_QUAL_QUAL_INVALID 0x10 | ||
29 | #define IW_QUAL_LEVEL_INVALID 0x20 | ||
30 | #define IW_QUAL_NOISE_INVALID 0x40 | ||
31 | #define IW_QUAL_QUAL_UPDATED 0x1 | ||
32 | #define IW_QUAL_LEVEL_UPDATED 0x2 | ||
33 | #define IW_QUAL_NOISE_UPDATED 0x4 | ||
34 | #endif | ||
35 | |||
36 | #define IEEE80211_DATA_LEN 2304 | ||
37 | /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section | ||
38 | 6.2.1.1.2. | ||
39 | |||
40 | The figure in section 7.1.2 suggests a body size of up to 2312 | ||
41 | bytes is allowed, which is a bit confusing, I suspect this | ||
42 | represents the 2304 bytes of real data, plus a possible 8 bytes of | ||
43 | WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ | ||
44 | |||
45 | |||
46 | #define IEEE80211_HLEN 30 | ||
47 | #define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) | ||
48 | |||
49 | struct ieee80211_hdr { | ||
50 | u16 frame_ctl; | ||
51 | u16 duration_id; | ||
52 | u8 addr1[ETH_ALEN]; | ||
53 | u8 addr2[ETH_ALEN]; | ||
54 | u8 addr3[ETH_ALEN]; | ||
55 | u16 seq_ctl; | ||
56 | u8 addr4[ETH_ALEN]; | ||
57 | } __attribute__ ((packed)); | ||
58 | |||
59 | struct ieee80211_hdr_3addr { | ||
60 | u16 frame_ctl; | ||
61 | u16 duration_id; | ||
62 | u8 addr1[ETH_ALEN]; | ||
63 | u8 addr2[ETH_ALEN]; | ||
64 | u8 addr3[ETH_ALEN]; | ||
65 | u16 seq_ctl; | ||
66 | } __attribute__ ((packed)); | ||
67 | |||
68 | enum eap_type { | ||
69 | EAP_PACKET = 0, | ||
70 | EAPOL_START, | ||
71 | EAPOL_LOGOFF, | ||
72 | EAPOL_KEY, | ||
73 | EAPOL_ENCAP_ASF_ALERT | ||
74 | }; | ||
75 | |||
76 | static const char *eap_types[] = { | ||
77 | [EAP_PACKET] = "EAP-Packet", | ||
78 | [EAPOL_START] = "EAPOL-Start", | ||
79 | [EAPOL_LOGOFF] = "EAPOL-Logoff", | ||
80 | [EAPOL_KEY] = "EAPOL-Key", | ||
81 | [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert" | ||
82 | }; | ||
83 | |||
84 | static inline const char *eap_get_type(int type) | ||
85 | { | ||
86 | return (type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type]; | ||
87 | } | ||
88 | |||
89 | struct eapol { | ||
90 | u8 snap[6]; | ||
91 | u16 ethertype; | ||
92 | u8 version; | ||
93 | u8 type; | ||
94 | u16 length; | ||
95 | } __attribute__ ((packed)); | ||
96 | |||
97 | #define IEEE80211_3ADDR_LEN 24 | ||
98 | #define IEEE80211_4ADDR_LEN 30 | ||
99 | #define IEEE80211_FCS_LEN 4 | ||
100 | |||
101 | #define MIN_FRAG_THRESHOLD 256U | ||
102 | #define MAX_FRAG_THRESHOLD 2346U | ||
103 | |||
104 | /* Frame control field constants */ | ||
105 | #define IEEE80211_FCTL_VERS 0x0002 | ||
106 | #define IEEE80211_FCTL_FTYPE 0x000c | ||
107 | #define IEEE80211_FCTL_STYPE 0x00f0 | ||
108 | #define IEEE80211_FCTL_TODS 0x0100 | ||
109 | #define IEEE80211_FCTL_FROMDS 0x0200 | ||
110 | #define IEEE80211_FCTL_MOREFRAGS 0x0400 | ||
111 | #define IEEE80211_FCTL_RETRY 0x0800 | ||
112 | #define IEEE80211_FCTL_PM 0x1000 | ||
113 | #define IEEE80211_FCTL_MOREDATA 0x2000 | ||
114 | #define IEEE80211_FCTL_WEP 0x4000 | ||
115 | #define IEEE80211_FCTL_ORDER 0x8000 | ||
116 | |||
117 | #define IEEE80211_FTYPE_MGMT 0x0000 | ||
118 | #define IEEE80211_FTYPE_CTL 0x0004 | ||
119 | #define IEEE80211_FTYPE_DATA 0x0008 | ||
120 | |||
121 | /* management */ | ||
122 | #define IEEE80211_STYPE_ASSOC_REQ 0x0000 | ||
123 | #define IEEE80211_STYPE_ASSOC_RESP 0x0010 | ||
124 | #define IEEE80211_STYPE_REASSOC_REQ 0x0020 | ||
125 | #define IEEE80211_STYPE_REASSOC_RESP 0x0030 | ||
126 | #define IEEE80211_STYPE_PROBE_REQ 0x0040 | ||
127 | #define IEEE80211_STYPE_PROBE_RESP 0x0050 | ||
128 | #define IEEE80211_STYPE_BEACON 0x0080 | ||
129 | #define IEEE80211_STYPE_ATIM 0x0090 | ||
130 | #define IEEE80211_STYPE_DISASSOC 0x00A0 | ||
131 | #define IEEE80211_STYPE_AUTH 0x00B0 | ||
132 | #define IEEE80211_STYPE_DEAUTH 0x00C0 | ||
133 | |||
134 | /* control */ | ||
135 | #define IEEE80211_STYPE_PSPOLL 0x00A0 | ||
136 | #define IEEE80211_STYPE_RTS 0x00B0 | ||
137 | #define IEEE80211_STYPE_CTS 0x00C0 | ||
138 | #define IEEE80211_STYPE_ACK 0x00D0 | ||
139 | #define IEEE80211_STYPE_CFEND 0x00E0 | ||
140 | #define IEEE80211_STYPE_CFENDACK 0x00F0 | ||
141 | |||
142 | /* data */ | ||
143 | #define IEEE80211_STYPE_DATA 0x0000 | ||
144 | #define IEEE80211_STYPE_DATA_CFACK 0x0010 | ||
145 | #define IEEE80211_STYPE_DATA_CFPOLL 0x0020 | ||
146 | #define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 | ||
147 | #define IEEE80211_STYPE_NULLFUNC 0x0040 | ||
148 | #define IEEE80211_STYPE_CFACK 0x0050 | ||
149 | #define IEEE80211_STYPE_CFPOLL 0x0060 | ||
150 | #define IEEE80211_STYPE_CFACKPOLL 0x0070 | ||
151 | |||
152 | #define IEEE80211_SCTL_FRAG 0x000F | ||
153 | #define IEEE80211_SCTL_SEQ 0xFFF0 | ||
154 | |||
155 | |||
156 | /* debug macros */ | ||
157 | |||
158 | #ifdef CONFIG_IEEE80211_DEBUG | ||
159 | extern u32 ieee80211_debug_level; | ||
160 | #define IEEE80211_DEBUG(level, fmt, args...) \ | ||
161 | do { if (ieee80211_debug_level & (level)) \ | ||
162 | printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ | ||
163 | in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) | ||
164 | #else | ||
165 | #define IEEE80211_DEBUG(level, fmt, args...) do {} while (0) | ||
166 | #endif /* CONFIG_IEEE80211_DEBUG */ | ||
167 | |||
168 | /* | ||
169 | * To use the debug system; | ||
170 | * | ||
171 | * If you are defining a new debug classification, simply add it to the #define | ||
172 | * list here in the form of: | ||
173 | * | ||
174 | * #define IEEE80211_DL_xxxx VALUE | ||
175 | * | ||
176 | * shifting value to the left one bit from the previous entry. xxxx should be | ||
177 | * the name of the classification (for example, WEP) | ||
178 | * | ||
179 | * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your | ||
180 | * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want | ||
181 | * to send output to that classification. | ||
182 | * | ||
183 | * To add your debug level to the list of levels seen when you perform | ||
184 | * | ||
185 | * % cat /proc/net/ipw/debug_level | ||
186 | * | ||
187 | * you simply need to add your entry to the ipw_debug_levels array. | ||
188 | * | ||
189 | * If you do not see debug_level in /proc/net/ipw then you do not have | ||
190 | * CONFIG_IEEE80211_DEBUG defined in your kernel configuration | ||
191 | * | ||
192 | */ | ||
193 | |||
194 | #define IEEE80211_DL_INFO (1<<0) | ||
195 | #define IEEE80211_DL_WX (1<<1) | ||
196 | #define IEEE80211_DL_SCAN (1<<2) | ||
197 | #define IEEE80211_DL_STATE (1<<3) | ||
198 | #define IEEE80211_DL_MGMT (1<<4) | ||
199 | #define IEEE80211_DL_FRAG (1<<5) | ||
200 | #define IEEE80211_DL_EAP (1<<6) | ||
201 | #define IEEE80211_DL_DROP (1<<7) | ||
202 | |||
203 | #define IEEE80211_DL_TX (1<<8) | ||
204 | #define IEEE80211_DL_RX (1<<9) | ||
205 | |||
206 | #define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) | ||
207 | #define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) | ||
208 | #define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a) | ||
209 | |||
210 | #define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a) | ||
211 | #define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a) | ||
212 | #define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a) | ||
213 | #define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a) | ||
214 | #define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a) | ||
215 | #define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a) | ||
216 | #define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) | ||
217 | #define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) | ||
218 | #define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) | ||
219 | #include <linux/netdevice.h> | ||
220 | #include <linux/wireless.h> | ||
221 | #include <linux/if_arp.h> /* ARPHRD_ETHER */ | ||
222 | |||
223 | #ifndef WIRELESS_SPY | ||
224 | #define WIRELESS_SPY // enable iwspy support | ||
225 | #endif | ||
226 | #include <net/iw_handler.h> // new driver API | ||
227 | |||
228 | #ifndef ETH_P_PAE | ||
229 | #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ | ||
230 | #endif /* ETH_P_PAE */ | ||
231 | |||
232 | #define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ | ||
233 | |||
234 | #ifndef ETH_P_80211_RAW | ||
235 | #define ETH_P_80211_RAW (ETH_P_ECONET + 1) | ||
236 | #endif | ||
237 | |||
238 | /* IEEE 802.11 defines */ | ||
239 | |||
240 | #define P80211_OUI_LEN 3 | ||
241 | |||
242 | struct ieee80211_snap_hdr { | ||
243 | |||
244 | u8 dsap; /* always 0xAA */ | ||
245 | u8 ssap; /* always 0xAA */ | ||
246 | u8 ctrl; /* always 0x03 */ | ||
247 | u8 oui[P80211_OUI_LEN]; /* organizational universal id */ | ||
248 | |||
249 | } __attribute__ ((packed)); | ||
250 | |||
251 | #define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) | ||
252 | |||
253 | #define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) | ||
254 | #define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) | ||
255 | |||
256 | #define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) | ||
257 | #define WLAN_GET_SEQ_SEQ(seq) ((seq) & IEEE80211_SCTL_SEQ) | ||
258 | |||
259 | /* Authentication algorithms */ | ||
260 | #define WLAN_AUTH_OPEN 0 | ||
261 | #define WLAN_AUTH_SHARED_KEY 1 | ||
262 | |||
263 | #define WLAN_AUTH_CHALLENGE_LEN 128 | ||
264 | |||
265 | #define WLAN_CAPABILITY_BSS (1<<0) | ||
266 | #define WLAN_CAPABILITY_IBSS (1<<1) | ||
267 | #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) | ||
268 | #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) | ||
269 | #define WLAN_CAPABILITY_PRIVACY (1<<4) | ||
270 | #define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) | ||
271 | #define WLAN_CAPABILITY_PBCC (1<<6) | ||
272 | #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) | ||
273 | |||
274 | /* Status codes */ | ||
275 | #define WLAN_STATUS_SUCCESS 0 | ||
276 | #define WLAN_STATUS_UNSPECIFIED_FAILURE 1 | ||
277 | #define WLAN_STATUS_CAPS_UNSUPPORTED 10 | ||
278 | #define WLAN_STATUS_REASSOC_NO_ASSOC 11 | ||
279 | #define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 | ||
280 | #define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 | ||
281 | #define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 | ||
282 | #define WLAN_STATUS_CHALLENGE_FAIL 15 | ||
283 | #define WLAN_STATUS_AUTH_TIMEOUT 16 | ||
284 | #define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 | ||
285 | #define WLAN_STATUS_ASSOC_DENIED_RATES 18 | ||
286 | /* 802.11b */ | ||
287 | #define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 | ||
288 | #define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 | ||
289 | #define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 | ||
290 | |||
291 | /* Reason codes */ | ||
292 | #define WLAN_REASON_UNSPECIFIED 1 | ||
293 | #define WLAN_REASON_PREV_AUTH_NOT_VALID 2 | ||
294 | #define WLAN_REASON_DEAUTH_LEAVING 3 | ||
295 | #define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 | ||
296 | #define WLAN_REASON_DISASSOC_AP_BUSY 5 | ||
297 | #define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 | ||
298 | #define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 | ||
299 | #define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 | ||
300 | #define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 | ||
301 | |||
302 | |||
303 | /* Information Element IDs */ | ||
304 | #define WLAN_EID_SSID 0 | ||
305 | #define WLAN_EID_SUPP_RATES 1 | ||
306 | #define WLAN_EID_FH_PARAMS 2 | ||
307 | #define WLAN_EID_DS_PARAMS 3 | ||
308 | #define WLAN_EID_CF_PARAMS 4 | ||
309 | #define WLAN_EID_TIM 5 | ||
310 | #define WLAN_EID_IBSS_PARAMS 6 | ||
311 | #define WLAN_EID_CHALLENGE 16 | ||
312 | #define WLAN_EID_RSN 48 | ||
313 | #define WLAN_EID_GENERIC 221 | ||
314 | |||
315 | #define IEEE80211_MGMT_HDR_LEN 24 | ||
316 | #define IEEE80211_DATA_HDR3_LEN 24 | ||
317 | #define IEEE80211_DATA_HDR4_LEN 30 | ||
318 | |||
319 | |||
320 | #define IEEE80211_STATMASK_SIGNAL (1<<0) | ||
321 | #define IEEE80211_STATMASK_RSSI (1<<1) | ||
322 | #define IEEE80211_STATMASK_NOISE (1<<2) | ||
323 | #define IEEE80211_STATMASK_RATE (1<<3) | ||
324 | #define IEEE80211_STATMASK_WEMASK 0x7 | ||
325 | |||
326 | |||
327 | #define IEEE80211_CCK_MODULATION (1<<0) | ||
328 | #define IEEE80211_OFDM_MODULATION (1<<1) | ||
329 | |||
330 | #define IEEE80211_24GHZ_BAND (1<<0) | ||
331 | #define IEEE80211_52GHZ_BAND (1<<1) | ||
332 | |||
333 | #define IEEE80211_CCK_RATE_1MB 0x02 | ||
334 | #define IEEE80211_CCK_RATE_2MB 0x04 | ||
335 | #define IEEE80211_CCK_RATE_5MB 0x0B | ||
336 | #define IEEE80211_CCK_RATE_11MB 0x16 | ||
337 | #define IEEE80211_OFDM_RATE_6MB 0x0C | ||
338 | #define IEEE80211_OFDM_RATE_9MB 0x12 | ||
339 | #define IEEE80211_OFDM_RATE_12MB 0x18 | ||
340 | #define IEEE80211_OFDM_RATE_18MB 0x24 | ||
341 | #define IEEE80211_OFDM_RATE_24MB 0x30 | ||
342 | #define IEEE80211_OFDM_RATE_36MB 0x48 | ||
343 | #define IEEE80211_OFDM_RATE_48MB 0x60 | ||
344 | #define IEEE80211_OFDM_RATE_54MB 0x6C | ||
345 | #define IEEE80211_BASIC_RATE_MASK 0x80 | ||
346 | |||
347 | #define IEEE80211_CCK_RATE_1MB_MASK (1<<0) | ||
348 | #define IEEE80211_CCK_RATE_2MB_MASK (1<<1) | ||
349 | #define IEEE80211_CCK_RATE_5MB_MASK (1<<2) | ||
350 | #define IEEE80211_CCK_RATE_11MB_MASK (1<<3) | ||
351 | #define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) | ||
352 | #define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) | ||
353 | #define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) | ||
354 | #define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) | ||
355 | #define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) | ||
356 | #define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) | ||
357 | #define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) | ||
358 | #define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) | ||
359 | |||
360 | #define IEEE80211_CCK_RATES_MASK 0x0000000F | ||
361 | #define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ | ||
362 | IEEE80211_CCK_RATE_2MB_MASK) | ||
363 | #define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ | ||
364 | IEEE80211_CCK_RATE_5MB_MASK | \ | ||
365 | IEEE80211_CCK_RATE_11MB_MASK) | ||
366 | |||
367 | #define IEEE80211_OFDM_RATES_MASK 0x00000FF0 | ||
368 | #define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ | ||
369 | IEEE80211_OFDM_RATE_12MB_MASK | \ | ||
370 | IEEE80211_OFDM_RATE_24MB_MASK) | ||
371 | #define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ | ||
372 | IEEE80211_OFDM_RATE_9MB_MASK | \ | ||
373 | IEEE80211_OFDM_RATE_18MB_MASK | \ | ||
374 | IEEE80211_OFDM_RATE_36MB_MASK | \ | ||
375 | IEEE80211_OFDM_RATE_48MB_MASK | \ | ||
376 | IEEE80211_OFDM_RATE_54MB_MASK) | ||
377 | #define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ | ||
378 | IEEE80211_CCK_DEFAULT_RATES_MASK) | ||
379 | |||
380 | #define IEEE80211_NUM_OFDM_RATES 8 | ||
381 | #define IEEE80211_NUM_CCK_RATES 4 | ||
382 | #define IEEE80211_OFDM_SHIFT_MASK_A 4 | ||
383 | |||
384 | |||
385 | |||
386 | |||
387 | /* NOTE: This data is for statistical purposes; not all hardware provides this | ||
388 | * information for frames received. Not setting these will not cause | ||
389 | * any adverse affects. */ | ||
390 | struct ieee80211_rx_stats { | ||
391 | u32 mac_time; | ||
392 | s8 rssi; | ||
393 | u8 signal; | ||
394 | u8 noise; | ||
395 | u16 rate; /* in 100 kbps */ | ||
396 | u8 received_channel; | ||
397 | u8 control; | ||
398 | u8 mask; | ||
399 | u8 freq; | ||
400 | u16 len; | ||
401 | }; | ||
402 | |||
403 | /* IEEE 802.11 requires that STA supports concurrent reception of at least | ||
404 | * three fragmented frames. This define can be increased to support more | ||
405 | * concurrent frames, but it should be noted that each entry can consume about | ||
406 | * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ | ||
407 | #define IEEE80211_FRAG_CACHE_LEN 4 | ||
408 | |||
409 | struct ieee80211_frag_entry { | ||
410 | unsigned long first_frag_time; | ||
411 | unsigned int seq; | ||
412 | unsigned int last_frag; | ||
413 | struct sk_buff *skb; | ||
414 | u8 src_addr[ETH_ALEN]; | ||
415 | u8 dst_addr[ETH_ALEN]; | ||
416 | }; | ||
417 | |||
418 | struct ieee80211_stats { | ||
419 | unsigned int tx_unicast_frames; | ||
420 | unsigned int tx_multicast_frames; | ||
421 | unsigned int tx_fragments; | ||
422 | unsigned int tx_unicast_octets; | ||
423 | unsigned int tx_multicast_octets; | ||
424 | unsigned int tx_deferred_transmissions; | ||
425 | unsigned int tx_single_retry_frames; | ||
426 | unsigned int tx_multiple_retry_frames; | ||
427 | unsigned int tx_retry_limit_exceeded; | ||
428 | unsigned int tx_discards; | ||
429 | unsigned int rx_unicast_frames; | ||
430 | unsigned int rx_multicast_frames; | ||
431 | unsigned int rx_fragments; | ||
432 | unsigned int rx_unicast_octets; | ||
433 | unsigned int rx_multicast_octets; | ||
434 | unsigned int rx_fcs_errors; | ||
435 | unsigned int rx_discards_no_buffer; | ||
436 | unsigned int tx_discards_wrong_sa; | ||
437 | unsigned int rx_discards_undecryptable; | ||
438 | unsigned int rx_message_in_msg_fragments; | ||
439 | unsigned int rx_message_in_bad_msg_fragments; | ||
440 | }; | ||
441 | |||
442 | struct ieee80211_device; | ||
443 | |||
444 | #define SEC_KEY_1 (1<<0) | ||
445 | #define SEC_KEY_2 (1<<1) | ||
446 | #define SEC_KEY_3 (1<<2) | ||
447 | #define SEC_KEY_4 (1<<3) | ||
448 | #define SEC_ACTIVE_KEY (1<<4) | ||
449 | #define SEC_AUTH_MODE (1<<5) | ||
450 | #define SEC_UNICAST_GROUP (1<<6) | ||
451 | #define SEC_LEVEL (1<<7) | ||
452 | #define SEC_ENABLED (1<<8) | ||
453 | |||
454 | #define SEC_LEVEL_0 0 /* None */ | ||
455 | #define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ | ||
456 | #define SEC_LEVEL_2 2 /* Level 1 + TKIP */ | ||
457 | #define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ | ||
458 | #define SEC_LEVEL_3 4 /* Level 2 + CCMP */ | ||
459 | |||
460 | #define WEP_KEYS 4 | ||
461 | #define WEP_KEY_LEN 13 | ||
462 | |||
463 | struct ieee80211_security { | ||
464 | u16 active_key:2, | ||
465 | enabled:1, | ||
466 | auth_mode:2, | ||
467 | auth_algo:4, | ||
468 | unicast_uses_group:1; | ||
469 | u8 key_sizes[WEP_KEYS]; | ||
470 | u8 keys[WEP_KEYS][WEP_KEY_LEN]; | ||
471 | u8 level; | ||
472 | u16 flags; | ||
473 | } __attribute__ ((packed)); | ||
474 | |||
475 | |||
476 | /* | ||
477 | |||
478 | 802.11 data frame from AP | ||
479 | |||
480 | ,-------------------------------------------------------------------. | ||
481 | Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | | ||
482 | |------|------|---------|---------|---------|------|---------|------| | ||
483 | Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | | ||
484 | | | tion | (BSSID) | | | ence | data | | | ||
485 | `-------------------------------------------------------------------' | ||
486 | |||
487 | Total: 28-2340 bytes | ||
488 | |||
489 | */ | ||
490 | |||
491 | struct ieee80211_header_data { | ||
492 | u16 frame_ctl; | ||
493 | u16 duration_id; | ||
494 | u8 addr1[6]; | ||
495 | u8 addr2[6]; | ||
496 | u8 addr3[6]; | ||
497 | u16 seq_ctrl; | ||
498 | }; | ||
499 | |||
500 | #define BEACON_PROBE_SSID_ID_POSITION 12 | ||
501 | |||
502 | /* Management Frame Information Element Types */ | ||
503 | #define MFIE_TYPE_SSID 0 | ||
504 | #define MFIE_TYPE_RATES 1 | ||
505 | #define MFIE_TYPE_FH_SET 2 | ||
506 | #define MFIE_TYPE_DS_SET 3 | ||
507 | #define MFIE_TYPE_CF_SET 4 | ||
508 | #define MFIE_TYPE_TIM 5 | ||
509 | #define MFIE_TYPE_IBSS_SET 6 | ||
510 | #define MFIE_TYPE_CHALLENGE 16 | ||
511 | #define MFIE_TYPE_RSN 48 | ||
512 | #define MFIE_TYPE_RATES_EX 50 | ||
513 | #define MFIE_TYPE_GENERIC 221 | ||
514 | |||
515 | struct ieee80211_info_element_hdr { | ||
516 | u8 id; | ||
517 | u8 len; | ||
518 | } __attribute__ ((packed)); | ||
519 | |||
520 | struct ieee80211_info_element { | ||
521 | u8 id; | ||
522 | u8 len; | ||
523 | u8 data[0]; | ||
524 | } __attribute__ ((packed)); | ||
525 | |||
526 | /* | ||
527 | * These are the data types that can make up management packets | ||
528 | * | ||
529 | u16 auth_algorithm; | ||
530 | u16 auth_sequence; | ||
531 | u16 beacon_interval; | ||
532 | u16 capability; | ||
533 | u8 current_ap[ETH_ALEN]; | ||
534 | u16 listen_interval; | ||
535 | struct { | ||
536 | u16 association_id:14, reserved:2; | ||
537 | } __attribute__ ((packed)); | ||
538 | u32 time_stamp[2]; | ||
539 | u16 reason; | ||
540 | u16 status; | ||
541 | */ | ||
542 | |||
543 | struct ieee80211_authentication { | ||
544 | struct ieee80211_header_data header; | ||
545 | u16 algorithm; | ||
546 | u16 transaction; | ||
547 | u16 status; | ||
548 | struct ieee80211_info_element info_element; | ||
549 | } __attribute__ ((packed)); | ||
550 | |||
551 | |||
552 | struct ieee80211_probe_response { | ||
553 | struct ieee80211_header_data header; | ||
554 | u32 time_stamp[2]; | ||
555 | u16 beacon_interval; | ||
556 | u16 capability; | ||
557 | struct ieee80211_info_element info_element; | ||
558 | } __attribute__ ((packed)); | ||
559 | |||
560 | struct ieee80211_assoc_request_frame { | ||
561 | u16 capability; | ||
562 | u16 listen_interval; | ||
563 | u8 current_ap[ETH_ALEN]; | ||
564 | struct ieee80211_info_element info_element; | ||
565 | } __attribute__ ((packed)); | ||
566 | |||
567 | struct ieee80211_assoc_response_frame { | ||
568 | struct ieee80211_hdr_3addr header; | ||
569 | u16 capability; | ||
570 | u16 status; | ||
571 | u16 aid; | ||
572 | struct ieee80211_info_element info_element; /* supported rates */ | ||
573 | } __attribute__ ((packed)); | ||
574 | |||
575 | |||
576 | struct ieee80211_txb { | ||
577 | u8 nr_frags; | ||
578 | u8 encrypted; | ||
579 | u16 reserved; | ||
580 | u16 frag_size; | ||
581 | u16 payload_size; | ||
582 | struct sk_buff *fragments[0]; | ||
583 | }; | ||
584 | |||
585 | |||
586 | /* SWEEP TABLE ENTRIES NUMBER*/ | ||
587 | #define MAX_SWEEP_TAB_ENTRIES 42 | ||
588 | #define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 | ||
589 | /* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs | ||
590 | * only use 8, and then use extended rates for the remaining supported | ||
591 | * rates. Other APs, however, stick all of their supported rates on the | ||
592 | * main rates information element... */ | ||
593 | #define MAX_RATES_LENGTH ((u8)12) | ||
594 | #define MAX_RATES_EX_LENGTH ((u8)16) | ||
595 | #define MAX_NETWORK_COUNT 128 | ||
596 | |||
597 | #define CRC_LENGTH 4U | ||
598 | |||
599 | #define MAX_WPA_IE_LEN 64 | ||
600 | |||
601 | #define NETWORK_EMPTY_ESSID (1<<0) | ||
602 | #define NETWORK_HAS_OFDM (1<<1) | ||
603 | #define NETWORK_HAS_CCK (1<<2) | ||
604 | |||
605 | struct ieee80211_network { | ||
606 | /* These entries are used to identify a unique network */ | ||
607 | u8 bssid[ETH_ALEN]; | ||
608 | u8 channel; | ||
609 | /* Ensure null-terminated for any debug msgs */ | ||
610 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | ||
611 | u8 ssid_len; | ||
612 | |||
613 | /* These are network statistics */ | ||
614 | struct ieee80211_rx_stats stats; | ||
615 | u16 capability; | ||
616 | u8 rates[MAX_RATES_LENGTH]; | ||
617 | u8 rates_len; | ||
618 | u8 rates_ex[MAX_RATES_EX_LENGTH]; | ||
619 | u8 rates_ex_len; | ||
620 | unsigned long last_scanned; | ||
621 | u8 mode; | ||
622 | u8 flags; | ||
623 | u32 last_associate; | ||
624 | u32 time_stamp[2]; | ||
625 | u16 beacon_interval; | ||
626 | u16 listen_interval; | ||
627 | u16 atim_window; | ||
628 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
629 | size_t wpa_ie_len; | ||
630 | u8 rsn_ie[MAX_WPA_IE_LEN]; | ||
631 | size_t rsn_ie_len; | ||
632 | struct list_head list; | ||
633 | }; | ||
634 | |||
635 | enum ieee80211_state { | ||
636 | IEEE80211_UNINITIALIZED = 0, | ||
637 | IEEE80211_INITIALIZED, | ||
638 | IEEE80211_ASSOCIATING, | ||
639 | IEEE80211_ASSOCIATED, | ||
640 | IEEE80211_AUTHENTICATING, | ||
641 | IEEE80211_AUTHENTICATED, | ||
642 | IEEE80211_SHUTDOWN | ||
643 | }; | ||
644 | |||
645 | #define DEFAULT_MAX_SCAN_AGE (15 * HZ) | ||
646 | #define DEFAULT_FTS 2346 | ||
647 | #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" | ||
648 | #define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] | ||
649 | |||
650 | |||
651 | extern inline int is_broadcast_ether_addr(const u8 *addr) | ||
652 | { | ||
653 | return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ | ||
654 | (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); | ||
655 | } | ||
656 | |||
657 | #define CFG_IEEE80211_RESERVE_FCS (1<<0) | ||
658 | #define CFG_IEEE80211_COMPUTE_FCS (1<<1) | ||
659 | |||
660 | struct ieee80211_device { | ||
661 | struct net_device *dev; | ||
662 | |||
663 | /* Bookkeeping structures */ | ||
664 | struct net_device_stats stats; | ||
665 | struct ieee80211_stats ieee_stats; | ||
666 | |||
667 | /* Probe / Beacon management */ | ||
668 | struct list_head network_free_list; | ||
669 | struct list_head network_list; | ||
670 | struct ieee80211_network *networks; | ||
671 | int scans; | ||
672 | int scan_age; | ||
673 | |||
674 | int iw_mode; /* operating mode (IW_MODE_*) */ | ||
675 | |||
676 | spinlock_t lock; | ||
677 | |||
678 | int tx_headroom; /* Set to size of any additional room needed at front | ||
679 | * of allocated Tx SKBs */ | ||
680 | u32 config; | ||
681 | |||
682 | /* WEP and other encryption related settings at the device level */ | ||
683 | int open_wep; /* Set to 1 to allow unencrypted frames */ | ||
684 | |||
685 | int reset_on_keychange; /* Set to 1 if the HW needs to be reset on | ||
686 | * WEP key changes */ | ||
687 | |||
688 | /* If the host performs {en,de}cryption, then set to 1 */ | ||
689 | int host_encrypt; | ||
690 | int host_decrypt; | ||
691 | int ieee802_1x; /* is IEEE 802.1X used */ | ||
692 | |||
693 | /* WPA data */ | ||
694 | int wpa_enabled; | ||
695 | int drop_unencrypted; | ||
696 | int tkip_countermeasures; | ||
697 | int privacy_invoked; | ||
698 | size_t wpa_ie_len; | ||
699 | u8 *wpa_ie; | ||
700 | |||
701 | struct list_head crypt_deinit_list; | ||
702 | struct ieee80211_crypt_data *crypt[WEP_KEYS]; | ||
703 | int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ | ||
704 | struct timer_list crypt_deinit_timer; | ||
705 | |||
706 | int bcrx_sta_key; /* use individual keys to override default keys even | ||
707 | * with RX of broad/multicast frames */ | ||
708 | |||
709 | /* Fragmentation structures */ | ||
710 | struct ieee80211_frag_entry frag_cache[IEEE80211_FRAG_CACHE_LEN]; | ||
711 | unsigned int frag_next_idx; | ||
712 | u16 fts; /* Fragmentation Threshold */ | ||
713 | |||
714 | /* Association info */ | ||
715 | u8 bssid[ETH_ALEN]; | ||
716 | |||
717 | enum ieee80211_state state; | ||
718 | |||
719 | int mode; /* A, B, G */ | ||
720 | int modulation; /* CCK, OFDM */ | ||
721 | int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ | ||
722 | int abg_ture; /* ABG flag */ | ||
723 | |||
724 | /* Callback functions */ | ||
725 | void (*set_security)(struct net_device *dev, | ||
726 | struct ieee80211_security *sec); | ||
727 | int (*hard_start_xmit)(struct ieee80211_txb *txb, | ||
728 | struct net_device *dev); | ||
729 | int (*reset_port)(struct net_device *dev); | ||
730 | |||
731 | /* This must be the last item so that it points to the data | ||
732 | * allocated beyond this structure by alloc_ieee80211 */ | ||
733 | u8 priv[0]; | ||
734 | }; | ||
735 | |||
736 | #define IEEE_A (1<<0) | ||
737 | #define IEEE_B (1<<1) | ||
738 | #define IEEE_G (1<<2) | ||
739 | #define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) | ||
740 | |||
741 | extern inline void *ieee80211_priv(struct net_device *dev) | ||
742 | { | ||
743 | return ((struct ieee80211_device *)netdev_priv(dev))->priv; | ||
744 | } | ||
745 | |||
746 | extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) | ||
747 | { | ||
748 | /* Single white space is for Linksys APs */ | ||
749 | if (essid_len == 1 && essid[0] == ' ') | ||
750 | return 1; | ||
751 | |||
752 | /* Otherwise, if the entire essid is 0, we assume it is hidden */ | ||
753 | while (essid_len) { | ||
754 | essid_len--; | ||
755 | if (essid[essid_len] != '\0') | ||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | return 1; | ||
760 | } | ||
761 | |||
762 | extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) | ||
763 | { | ||
764 | /* | ||
765 | * It is possible for both access points and our device to support | ||
766 | * combinations of modes, so as long as there is one valid combination | ||
767 | * of ap/device supported modes, then return success | ||
768 | * | ||
769 | */ | ||
770 | if ((mode & IEEE_A) && | ||
771 | (ieee->modulation & IEEE80211_OFDM_MODULATION) && | ||
772 | (ieee->freq_band & IEEE80211_52GHZ_BAND)) | ||
773 | return 1; | ||
774 | |||
775 | if ((mode & IEEE_G) && | ||
776 | (ieee->modulation & IEEE80211_OFDM_MODULATION) && | ||
777 | (ieee->freq_band & IEEE80211_24GHZ_BAND)) | ||
778 | return 1; | ||
779 | |||
780 | if ((mode & IEEE_B) && | ||
781 | (ieee->modulation & IEEE80211_CCK_MODULATION) && | ||
782 | (ieee->freq_band & IEEE80211_24GHZ_BAND)) | ||
783 | return 1; | ||
784 | |||
785 | return 0; | ||
786 | } | ||
787 | |||
788 | extern inline int ieee80211_get_hdrlen(u16 fc) | ||
789 | { | ||
790 | int hdrlen = 24; | ||
791 | |||
792 | switch (WLAN_FC_GET_TYPE(fc)) { | ||
793 | case IEEE80211_FTYPE_DATA: | ||
794 | if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) | ||
795 | hdrlen = 30; /* Addr4 */ | ||
796 | break; | ||
797 | case IEEE80211_FTYPE_CTL: | ||
798 | switch (WLAN_FC_GET_STYPE(fc)) { | ||
799 | case IEEE80211_STYPE_CTS: | ||
800 | case IEEE80211_STYPE_ACK: | ||
801 | hdrlen = 10; | ||
802 | break; | ||
803 | default: | ||
804 | hdrlen = 16; | ||
805 | break; | ||
806 | } | ||
807 | break; | ||
808 | } | ||
809 | |||
810 | return hdrlen; | ||
811 | } | ||
812 | |||
813 | |||
814 | |||
815 | /* ieee80211.c */ | ||
816 | extern void free_ieee80211(struct net_device *dev); | ||
817 | extern struct net_device *alloc_ieee80211(int sizeof_priv); | ||
818 | |||
819 | extern int ieee80211_set_encryption(struct ieee80211_device *ieee); | ||
820 | |||
821 | /* ieee80211_tx.c */ | ||
822 | |||
823 | |||
824 | extern int ieee80211_xmit(struct sk_buff *skb, | ||
825 | struct net_device *dev); | ||
826 | extern void ieee80211_txb_free(struct ieee80211_txb *); | ||
827 | |||
828 | |||
829 | /* ieee80211_rx.c */ | ||
830 | extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | ||
831 | struct ieee80211_rx_stats *rx_stats); | ||
832 | extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, | ||
833 | struct ieee80211_hdr *header, | ||
834 | struct ieee80211_rx_stats *stats); | ||
835 | |||
836 | /* iee80211_wx.c */ | ||
837 | extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee, | ||
838 | struct iw_request_info *info, | ||
839 | union iwreq_data *wrqu, char *key); | ||
840 | extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee, | ||
841 | struct iw_request_info *info, | ||
842 | union iwreq_data *wrqu, char *key); | ||
843 | extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee, | ||
844 | struct iw_request_info *info, | ||
845 | union iwreq_data *wrqu, char *key); | ||
846 | |||
847 | |||
848 | extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) | ||
849 | { | ||
850 | ieee->scans++; | ||
851 | } | ||
852 | |||
853 | extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) | ||
854 | { | ||
855 | return ieee->scans; | ||
856 | } | ||
857 | |||
858 | static inline const char *escape_essid(const char *essid, u8 essid_len) { | ||
859 | static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; | ||
860 | const char *s = essid; | ||
861 | char *d = escaped; | ||
862 | |||
863 | if (ieee80211_is_empty_essid(essid, essid_len)) { | ||
864 | memcpy(escaped, "<hidden>", sizeof("<hidden>")); | ||
865 | return escaped; | ||
866 | } | ||
867 | |||
868 | essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); | ||
869 | while (essid_len--) { | ||
870 | if (*s == '\0') { | ||
871 | *d++ = '\\'; | ||
872 | *d++ = '0'; | ||
873 | s++; | ||
874 | } else { | ||
875 | *d++ = *s++; | ||
876 | } | ||
877 | } | ||
878 | *d = '\0'; | ||
879 | return escaped; | ||
880 | } | ||
881 | |||
882 | #endif /* IEEE80211_H */ | ||
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/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 |