From 43b175bece9cf9084f7ae48ee711242d857503cc Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 27 Jun 2005 13:59:43 +0100 Subject: [PATCH] --- yaml --- r: 3609 b: refs/heads/master c: 99bcc0590806c4f7a4ecf1a11add335b56cde963 h: refs/heads/master i: 3607: 60e7ade1fd4c65cd936d102b51ba25e719ce025e v: v3 --- [refs] | 2 +- trunk/Documentation/block/ioprio.txt | 176 -- trunk/Documentation/kernel-parameters.txt | 2 +- trunk/arch/arm/mach-aaec2000/Makefile.boot | 1 + trunk/arch/i386/kernel/syscall_table.S | 2 - trunk/arch/ia64/kernel/entry.S | 4 +- trunk/arch/ppc/kernel/misc.S | 2 - trunk/drivers/block/as-iosched.c | 5 +- trunk/drivers/block/cfq-iosched.c | 2150 +++++--------- trunk/drivers/block/deadline-iosched.c | 3 +- trunk/drivers/block/elevator.c | 9 +- trunk/drivers/block/ll_rw_blk.c | 59 +- trunk/drivers/block/sx8.c | 7 +- trunk/drivers/input/evdev.c | 407 +-- trunk/drivers/input/gameport/Kconfig | 14 + trunk/drivers/input/gameport/Makefile | 2 + trunk/drivers/input/gameport/cs461x.c | 322 +++ trunk/drivers/input/gameport/ns558.c | 12 +- trunk/drivers/input/gameport/vortex.c | 186 ++ trunk/drivers/input/input.c | 37 +- trunk/drivers/input/joydev.c | 116 +- trunk/drivers/input/joystick/a3d.c | 2 +- trunk/drivers/input/joystick/adi.c | 4 +- trunk/drivers/input/joystick/amijoy.c | 29 +- trunk/drivers/input/joystick/db9.c | 17 +- trunk/drivers/input/joystick/gamecon.c | 29 +- trunk/drivers/input/joystick/gf2k.c | 2 +- trunk/drivers/input/joystick/grip_mp.c | 2 +- .../input/joystick/iforce/iforce-main.c | 1 - .../input/joystick/iforce/iforce-usb.c | 1 - trunk/drivers/input/joystick/spaceball.c | 4 +- trunk/drivers/input/joystick/spaceorb.c | 2 +- trunk/drivers/input/joystick/tmdc.c | 2 +- trunk/drivers/input/joystick/turbografx.c | 35 +- trunk/drivers/input/keyboard/atkbd.c | 6 +- trunk/drivers/input/keyboard/corgikbd.c | 6 +- trunk/drivers/input/keyboard/lkkbd.c | 8 +- trunk/drivers/input/keyboard/locomokbd.c | 28 +- trunk/drivers/input/keyboard/maple_keyb.c | 22 +- trunk/drivers/input/misc/uinput.c | 6 +- trunk/drivers/input/mouse/Makefile | 2 +- trunk/drivers/input/mouse/alps.c | 52 +- trunk/drivers/input/mouse/amimouse.c | 8 +- trunk/drivers/input/mouse/inport.c | 38 +- trunk/drivers/input/mouse/lifebook.c | 134 - trunk/drivers/input/mouse/lifebook.h | 17 - trunk/drivers/input/mouse/logibm.c | 17 +- trunk/drivers/input/mouse/maplemouse.c | 75 +- trunk/drivers/input/mouse/pc110pad.c | 21 +- trunk/drivers/input/mouse/psmouse-base.c | 351 +-- trunk/drivers/input/mouse/psmouse.h | 4 +- trunk/drivers/input/mouse/rpcmouse.c | 2 +- trunk/drivers/input/mouse/vsxxxaa.c | 4 +- trunk/drivers/input/mousedev.c | 8 +- trunk/drivers/input/serio/libps2.c | 136 +- trunk/drivers/input/touchscreen/elo.c | 2 +- .../input/touchscreen/h3600_ts_input.c | 180 +- trunk/drivers/input/touchscreen/mk712.c | 21 +- trunk/drivers/media/video/Kconfig | 2 +- trunk/drivers/net/3c523.c | 1 - trunk/drivers/net/Kconfig | 2 +- trunk/drivers/net/b44.c | 3 - trunk/drivers/net/cs89x0.c | 40 +- trunk/drivers/net/cs89x0.h | 2 +- trunk/drivers/net/e100.c | 25 +- trunk/drivers/net/e1000/e1000.h | 4 +- trunk/drivers/net/e1000/e1000_ethtool.c | 131 +- trunk/drivers/net/e1000/e1000_hw.c | 23 +- trunk/drivers/net/e1000/e1000_hw.h | 1 - trunk/drivers/net/e1000/e1000_main.c | 111 +- trunk/drivers/net/forcedeth.c | 53 +- trunk/drivers/net/gianfar.c | 652 ++--- trunk/drivers/net/gianfar.h | 363 +-- trunk/drivers/net/gianfar_ethtool.c | 277 +- trunk/drivers/net/pcnet32.c | 2 +- trunk/drivers/net/sb1000.c | 14 +- trunk/drivers/net/skfp/Makefile | 4 +- trunk/drivers/net/skfp/drvfbi.c | 222 +- trunk/drivers/net/skfp/ess.c | 4 +- trunk/drivers/net/skfp/fplustm.c | 70 + trunk/drivers/net/skfp/h/cmtdef.h | 7 + trunk/drivers/net/skfp/h/hwmtm.h | 25 + trunk/drivers/net/skfp/hwmtm.c | 34 +- trunk/drivers/net/skfp/pcmplc.c | 7 + trunk/drivers/net/skfp/pmf.c | 11 +- trunk/drivers/net/skfp/skfddi.c | 1 + trunk/drivers/net/skfp/smt.c | 46 +- trunk/drivers/net/skfp/smtdef.c | 5 + trunk/drivers/net/skfp/smtparse.c | 467 ++++ trunk/drivers/net/smc91x.c | 43 +- trunk/drivers/net/tokenring/lanstreamer.c | 6 +- trunk/drivers/net/tulip/tulip_core.c | 44 +- trunk/drivers/net/via-rhine.c | 6 +- trunk/drivers/net/wan/farsync.c | 1 - trunk/drivers/net/wireless/airo.c | 2 +- trunk/drivers/net/wireless/orinoco.c | 2465 +++++++---------- trunk/drivers/net/wireless/orinoco.h | 30 +- trunk/drivers/net/wireless/prism54/isl_38xx.c | 6 +- trunk/drivers/scsi/libata-scsi.c | 16 +- trunk/drivers/usb/Makefile | 1 - trunk/drivers/usb/input/Kconfig | 24 - trunk/drivers/usb/input/Makefile | 2 - trunk/drivers/usb/input/acecad.c | 285 -- trunk/drivers/usb/input/aiptek.c | 32 +- trunk/drivers/usb/input/ati_remote.c | 247 +- trunk/drivers/usb/input/hid-core.c | 26 +- trunk/drivers/usb/input/hid-debug.h | 16 +- trunk/drivers/usb/input/hid-input.c | 16 +- trunk/drivers/usb/input/hid-lgff.c | 18 +- trunk/drivers/usb/input/hid.h | 18 +- trunk/drivers/usb/input/hiddev.c | 56 +- trunk/drivers/usb/input/itmtouch.c | 268 -- trunk/drivers/usb/input/kbtab.c | 17 +- trunk/drivers/usb/input/mtouchusb.c | 410 +-- trunk/drivers/usb/input/powermate.c | 30 +- trunk/drivers/usb/input/touchkitusb.c | 11 +- trunk/drivers/usb/input/usbkbd.c | 29 +- trunk/drivers/usb/input/usbmouse.c | 31 +- trunk/drivers/usb/input/wacom.c | 398 +-- trunk/drivers/usb/input/xpad.c | 75 +- trunk/drivers/usb/net/pegasus.c | 2 +- trunk/drivers/usb/net/pegasus.h | 2 - trunk/drivers/usb/net/rtl8150.c | 2 +- trunk/fs/Makefile | 1 - trunk/fs/ioprio.c | 172 -- trunk/fs/reiserfs/journal.c | 12 - trunk/include/asm-i386/unistd.h | 4 +- trunk/include/asm-ia64/unistd.h | 2 - trunk/include/asm-ppc/unistd.h | 4 +- trunk/include/asm-x86_64/unistd.h | 6 +- trunk/include/linux/bio.h | 14 - trunk/include/linux/blkdev.h | 25 +- trunk/include/linux/elevator.h | 8 +- trunk/include/linux/fs.h | 19 - trunk/include/linux/init_task.h | 2 - trunk/include/linux/input.h | 4 - trunk/include/linux/ioprio.h | 88 - trunk/include/linux/joystick.h | 33 +- trunk/include/linux/libps2.h | 1 - trunk/include/linux/pci_ids.h | 2 - trunk/include/linux/sched.h | 6 +- trunk/include/linux/serio.h | 6 - trunk/include/linux/writeback.h | 6 +- trunk/include/net/ieee80211.h | 882 ------ trunk/kernel/exit.c | 2 - trunk/kernel/fork.c | 5 - trunk/kernel/sched.c | 8 + trunk/sound/oss/Kconfig | 2 +- trunk/sound/oss/es1370.c | 88 +- trunk/sound/oss/es1371.c | 95 +- trunk/sound/oss/esssolo1.c | 26 +- trunk/sound/oss/mad16.c | 30 +- trunk/sound/oss/sonicvibes.c | 25 +- trunk/sound/oss/trident.c | 37 +- trunk/sound/oss/via82cxxx_audio.c | 5 +- trunk/sound/pci/cs4281.c | 5 + 156 files changed, 5158 insertions(+), 8507 deletions(-) delete mode 100644 trunk/Documentation/block/ioprio.txt create mode 100644 trunk/arch/arm/mach-aaec2000/Makefile.boot create mode 100644 trunk/drivers/input/gameport/cs461x.c create mode 100644 trunk/drivers/input/gameport/vortex.c delete mode 100644 trunk/drivers/input/mouse/lifebook.c delete mode 100644 trunk/drivers/input/mouse/lifebook.h create mode 100644 trunk/drivers/net/skfp/smtparse.c delete mode 100644 trunk/drivers/usb/input/acecad.c delete mode 100644 trunk/drivers/usb/input/itmtouch.c delete mode 100644 trunk/fs/ioprio.c delete mode 100644 trunk/include/linux/ioprio.h delete mode 100644 trunk/include/net/ieee80211.h diff --git a/[refs] b/[refs] index 1532e1a41a4d..fda4e0d14244 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 61cca8c72eb284e80876bafdea057055f6e793e4 +refs/heads/master: 99bcc0590806c4f7a4ecf1a11add335b56cde963 diff --git a/trunk/Documentation/block/ioprio.txt b/trunk/Documentation/block/ioprio.txt deleted file mode 100644 index 96ccf681075e..000000000000 --- a/trunk/Documentation/block/ioprio.txt +++ /dev/null @@ -1,176 +0,0 @@ -Block io priorities -=================== - - -Intro ------ - -With the introduction of cfq v3 (aka cfq-ts or time sliced cfq), basic io -priorities is supported for reads on files. This enables users to io nice -processes or process groups, similar to what has been possible to cpu -scheduling for ages. This document mainly details the current possibilites -with cfq, other io schedulers do not support io priorities so far. - -Scheduling classes ------------------- - -CFQ implements three generic scheduling classes that determine how io is -served for a process. - -IOPRIO_CLASS_RT: This is the realtime io class. This scheduling class is given -higher priority than any other in the system, processes from this class are -given first access to the disk every time. Thus it needs to be used with some -care, one io RT process can starve the entire system. Within the RT class, -there are 8 levels of class data that determine exactly how much time this -process needs the disk for on each service. In the future this might change -to be more directly mappable to performance, by passing in a wanted data -rate instead. - -IOPRIO_CLASS_BE: This is the best-effort scheduling class, which is the default -for any process that hasn't set a specific io priority. The class data -determines how much io bandwidth the process will get, it's directly mappable -to the cpu nice levels just more coarsely implemented. 0 is the highest -BE prio level, 7 is the lowest. The mapping between cpu nice level and io -nice level is determined as: io_nice = (cpu_nice + 20) / 5. - -IOPRIO_CLASS_IDLE: This is the idle scheduling class, processes running at this -level only get io time when no one else needs the disk. The idle class has no -class data, since it doesn't really apply here. - -Tools ------ - -See below for a sample ionice tool. Usage: - -# ionice -c -n -p - -If pid isn't given, the current process is assumed. IO priority settings -are inherited on fork, so you can use ionice to start the process at a given -level: - -# ionice -c2 -n0 /bin/ls - -will run ls at the best-effort scheduling class at the highest priority. -For a running process, you can give the pid instead: - -# ionice -c1 -n2 -p100 - -will change pid 100 to run at the realtime scheduling class, at priority 2. - ----> snip ionice.c tool <--- - -#include -#include -#include -#include -#include -#include -#include - -extern int sys_ioprio_set(int, int, int); -extern int sys_ioprio_get(int, int); - -#if defined(__i386__) -#define __NR_ioprio_set 289 -#define __NR_ioprio_get 290 -#elif defined(__ppc__) -#define __NR_ioprio_set 273 -#define __NR_ioprio_get 274 -#elif defined(__x86_64__) -#define __NR_ioprio_set 251 -#define __NR_ioprio_get 252 -#elif defined(__ia64__) -#define __NR_ioprio_set 1274 -#define __NR_ioprio_get 1275 -#else -#error "Unsupported arch" -#endif - -_syscall3(int, ioprio_set, int, which, int, who, int, ioprio); -_syscall2(int, ioprio_get, int, which, int, who); - -enum { - IOPRIO_CLASS_NONE, - IOPRIO_CLASS_RT, - IOPRIO_CLASS_BE, - IOPRIO_CLASS_IDLE, -}; - -enum { - IOPRIO_WHO_PROCESS = 1, - IOPRIO_WHO_PGRP, - IOPRIO_WHO_USER, -}; - -#define IOPRIO_CLASS_SHIFT 13 - -const char *to_prio[] = { "none", "realtime", "best-effort", "idle", }; - -int main(int argc, char *argv[]) -{ - int ioprio = 4, set = 0, ioprio_class = IOPRIO_CLASS_BE; - int c, pid = 0; - - while ((c = getopt(argc, argv, "+n:c:p:")) != EOF) { - switch (c) { - case 'n': - ioprio = strtol(optarg, NULL, 10); - set = 1; - break; - case 'c': - ioprio_class = strtol(optarg, NULL, 10); - set = 1; - break; - case 'p': - pid = strtol(optarg, NULL, 10); - break; - } - } - - switch (ioprio_class) { - case IOPRIO_CLASS_NONE: - ioprio_class = IOPRIO_CLASS_BE; - break; - case IOPRIO_CLASS_RT: - case IOPRIO_CLASS_BE: - break; - case IOPRIO_CLASS_IDLE: - ioprio = 7; - break; - default: - printf("bad prio class %d\n", ioprio_class); - return 1; - } - - if (!set) { - if (!pid && argv[optind]) - pid = strtol(argv[optind], NULL, 10); - - ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid); - - printf("pid=%d, %d\n", pid, ioprio); - - if (ioprio == -1) - perror("ioprio_get"); - else { - ioprio_class = ioprio >> IOPRIO_CLASS_SHIFT; - ioprio = ioprio & 0xff; - printf("%s: prio %d\n", to_prio[ioprio_class], ioprio); - } - } else { - if (ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio | ioprio_class << IOPRIO_CLASS_SHIFT) == -1) { - perror("ioprio_set"); - return 1; - } - - if (argv[optind]) - execvp(argv[optind], &argv[optind]); - } - - return 0; -} - ----> snip ionice.c tool <--- - - -March 11 2005, Jens Axboe diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 89cd417651e0..f44bb5567c5b 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -1115,7 +1115,7 @@ running once the system is up. See Documentation/ramdisk.txt. psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to - probe for (bare|imps|exps|lifebook|any). + probe for (bare|imps|exps). psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports per second. psmouse.resetafter= diff --git a/trunk/arch/arm/mach-aaec2000/Makefile.boot b/trunk/arch/arm/mach-aaec2000/Makefile.boot new file mode 100644 index 000000000000..8f5a8b7c53c7 --- /dev/null +++ b/trunk/arch/arm/mach-aaec2000/Makefile.boot @@ -0,0 +1 @@ + zreladdr-y := 0xf0008000 diff --git a/trunk/arch/i386/kernel/syscall_table.S b/trunk/arch/i386/kernel/syscall_table.S index 3db9a04aec6e..442a6e937b19 100644 --- a/trunk/arch/i386/kernel/syscall_table.S +++ b/trunk/arch/i386/kernel/syscall_table.S @@ -289,5 +289,3 @@ ENTRY(sys_call_table) .long sys_add_key .long sys_request_key .long sys_keyctl - .long sys_ioprio_set - .long sys_ioprio_get /* 290 */ diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S index 785a51b0ad8e..b1d5d3d5276c 100644 --- a/trunk/arch/ia64/kernel/entry.S +++ b/trunk/arch/ia64/kernel/entry.S @@ -1577,8 +1577,8 @@ sys_call_table: data8 sys_add_key data8 sys_request_key data8 sys_keyctl - data8 sys_ioprio_set - data8 sys_ioprio_get // 1275 + data8 sys_ni_syscall + data8 sys_ni_syscall // 1275 data8 sys_set_zone_reclaim data8 sys_ni_syscall data8 sys_ni_syscall diff --git a/trunk/arch/ppc/kernel/misc.S b/trunk/arch/ppc/kernel/misc.S index 191a8def3bdb..b6a63a49a232 100644 --- a/trunk/arch/ppc/kernel/misc.S +++ b/trunk/arch/ppc/kernel/misc.S @@ -1449,5 +1449,3 @@ _GLOBAL(sys_call_table) .long sys_request_key /* 270 */ .long sys_keyctl .long sys_waitid - .long sys_ioprio_set - .long sys_ioprio_get diff --git a/trunk/drivers/block/as-iosched.c b/trunk/drivers/block/as-iosched.c index 91aeb678135d..3410b4d294b9 100644 --- a/trunk/drivers/block/as-iosched.c +++ b/trunk/drivers/block/as-iosched.c @@ -1806,8 +1806,7 @@ static void as_put_request(request_queue_t *q, struct request *rq) rq->elevator_private = NULL; } -static int as_set_request(request_queue_t *q, struct request *rq, - struct bio *bio, int gfp_mask) +static int as_set_request(request_queue_t *q, struct request *rq, int gfp_mask) { struct as_data *ad = q->elevator->elevator_data; struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask); @@ -1828,7 +1827,7 @@ static int as_set_request(request_queue_t *q, struct request *rq, return 1; } -static int as_may_queue(request_queue_t *q, int rw, struct bio *bio) +static int as_may_queue(request_queue_t *q, int rw) { int ret = ELV_MQUEUE_MAY; struct as_data *ad = q->elevator->elevator_data; diff --git a/trunk/drivers/block/cfq-iosched.c b/trunk/drivers/block/cfq-iosched.c index ff1cc968f96d..3ac47dde64da 100644 --- a/trunk/drivers/block/cfq-iosched.c +++ b/trunk/drivers/block/cfq-iosched.c @@ -21,34 +21,22 @@ #include #include #include -#include -#include + +static unsigned long max_elapsed_crq; +static unsigned long max_elapsed_dispatch; /* * tunables */ static int cfq_quantum = 4; /* max queue in one round of service */ static int cfq_queued = 8; /* minimum rq allocate limit per-queue*/ -static int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; +static int cfq_service = HZ; /* period over which service is avg */ +static int cfq_fifo_expire_r = HZ / 2; /* fifo timeout for sync requests */ +static int cfq_fifo_expire_w = 5 * HZ; /* fifo timeout for async requests */ +static int cfq_fifo_rate = HZ / 8; /* fifo expiry rate */ static int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ static int cfq_back_penalty = 2; /* penalty of a backwards seek */ -static int cfq_slice_sync = HZ / 10; -static int cfq_slice_async = HZ / 25; -static int cfq_slice_async_rq = 2; -static int cfq_slice_idle = HZ / 100; - -#define CFQ_IDLE_GRACE (HZ / 10) -#define CFQ_SLICE_SCALE (5) - -#define CFQ_KEY_ASYNC (0) -#define CFQ_KEY_ANY (0xffff) - -/* - * disable queueing at the driver/hardware level - */ -static int cfq_max_depth = 1; - /* * for the hash of cfqq inside the cfqd */ @@ -67,7 +55,6 @@ static int cfq_max_depth = 1; #define list_entry_hash(ptr) hlist_entry((ptr), struct cfq_rq, hash) #define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list) -#define list_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) #define RQ_DATA(rq) (rq)->elevator_private @@ -88,110 +75,78 @@ static int cfq_max_depth = 1; #define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) #define rq_rb_key(rq) (rq)->sector -static kmem_cache_t *crq_pool; -static kmem_cache_t *cfq_pool; -static kmem_cache_t *cfq_ioc_pool; - -#define CFQ_PRIO_LISTS IOPRIO_BE_NR -#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) -#define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE) -#define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) - -#define ASYNC (0) -#define SYNC (1) - -#define cfq_cfqq_dispatched(cfqq) \ - ((cfqq)->on_dispatch[ASYNC] + (cfqq)->on_dispatch[SYNC]) - -#define cfq_cfqq_class_sync(cfqq) ((cfqq)->key != CFQ_KEY_ASYNC) - -#define cfq_cfqq_sync(cfqq) \ - (cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC]) +/* + * threshold for switching off non-tag accounting + */ +#define CFQ_MAX_TAG (4) /* - * Per block device queue structure + * sort key types and names */ -struct cfq_data { - atomic_t ref; - request_queue_t *queue; +enum { + CFQ_KEY_PGID, + CFQ_KEY_TGID, + CFQ_KEY_UID, + CFQ_KEY_GID, + CFQ_KEY_LAST, +}; - /* - * rr list of queues with requests and the count of them - */ - struct list_head rr_list[CFQ_PRIO_LISTS]; - struct list_head busy_rr; - struct list_head cur_rr; - struct list_head idle_rr; - unsigned int busy_queues; +static char *cfq_key_types[] = { "pgid", "tgid", "uid", "gid", NULL }; - /* - * non-ordered list of empty cfqq's - */ +static kmem_cache_t *crq_pool; +static kmem_cache_t *cfq_pool; +static kmem_cache_t *cfq_ioc_pool; + +struct cfq_data { + struct list_head rr_list; struct list_head empty_list; - /* - * cfqq lookup hash - */ struct hlist_head *cfq_hash; - - /* - * global crq hash for all queues - */ struct hlist_head *crq_hash; - unsigned int max_queued; + /* queues on rr_list (ie they have pending requests */ + unsigned int busy_queues; - mempool_t *crq_pool; + unsigned int max_queued; - int rq_in_driver; + atomic_t ref; - /* - * schedule slice state info - */ - /* - * idle window management - */ - struct timer_list idle_slice_timer; - struct work_struct unplug_work; + int key_type; - struct cfq_queue *active_queue; - struct cfq_io_context *active_cic; - int cur_prio, cur_end_prio; - unsigned int dispatch_slice; + mempool_t *crq_pool; - struct timer_list idle_class_timer; + request_queue_t *queue; sector_t last_sector; - unsigned long last_end_request; - unsigned int rq_starved; + int rq_in_driver; /* * tunables, see top of file */ unsigned int cfq_quantum; unsigned int cfq_queued; - unsigned int cfq_fifo_expire[2]; + unsigned int cfq_fifo_expire_r; + unsigned int cfq_fifo_expire_w; + unsigned int cfq_fifo_batch_expire; unsigned int cfq_back_penalty; unsigned int cfq_back_max; - unsigned int cfq_slice[2]; - unsigned int cfq_slice_async_rq; - unsigned int cfq_slice_idle; - unsigned int cfq_max_depth; + unsigned int find_best_crq; + + unsigned int cfq_tagged; }; -/* - * Per process-grouping structure - */ struct cfq_queue { /* reference count */ atomic_t ref; /* parent cfq_data */ struct cfq_data *cfqd; - /* cfqq lookup hash */ + /* hash of mergeable requests */ struct hlist_node cfq_hash; /* hash key */ - unsigned int key; + unsigned long key; + /* whether queue is on rr (or empty) list */ + int on_rr; /* on either rr or empty list of cfqd */ struct list_head cfq_list; /* sorted list of pending requests */ @@ -203,22 +158,21 @@ struct cfq_queue { /* currently allocated requests */ int allocated[2]; /* fifo list of requests in sort_list */ - struct list_head fifo; + struct list_head fifo[2]; + /* last time fifo expired */ + unsigned long last_fifo_expire; - unsigned long slice_start; - unsigned long slice_end; - unsigned long slice_left; - unsigned long service_last; + int key_type; - /* number of requests that are on the dispatch list */ - int on_dispatch[2]; + unsigned long service_start; + unsigned long service_used; - /* io prio of this group */ - unsigned short ioprio, org_ioprio; - unsigned short ioprio_class, org_ioprio_class; + unsigned int max_rate; - /* various state flags, see below */ - unsigned int flags; + /* number of requests that have been handed to the driver */ + int in_flight; + /* number of currently allocated requests */ + int alloc_limit[2]; }; struct cfq_rq { @@ -230,79 +184,42 @@ struct cfq_rq { struct cfq_queue *cfq_queue; struct cfq_io_context *io_context; - unsigned int crq_flags; -}; - -enum cfqq_state_flags { - CFQ_CFQQ_FLAG_on_rr = 0, - CFQ_CFQQ_FLAG_wait_request, - CFQ_CFQQ_FLAG_must_alloc, - CFQ_CFQQ_FLAG_must_alloc_slice, - CFQ_CFQQ_FLAG_must_dispatch, - CFQ_CFQQ_FLAG_fifo_expire, - CFQ_CFQQ_FLAG_idle_window, - CFQ_CFQQ_FLAG_prio_changed, - CFQ_CFQQ_FLAG_expired, -}; + unsigned long service_start; + unsigned long queue_start; -#define CFQ_CFQQ_FNS(name) \ -static inline void cfq_mark_cfqq_##name(struct cfq_queue *cfqq) \ -{ \ - cfqq->flags |= (1 << CFQ_CFQQ_FLAG_##name); \ -} \ -static inline void cfq_clear_cfqq_##name(struct cfq_queue *cfqq) \ -{ \ - cfqq->flags &= ~(1 << CFQ_CFQQ_FLAG_##name); \ -} \ -static inline int cfq_cfqq_##name(const struct cfq_queue *cfqq) \ -{ \ - return (cfqq->flags & (1 << CFQ_CFQQ_FLAG_##name)) != 0; \ -} - -CFQ_CFQQ_FNS(on_rr); -CFQ_CFQQ_FNS(wait_request); -CFQ_CFQQ_FNS(must_alloc); -CFQ_CFQQ_FNS(must_alloc_slice); -CFQ_CFQQ_FNS(must_dispatch); -CFQ_CFQQ_FNS(fifo_expire); -CFQ_CFQQ_FNS(idle_window); -CFQ_CFQQ_FNS(prio_changed); -CFQ_CFQQ_FNS(expired); -#undef CFQ_CFQQ_FNS - -enum cfq_rq_state_flags { - CFQ_CRQ_FLAG_in_flight = 0, - CFQ_CRQ_FLAG_in_driver, - CFQ_CRQ_FLAG_is_sync, - CFQ_CRQ_FLAG_requeued, + unsigned int in_flight : 1; + unsigned int accounted : 1; + unsigned int is_sync : 1; + unsigned int is_write : 1; }; -#define CFQ_CRQ_FNS(name) \ -static inline void cfq_mark_crq_##name(struct cfq_rq *crq) \ -{ \ - crq->crq_flags |= (1 << CFQ_CRQ_FLAG_##name); \ -} \ -static inline void cfq_clear_crq_##name(struct cfq_rq *crq) \ -{ \ - crq->crq_flags &= ~(1 << CFQ_CRQ_FLAG_##name); \ -} \ -static inline int cfq_crq_##name(const struct cfq_rq *crq) \ -{ \ - return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0; \ -} - -CFQ_CRQ_FNS(in_flight); -CFQ_CRQ_FNS(in_driver); -CFQ_CRQ_FNS(is_sync); -CFQ_CRQ_FNS(requeued); -#undef CFQ_CRQ_FNS - -static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); +static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned long); static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *); +static void cfq_update_next_crq(struct cfq_rq *); static void cfq_put_cfqd(struct cfq_data *cfqd); -static inline int cfq_pending_requests(struct cfq_data *cfqd); -#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) +/* + * what the fairness is based on (ie how processes are grouped and + * differentiated) + */ +static inline unsigned long +cfq_hash_key(struct cfq_data *cfqd, struct task_struct *tsk) +{ + /* + * optimize this so that ->key_type is the offset into the struct + */ + switch (cfqd->key_type) { + case CFQ_KEY_PGID: + return process_group(tsk); + default: + case CFQ_KEY_TGID: + return tsk->tgid; + case CFQ_KEY_UID: + return tsk->uid; + case CFQ_KEY_GID: + return tsk->gid; + } +} /* * lots of deadline iosched dupes, can be abstracted later... @@ -318,12 +235,16 @@ static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq) if (q->last_merge == crq->request) q->last_merge = NULL; + + cfq_update_next_crq(crq); } static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq) { const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request)); + BUG_ON(!hlist_unhashed(&crq->hash)); + hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]); } @@ -336,6 +257,8 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) struct cfq_rq *crq = list_entry_hash(entry); struct request *__rq = crq->request; + BUG_ON(hlist_unhashed(&crq->hash)); + if (!rq_mergeable(__rq)) { cfq_del_crq_hash(crq); continue; @@ -364,16 +287,36 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) return crq2; if (crq2 == NULL) return crq1; - if (cfq_crq_requeued(crq1)) - return crq1; - if (cfq_crq_requeued(crq2)) - return crq2; s1 = crq1->request->sector; s2 = crq2->request->sector; last = cfqd->last_sector; +#if 0 + if (!list_empty(&cfqd->queue->queue_head)) { + struct list_head *entry = &cfqd->queue->queue_head; + unsigned long distance = ~0UL; + struct request *rq; + + while ((entry = entry->prev) != &cfqd->queue->queue_head) { + rq = list_entry_rq(entry); + + if (blk_barrier_rq(rq)) + break; + + if (distance < abs(s1 - rq->sector + rq->nr_sectors)) { + distance = abs(s1 - rq->sector +rq->nr_sectors); + last = rq->sector + rq->nr_sectors; + } + if (distance < abs(s2 - rq->sector + rq->nr_sectors)) { + distance = abs(s2 - rq->sector +rq->nr_sectors); + last = rq->sector + rq->nr_sectors; + } + } + } +#endif + /* * by definition, 1KiB is 2 sectors */ @@ -434,14 +377,11 @@ cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct cfq_rq *crq_next = NULL, *crq_prev = NULL; struct rb_node *rbnext, *rbprev; - rbnext = NULL; - if (ON_RB(&last->rb_node)) - rbnext = rb_next(&last->rb_node); - if (!rbnext) { + if (!ON_RB(&last->rb_node)) + return NULL; + + if ((rbnext = rb_next(&last->rb_node)) == NULL) rbnext = rb_first(&cfqq->sort_list); - if (rbnext == &last->rb_node) - rbnext = NULL; - } rbprev = rb_prev(&last->rb_node); @@ -461,53 +401,67 @@ static void cfq_update_next_crq(struct cfq_rq *crq) cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq); } -static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) +static int cfq_check_sort_rr_list(struct cfq_queue *cfqq) { - struct cfq_data *cfqd = cfqq->cfqd; - struct list_head *list, *entry; + struct list_head *head = &cfqq->cfqd->rr_list; + struct list_head *next, *prev; - BUG_ON(!cfq_cfqq_on_rr(cfqq)); + /* + * list might still be ordered + */ + next = cfqq->cfq_list.next; + if (next != head) { + struct cfq_queue *cnext = list_entry_cfqq(next); - list_del(&cfqq->cfq_list); + if (cfqq->service_used > cnext->service_used) + return 1; + } - if (cfq_class_rt(cfqq)) - list = &cfqd->cur_rr; - else if (cfq_class_idle(cfqq)) - list = &cfqd->idle_rr; - else { - /* - * if cfqq has requests in flight, don't allow it to be - * found in cfq_set_active_queue before it has finished them. - * this is done to increase fairness between a process that - * has lots of io pending vs one that only generates one - * sporadically or synchronously - */ - if (cfq_cfqq_dispatched(cfqq)) - list = &cfqd->busy_rr; - else - list = &cfqd->rr_list[cfqq->ioprio]; + prev = cfqq->cfq_list.prev; + if (prev != head) { + struct cfq_queue *cprev = list_entry_cfqq(prev); + + if (cfqq->service_used < cprev->service_used) + return 1; } - /* - * if queue was preempted, just add to front to be fair. busy_rr - * isn't sorted. - */ - if (preempted || list == &cfqd->busy_rr) { - list_add(&cfqq->cfq_list, list); + return 0; +} + +static void cfq_sort_rr_list(struct cfq_queue *cfqq, int new_queue) +{ + struct list_head *entry = &cfqq->cfqd->rr_list; + + if (!cfqq->on_rr) return; - } + if (!new_queue && !cfq_check_sort_rr_list(cfqq)) + return; + + list_del(&cfqq->cfq_list); /* - * sort by when queue was last serviced + * sort by our mean service_used, sub-sort by in-flight requests */ - entry = list; - while ((entry = entry->prev) != list) { + while ((entry = entry->prev) != &cfqq->cfqd->rr_list) { struct cfq_queue *__cfqq = list_entry_cfqq(entry); - if (!__cfqq->service_last) - break; - if (time_before(__cfqq->service_last, cfqq->service_last)) + if (cfqq->service_used > __cfqq->service_used) break; + else if (cfqq->service_used == __cfqq->service_used) { + struct list_head *prv; + + while ((prv = entry->prev) != &cfqq->cfqd->rr_list) { + __cfqq = list_entry_cfqq(prv); + + WARN_ON(__cfqq->service_used > cfqq->service_used); + if (cfqq->service_used != __cfqq->service_used) + break; + if (cfqq->in_flight > __cfqq->in_flight) + break; + + entry = prv; + } + } } list_add(&cfqq->cfq_list, entry); @@ -515,24 +469,28 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) /* * add to busy list of queues for service, trying to be fair in ordering - * the pending list according to last request service + * the pending list according to requests serviced */ static inline void -cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq, int requeue) +cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) { - BUG_ON(cfq_cfqq_on_rr(cfqq)); - cfq_mark_cfqq_on_rr(cfqq); + /* + * it's currently on the empty list + */ + cfqq->on_rr = 1; cfqd->busy_queues++; - cfq_resort_rr_list(cfqq, requeue); + if (time_after(jiffies, cfqq->service_start + cfq_service)) + cfqq->service_used >>= 3; + + cfq_sort_rr_list(cfqq, 1); } static inline void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) { - BUG_ON(!cfq_cfqq_on_rr(cfqq)); - cfq_clear_cfqq_on_rr(cfqq); list_move(&cfqq->cfq_list, &cfqd->empty_list); + cfqq->on_rr = 0; BUG_ON(!cfqd->busy_queues); cfqd->busy_queues--; @@ -547,17 +505,16 @@ static inline void cfq_del_crq_rb(struct cfq_rq *crq) if (ON_RB(&crq->rb_node)) { struct cfq_data *cfqd = cfqq->cfqd; - const int sync = cfq_crq_is_sync(crq); - BUG_ON(!cfqq->queued[sync]); - cfqq->queued[sync]--; + BUG_ON(!cfqq->queued[crq->is_sync]); cfq_update_next_crq(crq); + cfqq->queued[crq->is_sync]--; rb_erase(&crq->rb_node, &cfqq->sort_list); RB_CLEAR_COLOR(&crq->rb_node); - if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list)) + if (RB_EMPTY(&cfqq->sort_list) && cfqq->on_rr) cfq_del_cfqq_rr(cfqd, cfqq); } } @@ -593,7 +550,7 @@ static void cfq_add_crq_rb(struct cfq_rq *crq) struct cfq_rq *__alias; crq->rb_key = rq_rb_key(rq); - cfqq->queued[cfq_crq_is_sync(crq)]++; + cfqq->queued[crq->is_sync]++; /* * looks a little odd, but the first insert might return an alias. @@ -604,8 +561,8 @@ static void cfq_add_crq_rb(struct cfq_rq *crq) rb_insert_color(&crq->rb_node, &cfqq->sort_list); - if (!cfq_cfqq_on_rr(cfqq)) - cfq_add_cfqq_rr(cfqd, cfqq, cfq_crq_requeued(crq)); + if (!cfqq->on_rr) + cfq_add_cfqq_rr(cfqd, cfqq); /* * check if this request is a better next-serve candidate @@ -618,16 +575,17 @@ cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) { if (ON_RB(&crq->rb_node)) { rb_erase(&crq->rb_node, &cfqq->sort_list); - cfqq->queued[cfq_crq_is_sync(crq)]--; + cfqq->queued[crq->is_sync]--; } cfq_add_crq_rb(crq); } -static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) - +static struct request * +cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) { - struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY); + const unsigned long key = cfq_hash_key(cfqd, current); + struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, key); struct rb_node *n; if (!cfqq) @@ -651,25 +609,20 @@ static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) static void cfq_deactivate_request(request_queue_t *q, struct request *rq) { - struct cfq_data *cfqd = q->elevator->elevator_data; struct cfq_rq *crq = RQ_DATA(rq); if (crq) { struct cfq_queue *cfqq = crq->cfq_queue; - if (cfq_crq_in_driver(crq)) { - cfq_clear_crq_in_driver(crq); - WARN_ON(!cfqd->rq_in_driver); - cfqd->rq_in_driver--; + if (cfqq->cfqd->cfq_tagged) { + cfqq->service_used--; + cfq_sort_rr_list(cfqq, 0); } - if (cfq_crq_in_flight(crq)) { - const int sync = cfq_crq_is_sync(crq); - cfq_clear_crq_in_flight(crq); - WARN_ON(!cfqq->on_dispatch[sync]); - cfqq->on_dispatch[sync]--; + if (crq->accounted) { + crq->accounted = 0; + cfqq->cfqd->rq_in_driver--; } - cfq_mark_crq_requeued(crq); } } @@ -687,10 +640,11 @@ static void cfq_remove_request(request_queue_t *q, struct request *rq) struct cfq_rq *crq = RQ_DATA(rq); if (crq) { - list_del_init(&rq->queuelist); - cfq_del_crq_rb(crq); cfq_remove_merge_hints(q, crq); + list_del_init(&rq->queuelist); + if (crq->cfq_queue) + cfq_del_crq_rb(crq); } } @@ -708,15 +662,21 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio) } __rq = cfq_find_rq_hash(cfqd, bio->bi_sector); - if (__rq && elv_rq_merge_ok(__rq, bio)) { - ret = ELEVATOR_BACK_MERGE; - goto out; + if (__rq) { + BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector); + + if (elv_rq_merge_ok(__rq, bio)) { + ret = ELEVATOR_BACK_MERGE; + goto out; + } } __rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio)); - if (__rq && elv_rq_merge_ok(__rq, bio)) { - ret = ELEVATOR_FRONT_MERGE; - goto out; + if (__rq) { + if (elv_rq_merge_ok(__rq, bio)) { + ret = ELEVATOR_FRONT_MERGE; + goto out; + } } return ELEVATOR_NO_MERGE; @@ -749,506 +709,235 @@ static void cfq_merged_requests(request_queue_t *q, struct request *rq, struct request *next) { - cfq_merged_request(q, rq); - - /* - * reposition in fifo if next is older than rq - */ - if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && - time_before(next->start_time, rq->start_time)) - list_move(&rq->queuelist, &next->queuelist); + struct cfq_rq *crq = RQ_DATA(rq); + struct cfq_rq *cnext = RQ_DATA(next); - cfq_remove_request(q, next); -} + cfq_merged_request(q, rq); -static inline void -__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - if (cfqq) { - /* - * stop potential idle class queues waiting service - */ - del_timer(&cfqd->idle_class_timer); - - cfqq->slice_start = jiffies; - cfqq->slice_end = 0; - cfqq->slice_left = 0; - cfq_clear_cfqq_must_alloc_slice(cfqq); - cfq_clear_cfqq_fifo_expire(cfqq); - cfq_clear_cfqq_expired(cfqq); + if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist)) { + if (time_before(cnext->queue_start, crq->queue_start)) { + list_move(&rq->queuelist, &next->queuelist); + crq->queue_start = cnext->queue_start; + } } - cfqd->active_queue = cfqq; + cfq_update_next_crq(cnext); + cfq_remove_request(q, next); } /* - * 0 - * 0,1 - * 0,1,2 - * 0,1,2,3 - * 0,1,2,3,4 - * 0,1,2,3,4,5 - * 0,1,2,3,4,5,6 - * 0,1,2,3,4,5,6,7 + * we dispatch cfqd->cfq_quantum requests in total from the rr_list queues, + * this function sector sorts the selected request to minimize seeks. we start + * at cfqd->last_sector, not 0. */ -static int cfq_get_next_prio_level(struct cfq_data *cfqd) +static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq) { - int prio, wrap; + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_queue *cfqq = crq->cfq_queue; + struct list_head *head = &q->queue_head, *entry = head; + struct request *__rq; + sector_t last; + + cfq_del_crq_rb(crq); + cfq_remove_merge_hints(q, crq); + list_del(&crq->request->queuelist); - prio = -1; - wrap = 0; - do { - int p; + last = cfqd->last_sector; + while ((entry = entry->prev) != head) { + __rq = list_entry_rq(entry); - for (p = cfqd->cur_prio; p <= cfqd->cur_end_prio; p++) { - if (!list_empty(&cfqd->rr_list[p])) { - prio = p; - break; - } - } + if (blk_barrier_rq(crq->request)) + break; + if (!blk_fs_request(crq->request)) + break; - if (prio != -1) + if (crq->request->sector > __rq->sector) + break; + if (__rq->sector > last && crq->request->sector < last) { + last = crq->request->sector; break; - cfqd->cur_prio = 0; - if (++cfqd->cur_end_prio == CFQ_PRIO_LISTS) { - cfqd->cur_end_prio = 0; - if (wrap) - break; - wrap = 1; } - } while (1); + } - if (unlikely(prio == -1)) - return -1; + cfqd->last_sector = last; + crq->in_flight = 1; + cfqq->in_flight++; + list_add(&crq->request->queuelist, entry); +} - BUG_ON(prio >= CFQ_PRIO_LISTS); +/* + * return expired entry, or NULL to just start from scratch in rbtree + */ +static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq) +{ + struct cfq_data *cfqd = cfqq->cfqd; + const int reads = !list_empty(&cfqq->fifo[0]); + const int writes = !list_empty(&cfqq->fifo[1]); + unsigned long now = jiffies; + struct cfq_rq *crq; - list_splice_init(&cfqd->rr_list[prio], &cfqd->cur_rr); + if (time_before(now, cfqq->last_fifo_expire + cfqd->cfq_fifo_batch_expire)) + return NULL; - cfqd->cur_prio = prio + 1; - if (cfqd->cur_prio > cfqd->cur_end_prio) { - cfqd->cur_end_prio = cfqd->cur_prio; - cfqd->cur_prio = 0; + crq = RQ_DATA(list_entry(cfqq->fifo[0].next, struct request, queuelist)); + if (reads && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_r)) { + cfqq->last_fifo_expire = now; + return crq; } - if (cfqd->cur_end_prio == CFQ_PRIO_LISTS) { - cfqd->cur_prio = 0; - cfqd->cur_end_prio = 0; + + crq = RQ_DATA(list_entry(cfqq->fifo[1].next, struct request, queuelist)); + if (writes && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_w)) { + cfqq->last_fifo_expire = now; + return crq; } - return prio; + return NULL; } -static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) +/* + * dispatch a single request from given queue + */ +static inline void +cfq_dispatch_request(request_queue_t *q, struct cfq_data *cfqd, + struct cfq_queue *cfqq) { - struct cfq_queue *cfqq; + struct cfq_rq *crq; /* - * if current queue is expired but not done with its requests yet, - * wait for that to happen + * follow expired path, else get first next available */ - if ((cfqq = cfqd->active_queue) != NULL) { - if (cfq_cfqq_expired(cfqq) && cfq_cfqq_dispatched(cfqq)) - return NULL; + if ((crq = cfq_check_fifo(cfqq)) == NULL) { + if (cfqd->find_best_crq) + crq = cfqq->next_crq; + else + crq = rb_entry_crq(rb_first(&cfqq->sort_list)); } - /* - * if current list is non-empty, grab first entry. if it is empty, - * get next prio level and grab first entry then if any are spliced - */ - if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1) - cfqq = list_entry_cfqq(cfqd->cur_rr.next); + cfqd->last_sector = crq->request->sector + crq->request->nr_sectors; /* - * if we have idle queues and no rt or be queues had pending - * requests, either allow immediate service if the grace period - * has passed or arm the idle grace timer + * finally, insert request into driver list */ - if (!cfqq && !list_empty(&cfqd->idle_rr)) { - unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE; - - if (time_after_eq(jiffies, end)) - cfqq = list_entry_cfqq(cfqd->idle_rr.next); - else - mod_timer(&cfqd->idle_class_timer, end); - } - - __cfq_set_active_queue(cfqd, cfqq); - return cfqq; + cfq_dispatch_sort(q, crq); } -/* - * current cfqq expired its slice (or was too idle), select new one - */ -static void -__cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, - int preempted) +static int cfq_dispatch_requests(request_queue_t *q, int max_dispatch) { - unsigned long now = jiffies; + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_queue *cfqq; + struct list_head *entry, *tmp; + int queued, busy_queues, first_round; - if (cfq_cfqq_wait_request(cfqq)) - del_timer(&cfqd->idle_slice_timer); + if (list_empty(&cfqd->rr_list)) + return 0; - if (!preempted && !cfq_cfqq_dispatched(cfqq)) - cfqq->service_last = now; + queued = 0; + first_round = 1; +restart: + busy_queues = 0; + list_for_each_safe(entry, tmp, &cfqd->rr_list) { + cfqq = list_entry_cfqq(entry); - cfq_clear_cfqq_must_dispatch(cfqq); - cfq_clear_cfqq_wait_request(cfqq); + BUG_ON(RB_EMPTY(&cfqq->sort_list)); - /* - * store what was left of this slice, if the queue idled out - * or was preempted - */ - if (time_after(now, cfqq->slice_end)) - cfqq->slice_left = now - cfqq->slice_end; - else - cfqq->slice_left = 0; + /* + * first round of queueing, only select from queues that + * don't already have io in-flight + */ + if (first_round && cfqq->in_flight) + continue; - if (cfq_cfqq_on_rr(cfqq)) - cfq_resort_rr_list(cfqq, preempted); + cfq_dispatch_request(q, cfqd, cfqq); - if (cfqq == cfqd->active_queue) - cfqd->active_queue = NULL; + if (!RB_EMPTY(&cfqq->sort_list)) + busy_queues++; - if (cfqd->active_cic) { - put_io_context(cfqd->active_cic->ioc); - cfqd->active_cic = NULL; + queued++; } - cfqd->dispatch_slice = 0; -} - -static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted) -{ - struct cfq_queue *cfqq = cfqd->active_queue; - - if (cfqq) { - /* - * use deferred expiry, if there are requests in progress as - * not to disturb the slice of the next queue - */ - if (cfq_cfqq_dispatched(cfqq)) - cfq_mark_cfqq_expired(cfqq); - else - __cfq_slice_expired(cfqd, cfqq, preempted); + if ((queued < max_dispatch) && (busy_queues || first_round)) { + first_round = 0; + goto restart; } -} -static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) + return queued; +} +static inline void cfq_account_dispatch(struct cfq_rq *crq) { - WARN_ON(!RB_EMPTY(&cfqq->sort_list)); - WARN_ON(cfqq != cfqd->active_queue); + struct cfq_queue *cfqq = crq->cfq_queue; + struct cfq_data *cfqd = cfqq->cfqd; + unsigned long now, elapsed; + + if (!blk_fs_request(crq->request)) + return; /* - * idle is disabled, either manually or by past process history + * accounted bit is necessary since some drivers will call + * elv_next_request() many times for the same request (eg ide) */ - if (!cfqd->cfq_slice_idle) - return 0; - if (!cfq_cfqq_idle_window(cfqq)) - return 0; + if (crq->accounted) + return; + + now = jiffies; + if (cfqq->service_start == ~0UL) + cfqq->service_start = now; + /* - * task has exited, don't wait + * on drives with tagged command queueing, command turn-around time + * doesn't necessarily reflect the time spent processing this very + * command inside the drive. so do the accounting differently there, + * by just sorting on the number of requests */ - if (cfqd->active_cic && !cfqd->active_cic->ioc->task) - return 0; + if (cfqd->cfq_tagged) { + if (time_after(now, cfqq->service_start + cfq_service)) { + cfqq->service_start = now; + cfqq->service_used /= 10; + } - cfq_mark_cfqq_must_dispatch(cfqq); - cfq_mark_cfqq_wait_request(cfqq); + cfqq->service_used++; + cfq_sort_rr_list(cfqq, 0); + } - if (!timer_pending(&cfqd->idle_slice_timer)) { - unsigned long slice_left = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle); + elapsed = now - crq->queue_start; + if (elapsed > max_elapsed_dispatch) + max_elapsed_dispatch = elapsed; - cfqd->idle_slice_timer.expires = jiffies + slice_left; - add_timer(&cfqd->idle_slice_timer); - } + crq->accounted = 1; + crq->service_start = now; - return 1; + if (++cfqd->rq_in_driver >= CFQ_MAX_TAG && !cfqd->cfq_tagged) { + cfqq->cfqd->cfq_tagged = 1; + printk("cfq: depth %d reached, tagging now on\n", CFQ_MAX_TAG); + } } -/* - * we dispatch cfqd->cfq_quantum requests in total from the rr_list queues, - * this function sector sorts the selected request to minimize seeks. we start - * at cfqd->last_sector, not 0. - */ -static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq) +static inline void +cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq) { - struct cfq_data *cfqd = q->elevator->elevator_data; - struct cfq_queue *cfqq = crq->cfq_queue; - struct list_head *head = &q->queue_head, *entry = head; - struct request *__rq; - sector_t last; + struct cfq_data *cfqd = cfqq->cfqd; - list_del(&crq->request->queuelist); - - last = cfqd->last_sector; - list_for_each_entry_reverse(__rq, head, queuelist) { - struct cfq_rq *__crq = RQ_DATA(__rq); - - if (blk_barrier_rq(__rq)) - break; - if (!blk_fs_request(__rq)) - break; - if (cfq_crq_requeued(__crq)) - break; - - if (__rq->sector <= crq->request->sector) - break; - if (__rq->sector > last && crq->request->sector < last) { - last = crq->request->sector + crq->request->nr_sectors; - break; - } - entry = &__rq->queuelist; - } - - cfqd->last_sector = last; - - cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq); - - cfq_del_crq_rb(crq); - cfq_remove_merge_hints(q, crq); - - cfq_mark_crq_in_flight(crq); - cfq_clear_crq_requeued(crq); - - cfqq->on_dispatch[cfq_crq_is_sync(crq)]++; - list_add_tail(&crq->request->queuelist, entry); -} - -/* - * return expired entry, or NULL to just start from scratch in rbtree - */ -static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq) -{ - struct cfq_data *cfqd = cfqq->cfqd; - struct request *rq; - struct cfq_rq *crq; - - if (cfq_cfqq_fifo_expire(cfqq)) - return NULL; - - if (!list_empty(&cfqq->fifo)) { - int fifo = cfq_cfqq_class_sync(cfqq); - - crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next)); - rq = crq->request; - if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) { - cfq_mark_cfqq_fifo_expire(cfqq); - return crq; - } - } - - return NULL; -} - -/* - * Scale schedule slice based on io priority. Use the sync time slice only - * if a queue is marked sync and has sync io queued. A sync queue with async - * io only, should not get full sync slice length. - */ -static inline int -cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - const int base_slice = cfqd->cfq_slice[cfq_cfqq_sync(cfqq)]; - - WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR); - - return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - cfqq->ioprio)); -} - -static inline void -cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies; -} - -static inline int -cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - const int base_rq = cfqd->cfq_slice_async_rq; - - WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR); - - return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio)); -} - -/* - * scheduler run of queue, if there are requests pending and no one in the - * driver that will restart queueing - */ -static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) -{ - if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd)) - kblockd_schedule_work(&cfqd->unplug_work); -} - -/* - * get next queue for service - */ -static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) -{ - unsigned long now = jiffies; - struct cfq_queue *cfqq; - - cfqq = cfqd->active_queue; - if (!cfqq) - goto new_queue; - - if (cfq_cfqq_expired(cfqq)) - goto new_queue; - - /* - * slice has expired - */ - if (!cfq_cfqq_must_dispatch(cfqq) && time_after(now, cfqq->slice_end)) - goto expire; - - /* - * if queue has requests, dispatch one. if not, check if - * enough slice is left to wait for one - */ - if (!RB_EMPTY(&cfqq->sort_list)) - goto keep_queue; - else if (!force && cfq_cfqq_class_sync(cfqq) && - time_before(now, cfqq->slice_end)) { - if (cfq_arm_slice_timer(cfqd, cfqq)) - return NULL; - } - -expire: - cfq_slice_expired(cfqd, 0); -new_queue: - cfqq = cfq_set_active_queue(cfqd); -keep_queue: - return cfqq; -} - -static int -__cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, - int max_dispatch) -{ - int dispatched = 0; - - BUG_ON(RB_EMPTY(&cfqq->sort_list)); - - do { - struct cfq_rq *crq; - - /* - * follow expired path, else get first next available - */ - if ((crq = cfq_check_fifo(cfqq)) == NULL) - crq = cfqq->next_crq; - - /* - * finally, insert request into driver dispatch list - */ - cfq_dispatch_sort(cfqd->queue, crq); - - cfqd->dispatch_slice++; - dispatched++; - - if (!cfqd->active_cic) { - atomic_inc(&crq->io_context->ioc->refcount); - cfqd->active_cic = crq->io_context; - } - - if (RB_EMPTY(&cfqq->sort_list)) - break; - - } while (dispatched < max_dispatch); - - /* - * if slice end isn't set yet, set it. if at least one request was - * sync, use the sync time slice value - */ - if (!cfqq->slice_end) - cfq_set_prio_slice(cfqd, cfqq); - - /* - * expire an async queue immediately if it has used up its slice. idle - * queue always expire after 1 dispatch round. - */ - if ((!cfq_cfqq_sync(cfqq) && - cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) || - cfq_class_idle(cfqq)) - cfq_slice_expired(cfqd, 0); - - return dispatched; -} - -static int -cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct cfq_queue *cfqq; - - if (!cfqd->busy_queues) - return 0; - - cfqq = cfq_select_queue(cfqd, force); - if (cfqq) { - cfq_clear_cfqq_must_dispatch(cfqq); - cfq_clear_cfqq_wait_request(cfqq); - del_timer(&cfqd->idle_slice_timer); - - if (cfq_class_idle(cfqq)) - max_dispatch = 1; - - return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); - } - - return 0; -} - -static inline void cfq_account_dispatch(struct cfq_rq *crq) -{ - struct cfq_queue *cfqq = crq->cfq_queue; - struct cfq_data *cfqd = cfqq->cfqd; - - if (unlikely(!blk_fs_request(crq->request))) - return; - - /* - * accounted bit is necessary since some drivers will call - * elv_next_request() many times for the same request (eg ide) - */ - if (cfq_crq_in_driver(crq)) - return; - - cfq_mark_crq_in_driver(crq); - cfqd->rq_in_driver++; -} - -static inline void -cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq) -{ - struct cfq_data *cfqd = cfqq->cfqd; - unsigned long now; - - if (!cfq_crq_in_driver(crq)) - return; - - now = jiffies; + if (!crq->accounted) + return; WARN_ON(!cfqd->rq_in_driver); cfqd->rq_in_driver--; - if (!cfq_class_idle(cfqq)) - cfqd->last_end_request = now; + if (!cfqd->cfq_tagged) { + unsigned long now = jiffies; + unsigned long duration = now - crq->service_start; - if (!cfq_cfqq_dispatched(cfqq)) { - if (cfq_cfqq_on_rr(cfqq)) { - cfqq->service_last = now; - cfq_resort_rr_list(cfqq, 0); - } - if (cfq_cfqq_expired(cfqq)) { - __cfq_slice_expired(cfqd, cfqq, 0); - cfq_schedule_dispatch(cfqd); + if (time_after(now, cfqq->service_start + cfq_service)) { + cfqq->service_start = now; + cfqq->service_used >>= 3; } - } - if (cfq_crq_is_sync(crq)) - crq->io_context->last_end_request = now; + cfqq->service_used += duration; + cfq_sort_rr_list(cfqq, 0); + + if (duration > max_elapsed_crq) + max_elapsed_crq = duration; + } } static struct request *cfq_next_request(request_queue_t *q) @@ -1261,18 +950,7 @@ static struct request *cfq_next_request(request_queue_t *q) dispatch: rq = list_entry_rq(q->queue_head.next); - crq = RQ_DATA(rq); - if (crq) { - struct cfq_queue *cfqq = crq->cfq_queue; - - /* - * if idle window is disabled, allow queue buildup - */ - if (!cfq_crq_in_driver(crq) && - !cfq_cfqq_idle_window(cfqq) && - cfqd->rq_in_driver >= cfqd->cfq_max_depth) - return NULL; - + if ((crq = RQ_DATA(rq)) != NULL) { cfq_remove_merge_hints(q, crq); cfq_account_dispatch(crq); } @@ -1280,7 +958,7 @@ static struct request *cfq_next_request(request_queue_t *q) return rq; } - if (cfq_dispatch_requests(q, cfqd->cfq_quantum, 0)) + if (cfq_dispatch_requests(q, cfqd->cfq_quantum)) goto dispatch; return NULL; @@ -1294,21 +972,13 @@ static struct request *cfq_next_request(request_queue_t *q) */ static void cfq_put_queue(struct cfq_queue *cfqq) { - struct cfq_data *cfqd = cfqq->cfqd; - - BUG_ON(atomic_read(&cfqq->ref) <= 0); + BUG_ON(!atomic_read(&cfqq->ref)); if (!atomic_dec_and_test(&cfqq->ref)) return; BUG_ON(rb_first(&cfqq->sort_list)); - BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]); - BUG_ON(cfq_cfqq_on_rr(cfqq)); - - if (unlikely(cfqd->active_queue == cfqq)) { - __cfq_slice_expired(cfqd, cfqq, 0); - cfq_schedule_dispatch(cfqd); - } + BUG_ON(cfqq->on_rr); cfq_put_cfqd(cfqq->cfqd); @@ -1321,17 +991,15 @@ static void cfq_put_queue(struct cfq_queue *cfqq) } static inline struct cfq_queue * -__cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio, - const int hashval) +__cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key, const int hashval) { struct hlist_head *hash_list = &cfqd->cfq_hash[hashval]; struct hlist_node *entry, *next; hlist_for_each_safe(entry, next, hash_list) { struct cfq_queue *__cfqq = list_entry_qhash(entry); - const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio); - if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY)) + if (__cfqq->key == key) return __cfqq; } @@ -1339,220 +1007,94 @@ __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio, } static struct cfq_queue * -cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio) +cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key) { - return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT)); + return __cfq_find_cfq_hash(cfqd, key, hash_long(key, CFQ_QHASH_SHIFT)); } -static void cfq_free_io_context(struct cfq_io_context *cic) +static inline void +cfq_rehash_cfqq(struct cfq_data *cfqd, struct cfq_queue **cfqq, + struct cfq_io_context *cic) { - struct cfq_io_context *__cic; - struct list_head *entry, *next; + unsigned long hashkey = cfq_hash_key(cfqd, current); + unsigned long hashval = hash_long(hashkey, CFQ_QHASH_SHIFT); + struct cfq_queue *__cfqq; + unsigned long flags; - list_for_each_safe(entry, next, &cic->list) { - __cic = list_entry(entry, struct cfq_io_context, list); - kmem_cache_free(cfq_ioc_pool, __cic); + spin_lock_irqsave(cfqd->queue->queue_lock, flags); + + hlist_del(&(*cfqq)->cfq_hash); + + __cfqq = __cfq_find_cfq_hash(cfqd, hashkey, hashval); + if (!__cfqq || __cfqq == *cfqq) { + __cfqq = *cfqq; + hlist_add_head(&__cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); + __cfqq->key_type = cfqd->key_type; + } else { + atomic_inc(&__cfqq->ref); + cic->cfqq = __cfqq; + cfq_put_queue(*cfqq); + *cfqq = __cfqq; } - kmem_cache_free(cfq_ioc_pool, cic); + cic->cfqq = __cfqq; + spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); } -/* - * Called with interrupts disabled - */ -static void cfq_exit_single_io_context(struct cfq_io_context *cic) +static void cfq_free_io_context(struct cfq_io_context *cic) { - struct cfq_data *cfqd = cic->cfqq->cfqd; - request_queue_t *q = cfqd->queue; - - WARN_ON(!irqs_disabled()); - - spin_lock(q->queue_lock); - - if (unlikely(cic->cfqq == cfqd->active_queue)) { - __cfq_slice_expired(cfqd, cic->cfqq, 0); - cfq_schedule_dispatch(cfqd); - } - - cfq_put_queue(cic->cfqq); - cic->cfqq = NULL; - spin_unlock(q->queue_lock); + kmem_cache_free(cfq_ioc_pool, cic); } /* - * Another task may update the task cic list, if it is doing a queue lookup - * on its behalf. cfq_cic_lock excludes such concurrent updates + * locking hierarchy is: io_context lock -> queue locks */ static void cfq_exit_io_context(struct cfq_io_context *cic) { - struct cfq_io_context *__cic; - struct list_head *entry; + struct cfq_queue *cfqq = cic->cfqq; + struct list_head *entry = &cic->list; + request_queue_t *q; unsigned long flags; - local_irq_save(flags); - /* * put the reference this task is holding to the various queues */ - list_for_each(entry, &cic->list) { + spin_lock_irqsave(&cic->ioc->lock, flags); + while ((entry = cic->list.next) != &cic->list) { + struct cfq_io_context *__cic; + __cic = list_entry(entry, struct cfq_io_context, list); - cfq_exit_single_io_context(__cic); + list_del(entry); + + q = __cic->cfqq->cfqd->queue; + spin_lock(q->queue_lock); + cfq_put_queue(__cic->cfqq); + spin_unlock(q->queue_lock); } - cfq_exit_single_io_context(cic); - local_irq_restore(flags); + q = cfqq->cfqd->queue; + spin_lock(q->queue_lock); + cfq_put_queue(cfqq); + spin_unlock(q->queue_lock); + + cic->cfqq = NULL; + spin_unlock_irqrestore(&cic->ioc->lock, flags); } -static struct cfq_io_context * -cfq_alloc_io_context(struct cfq_data *cfqd, int gfp_mask) +static struct cfq_io_context *cfq_alloc_io_context(int gfp_flags) { - struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask); + struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_flags); if (cic) { - INIT_LIST_HEAD(&cic->list); - cic->cfqq = NULL; - cic->key = NULL; - cic->last_end_request = jiffies; - cic->ttime_total = 0; - cic->ttime_samples = 0; - cic->ttime_mean = 0; cic->dtor = cfq_free_io_context; cic->exit = cfq_exit_io_context; + INIT_LIST_HEAD(&cic->list); + cic->cfqq = NULL; } return cic; } -static void cfq_init_prio_data(struct cfq_queue *cfqq) -{ - struct task_struct *tsk = current; - int ioprio_class; - - if (!cfq_cfqq_prio_changed(cfqq)) - return; - - ioprio_class = IOPRIO_PRIO_CLASS(tsk->ioprio); - switch (ioprio_class) { - default: - printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class); - case IOPRIO_CLASS_NONE: - /* - * no prio set, place us in the middle of the BE classes - */ - cfqq->ioprio = task_nice_ioprio(tsk); - cfqq->ioprio_class = IOPRIO_CLASS_BE; - break; - case IOPRIO_CLASS_RT: - cfqq->ioprio = task_ioprio(tsk); - cfqq->ioprio_class = IOPRIO_CLASS_RT; - break; - case IOPRIO_CLASS_BE: - cfqq->ioprio = task_ioprio(tsk); - cfqq->ioprio_class = IOPRIO_CLASS_BE; - break; - case IOPRIO_CLASS_IDLE: - cfqq->ioprio_class = IOPRIO_CLASS_IDLE; - cfqq->ioprio = 7; - cfq_clear_cfqq_idle_window(cfqq); - break; - } - - /* - * keep track of original prio settings in case we have to temporarily - * elevate the priority of this queue - */ - cfqq->org_ioprio = cfqq->ioprio; - cfqq->org_ioprio_class = cfqq->ioprio_class; - - if (cfq_cfqq_on_rr(cfqq)) - cfq_resort_rr_list(cfqq, 0); - - cfq_clear_cfqq_prio_changed(cfqq); -} - -static inline void changed_ioprio(struct cfq_queue *cfqq) -{ - if (cfqq) { - struct cfq_data *cfqd = cfqq->cfqd; - - spin_lock(cfqd->queue->queue_lock); - cfq_mark_cfqq_prio_changed(cfqq); - cfq_init_prio_data(cfqq); - spin_unlock(cfqd->queue->queue_lock); - } -} - -/* - * callback from sys_ioprio_set, irqs are disabled - */ -static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio) -{ - struct cfq_io_context *cic = ioc->cic; - - changed_ioprio(cic->cfqq); - - list_for_each_entry(cic, &cic->list, list) - changed_ioprio(cic->cfqq); - - return 0; -} - -static struct cfq_queue * -cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio, - int gfp_mask) -{ - const int hashval = hash_long(key, CFQ_QHASH_SHIFT); - struct cfq_queue *cfqq, *new_cfqq = NULL; - -retry: - cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval); - - if (!cfqq) { - if (new_cfqq) { - cfqq = new_cfqq; - new_cfqq = NULL; - } else if (gfp_mask & __GFP_WAIT) { - spin_unlock_irq(cfqd->queue->queue_lock); - new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); - spin_lock_irq(cfqd->queue->queue_lock); - goto retry; - } else { - cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); - if (!cfqq) - goto out; - } - - memset(cfqq, 0, sizeof(*cfqq)); - - INIT_HLIST_NODE(&cfqq->cfq_hash); - INIT_LIST_HEAD(&cfqq->cfq_list); - RB_CLEAR_ROOT(&cfqq->sort_list); - INIT_LIST_HEAD(&cfqq->fifo); - - cfqq->key = key; - hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); - atomic_set(&cfqq->ref, 0); - cfqq->cfqd = cfqd; - atomic_inc(&cfqd->ref); - cfqq->service_last = 0; - /* - * set ->slice_left to allow preemption for a new process - */ - cfqq->slice_left = 2 * cfqd->cfq_slice_idle; - cfq_mark_cfqq_idle_window(cfqq); - cfq_mark_cfqq_prio_changed(cfqq); - cfq_init_prio_data(cfqq); - } - - if (new_cfqq) - kmem_cache_free(cfq_pool, new_cfqq); - - atomic_inc(&cfqq->ref); -out: - WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq); - return cfqq; -} - /* * Setup general io context and cfq io context. There can be several cfq * io contexts per general io context, if this process is doing io to more @@ -1560,39 +1102,39 @@ cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio, * cfqq, so we don't need to worry about it disappearing */ static struct cfq_io_context * -cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask) +cfq_get_io_context(struct cfq_queue **cfqq, int gfp_flags) { - struct io_context *ioc = NULL; + struct cfq_data *cfqd = (*cfqq)->cfqd; + struct cfq_queue *__cfqq = *cfqq; struct cfq_io_context *cic; + struct io_context *ioc; - might_sleep_if(gfp_mask & __GFP_WAIT); + might_sleep_if(gfp_flags & __GFP_WAIT); - ioc = get_io_context(gfp_mask); + ioc = get_io_context(gfp_flags); if (!ioc) return NULL; if ((cic = ioc->cic) == NULL) { - cic = cfq_alloc_io_context(cfqd, gfp_mask); + cic = cfq_alloc_io_context(gfp_flags); if (cic == NULL) goto err; - /* - * manually increment generic io_context usage count, it - * cannot go away since we are already holding one ref to it - */ ioc->cic = cic; - ioc->set_ioprio = cfq_ioc_set_ioprio; cic->ioc = ioc; - cic->key = cfqd; - atomic_inc(&cfqd->ref); + cic->cfqq = __cfqq; + atomic_inc(&__cfqq->ref); } else { struct cfq_io_context *__cic; + unsigned long flags; /* - * the first cic on the list is actually the head itself + * since the first cic on the list is actually the head + * itself, need to check this here or we'll duplicate an + * cic per ioc for no reason */ - if (cic->key == cfqd) + if (cic->cfqq == __cfqq) goto out; /* @@ -1600,262 +1142,152 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask) * should be ok here, the list will usually not be more than * 1 or a few entries long */ + spin_lock_irqsave(&ioc->lock, flags); list_for_each_entry(__cic, &cic->list, list) { /* * this process is already holding a reference to * this queue, so no need to get one more */ - if (__cic->key == cfqd) { + if (__cic->cfqq == __cfqq) { cic = __cic; + spin_unlock_irqrestore(&ioc->lock, flags); goto out; } } + spin_unlock_irqrestore(&ioc->lock, flags); /* * nope, process doesn't have a cic assoicated with this * cfqq yet. get a new one and add to list */ - __cic = cfq_alloc_io_context(cfqd, gfp_mask); + __cic = cfq_alloc_io_context(gfp_flags); if (__cic == NULL) goto err; __cic->ioc = ioc; - __cic->key = cfqd; - atomic_inc(&cfqd->ref); + __cic->cfqq = __cfqq; + atomic_inc(&__cfqq->ref); + spin_lock_irqsave(&ioc->lock, flags); list_add(&__cic->list, &cic->list); - cic = __cic; - } + spin_unlock_irqrestore(&ioc->lock, flags); -out: - return cic; -err: - put_io_context(ioc); - return NULL; -} - -static void -cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic) -{ - unsigned long elapsed, ttime; - - /* - * if this context already has stuff queued, thinktime is from - * last queue not last end - */ -#if 0 - if (time_after(cic->last_end_request, cic->last_queue)) - elapsed = jiffies - cic->last_end_request; - else - elapsed = jiffies - cic->last_queue; -#else - elapsed = jiffies - cic->last_end_request; -#endif - - ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle); - - cic->ttime_samples = (7*cic->ttime_samples + 256) / 8; - cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8; - cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples; -} - -#define sample_valid(samples) ((samples) > 80) - -/* - * Disable idle window if the process thinks too long or seeks so much that - * it doesn't matter - */ -static void -cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, - struct cfq_io_context *cic) -{ - int enable_idle = cfq_cfqq_idle_window(cfqq); - - if (!cic->ioc->task || !cfqd->cfq_slice_idle) - enable_idle = 0; - else if (sample_valid(cic->ttime_samples)) { - if (cic->ttime_mean > cfqd->cfq_slice_idle) - enable_idle = 0; - else - enable_idle = 1; + cic = __cic; + *cfqq = __cfqq; } - if (enable_idle) - cfq_mark_cfqq_idle_window(cfqq); - else - cfq_clear_cfqq_idle_window(cfqq); -} - - -/* - * Check if new_cfqq should preempt the currently active queue. Return 0 for - * no or if we aren't sure, a 1 will cause a preempt. - */ -static int -cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, - struct cfq_rq *crq) -{ - struct cfq_queue *cfqq = cfqd->active_queue; - - if (cfq_class_idle(new_cfqq)) - return 0; - - if (!cfqq) - return 1; - - if (cfq_class_idle(cfqq)) - return 1; - if (!cfq_cfqq_wait_request(new_cfqq)) - return 0; +out: /* - * if it doesn't have slice left, forget it + * if key_type has been changed on the fly, we lazily rehash + * each queue at lookup time */ - if (new_cfqq->slice_left < cfqd->cfq_slice_idle) - return 0; - if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq)) - return 1; + if ((*cfqq)->key_type != cfqd->key_type) + cfq_rehash_cfqq(cfqd, cfqq, cic); - return 0; + return cic; +err: + put_io_context(ioc); + return NULL; } -/* - * cfqq preempts the active queue. if we allowed preempt with no slice left, - * let it have half of its nominal slice. - */ -static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) +static struct cfq_queue * +__cfq_get_queue(struct cfq_data *cfqd, unsigned long key, int gfp_mask) { - struct cfq_queue *__cfqq, *next; - - list_for_each_entry_safe(__cfqq, next, &cfqd->cur_rr, cfq_list) - cfq_resort_rr_list(__cfqq, 1); - - if (!cfqq->slice_left) - cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2; - - cfqq->slice_end = cfqq->slice_left + jiffies; - __cfq_slice_expired(cfqd, cfqq, 1); - __cfq_set_active_queue(cfqd, cfqq); -} + const int hashval = hash_long(key, CFQ_QHASH_SHIFT); + struct cfq_queue *cfqq, *new_cfqq = NULL; -/* - * should really be a ll_rw_blk.c helper - */ -static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - request_queue_t *q = cfqd->queue; +retry: + cfqq = __cfq_find_cfq_hash(cfqd, key, hashval); - if (!blk_queue_plugged(q)) - q->request_fn(q); - else - __generic_unplug_device(q); -} + if (!cfqq) { + if (new_cfqq) { + cfqq = new_cfqq; + new_cfqq = NULL; + } else { + spin_unlock_irq(cfqd->queue->queue_lock); + new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); + spin_lock_irq(cfqd->queue->queue_lock); -/* - * Called when a new fs request (crq) is added (to cfqq). Check if there's - * something we should do about it - */ -static void -cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, - struct cfq_rq *crq) -{ - const int sync = cfq_crq_is_sync(crq); + if (!new_cfqq && !(gfp_mask & __GFP_WAIT)) + goto out; - cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); + goto retry; + } - if (sync) { - struct cfq_io_context *cic = crq->io_context; + memset(cfqq, 0, sizeof(*cfqq)); - cfq_update_io_thinktime(cfqd, cic); - cfq_update_idle_window(cfqd, cfqq, cic); + INIT_HLIST_NODE(&cfqq->cfq_hash); + INIT_LIST_HEAD(&cfqq->cfq_list); + RB_CLEAR_ROOT(&cfqq->sort_list); + INIT_LIST_HEAD(&cfqq->fifo[0]); + INIT_LIST_HEAD(&cfqq->fifo[1]); - cic->last_queue = jiffies; + cfqq->key = key; + hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); + atomic_set(&cfqq->ref, 0); + cfqq->cfqd = cfqd; + atomic_inc(&cfqd->ref); + cfqq->key_type = cfqd->key_type; + cfqq->service_start = ~0UL; } - if (cfqq == cfqd->active_queue) { - /* - * if we are waiting for a request for this queue, let it rip - * immediately and flag that we must not expire this queue - * just now - */ - if (cfq_cfqq_wait_request(cfqq)) { - cfq_mark_cfqq_must_dispatch(cfqq); - del_timer(&cfqd->idle_slice_timer); - cfq_start_queueing(cfqd, cfqq); - } - } else if (cfq_should_preempt(cfqd, cfqq, crq)) { - /* - * not the active queue - expire current slice if it is - * idle and has expired it's mean thinktime or this new queue - * has some old slice time left and is of higher priority - */ - cfq_preempt_queue(cfqd, cfqq); - cfq_mark_cfqq_must_dispatch(cfqq); - cfq_start_queueing(cfqd, cfqq); - } + if (new_cfqq) + kmem_cache_free(cfq_pool, new_cfqq); + + atomic_inc(&cfqq->ref); +out: + WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq); + return cfqq; } -static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq) +static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq) { - struct cfq_rq *crq = RQ_DATA(rq); - struct cfq_queue *cfqq = crq->cfq_queue; - - cfq_init_prio_data(cfqq); + crq->is_sync = 0; + if (rq_data_dir(crq->request) == READ || current->flags & PF_SYNCWRITE) + crq->is_sync = 1; cfq_add_crq_rb(crq); + crq->queue_start = jiffies; - list_add_tail(&rq->queuelist, &cfqq->fifo); - - if (rq_mergeable(rq)) { - cfq_add_crq_hash(cfqd, crq); - - if (!cfqd->queue->last_merge) - cfqd->queue->last_merge = rq; - } - - cfq_crq_enqueued(cfqd, cfqq, crq); + list_add_tail(&crq->request->queuelist, &crq->cfq_queue->fifo[crq->is_sync]); } static void cfq_insert_request(request_queue_t *q, struct request *rq, int where) { struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_rq *crq = RQ_DATA(rq); switch (where) { case ELEVATOR_INSERT_BACK: - while (cfq_dispatch_requests(q, INT_MAX, 1)) + while (cfq_dispatch_requests(q, cfqd->cfq_quantum)) ; list_add_tail(&rq->queuelist, &q->queue_head); - /* - * If we were idling with pending requests on - * inactive cfqqs, force dispatching will - * remove the idle timer and the queue won't - * be kicked by __make_request() afterward. - * Kick it here. - */ - cfq_schedule_dispatch(cfqd); break; case ELEVATOR_INSERT_FRONT: list_add(&rq->queuelist, &q->queue_head); break; case ELEVATOR_INSERT_SORT: BUG_ON(!blk_fs_request(rq)); - cfq_enqueue(cfqd, rq); + cfq_enqueue(cfqd, crq); break; default: printk("%s: bad insert point %d\n", __FUNCTION__,where); return; } -} -static inline int cfq_pending_requests(struct cfq_data *cfqd) -{ - return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues; + if (rq_mergeable(rq)) { + cfq_add_crq_hash(cfqd, crq); + + if (!q->last_merge) + q->last_merge = rq; + } } static int cfq_queue_empty(request_queue_t *q) { struct cfq_data *cfqd = q->elevator->elevator_data; - return !cfq_pending_requests(cfqd); + return list_empty(&q->queue_head) && list_empty(&cfqd->rr_list); } static void cfq_completed_request(request_queue_t *q, struct request *rq) @@ -1868,11 +1300,9 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq) cfqq = crq->cfq_queue; - if (cfq_crq_in_flight(crq)) { - const int sync = cfq_crq_is_sync(crq); - - WARN_ON(!cfqq->on_dispatch[sync]); - cfqq->on_dispatch[sync]--; + if (crq->in_flight) { + WARN_ON(!cfqq->in_flight); + cfqq->in_flight--; } cfq_account_completion(cfqq, crq); @@ -1902,136 +1332,51 @@ cfq_latter_request(request_queue_t *q, struct request *rq) return NULL; } -/* - * we temporarily boost lower priority queues if they are holding fs exclusive - * resources. they are boosted to normal prio (CLASS_BE/4) - */ -static void cfq_prio_boost(struct cfq_queue *cfqq) -{ - const int ioprio_class = cfqq->ioprio_class; - const int ioprio = cfqq->ioprio; - - if (has_fs_excl()) { - /* - * boost idle prio on transactions that would lock out other - * users of the filesystem - */ - if (cfq_class_idle(cfqq)) - cfqq->ioprio_class = IOPRIO_CLASS_BE; - if (cfqq->ioprio > IOPRIO_NORM) - cfqq->ioprio = IOPRIO_NORM; - } else { - /* - * check if we need to unboost the queue - */ - if (cfqq->ioprio_class != cfqq->org_ioprio_class) - cfqq->ioprio_class = cfqq->org_ioprio_class; - if (cfqq->ioprio != cfqq->org_ioprio) - cfqq->ioprio = cfqq->org_ioprio; - } - - /* - * refile between round-robin lists if we moved the priority class - */ - if ((ioprio_class != cfqq->ioprio_class || ioprio != cfqq->ioprio) && - cfq_cfqq_on_rr(cfqq)) - cfq_resort_rr_list(cfqq, 0); -} - -static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) +static int cfq_may_queue(request_queue_t *q, int rw) { - if (rw == READ || process_sync(task)) - return task->pid; - - return CFQ_KEY_ASYNC; -} - -static inline int -__cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, - struct task_struct *task, int rw) -{ -#if 1 - if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && - !cfq_cfqq_must_alloc_slice) { - cfq_mark_cfqq_must_alloc_slice(cfqq); - return ELV_MQUEUE_MUST; - } - - return ELV_MQUEUE_MAY; -#else - if (!cfqq || task->flags & PF_MEMALLOC) - return ELV_MQUEUE_MAY; - if (!cfqq->allocated[rw] || cfq_cfqq_must_alloc(cfqq)) { - if (cfq_cfqq_wait_request(cfqq)) - return ELV_MQUEUE_MUST; - - /* - * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we - * can quickly flood the queue with writes from a single task - */ - if (rw == READ || !cfq_cfqq_must_alloc_slice) { - cfq_mark_cfqq_must_alloc_slice(cfqq); - return ELV_MQUEUE_MUST; - } + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_queue *cfqq; + int ret = ELV_MQUEUE_MAY; + if (current->flags & PF_MEMALLOC) return ELV_MQUEUE_MAY; - } - if (cfq_class_idle(cfqq)) - return ELV_MQUEUE_NO; - if (cfqq->allocated[rw] >= cfqd->max_queued) { - struct io_context *ioc = get_io_context(GFP_ATOMIC); - int ret = ELV_MQUEUE_NO; - if (ioc && ioc->nr_batch_requests) - ret = ELV_MQUEUE_MAY; + cfqq = cfq_find_cfq_hash(cfqd, cfq_hash_key(cfqd, current)); + if (cfqq) { + int limit = cfqd->max_queued; - put_io_context(ioc); - return ret; - } + if (cfqq->allocated[rw] < cfqd->cfq_queued) + return ELV_MQUEUE_MUST; - return ELV_MQUEUE_MAY; -#endif -} + if (cfqd->busy_queues) + limit = q->nr_requests / cfqd->busy_queues; -static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct task_struct *tsk = current; - struct cfq_queue *cfqq; + if (limit < cfqd->cfq_queued) + limit = cfqd->cfq_queued; + else if (limit > cfqd->max_queued) + limit = cfqd->max_queued; - /* - * don't force setup of a queue from here, as a call to may_queue - * does not necessarily imply that a request actually will be queued. - * so just lookup a possibly existing queue, or return 'may queue' - * if that fails - */ - cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio); - if (cfqq) { - cfq_init_prio_data(cfqq); - cfq_prio_boost(cfqq); + if (cfqq->allocated[rw] >= limit) { + if (limit > cfqq->alloc_limit[rw]) + cfqq->alloc_limit[rw] = limit; - return __cfq_may_queue(cfqd, cfqq, tsk, rw); + ret = ELV_MQUEUE_NO; + } } - return ELV_MQUEUE_MAY; + return ret; } static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq) { - struct cfq_data *cfqd = q->elevator->elevator_data; struct request_list *rl = &q->rq; + const int write = waitqueue_active(&rl->wait[WRITE]); + const int read = waitqueue_active(&rl->wait[READ]); - if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) { - smp_mb(); - if (waitqueue_active(&rl->wait[READ])) - wake_up(&rl->wait[READ]); - } - - if (cfqq->allocated[WRITE] <= cfqd->max_queued || cfqd->rq_starved) { - smp_mb(); - if (waitqueue_active(&rl->wait[WRITE])) - wake_up(&rl->wait[WRITE]); - } + if (read && cfqq->allocated[READ] < cfqq->alloc_limit[READ]) + wake_up(&rl->wait[READ]); + if (write && cfqq->allocated[WRITE] < cfqq->alloc_limit[WRITE]) + wake_up(&rl->wait[WRITE]); } /* @@ -2044,61 +1389,69 @@ static void cfq_put_request(request_queue_t *q, struct request *rq) if (crq) { struct cfq_queue *cfqq = crq->cfq_queue; - const int rw = rq_data_dir(rq); - BUG_ON(!cfqq->allocated[rw]); - cfqq->allocated[rw]--; + BUG_ON(q->last_merge == rq); + BUG_ON(!hlist_unhashed(&crq->hash)); + + if (crq->io_context) + put_io_context(crq->io_context->ioc); - put_io_context(crq->io_context->ioc); + BUG_ON(!cfqq->allocated[crq->is_write]); + cfqq->allocated[crq->is_write]--; mempool_free(crq, cfqd->crq_pool); rq->elevator_private = NULL; + smp_mb(); cfq_check_waiters(q, cfqq); cfq_put_queue(cfqq); } } /* - * Allocate cfq data structures associated with this request. + * Allocate cfq data structures associated with this request. A queue and */ -static int -cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, - int gfp_mask) +static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask) { struct cfq_data *cfqd = q->elevator->elevator_data; - struct task_struct *tsk = current; struct cfq_io_context *cic; const int rw = rq_data_dir(rq); - pid_t key = cfq_queue_pid(tsk, rw); - struct cfq_queue *cfqq; + struct cfq_queue *cfqq, *saved_cfqq; struct cfq_rq *crq; unsigned long flags; might_sleep_if(gfp_mask & __GFP_WAIT); - cic = cfq_get_io_context(cfqd, key, gfp_mask); - spin_lock_irqsave(q->queue_lock, flags); - if (!cic) - goto queue_fail; - - if (!cic->cfqq) { - cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask); - if (!cfqq) - goto queue_fail; + cfqq = __cfq_get_queue(cfqd, cfq_hash_key(cfqd, current), gfp_mask); + if (!cfqq) + goto out_lock; - cic->cfqq = cfqq; - } else - cfqq = cic->cfqq; +repeat: + if (cfqq->allocated[rw] >= cfqd->max_queued) + goto out_lock; cfqq->allocated[rw]++; - cfq_clear_cfqq_must_alloc(cfqq); - cfqd->rq_starved = 0; - atomic_inc(&cfqq->ref); spin_unlock_irqrestore(q->queue_lock, flags); + /* + * if hashing type has changed, the cfq_queue might change here. + */ + saved_cfqq = cfqq; + cic = cfq_get_io_context(&cfqq, gfp_mask); + if (!cic) + goto err; + + /* + * repeat allocation checks on queue change + */ + if (unlikely(saved_cfqq != cfqq)) { + spin_lock_irqsave(q->queue_lock, flags); + saved_cfqq->allocated[rw]--; + goto repeat; + } + crq = mempool_alloc(cfqd->crq_pool, gfp_mask); if (crq) { RB_CLEAR(&crq->rb_node); @@ -2107,141 +1460,24 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, INIT_HLIST_NODE(&crq->hash); crq->cfq_queue = cfqq; crq->io_context = cic; - cfq_clear_crq_in_flight(crq); - cfq_clear_crq_in_driver(crq); - cfq_clear_crq_requeued(crq); - - if (rw == READ || process_sync(tsk)) - cfq_mark_crq_is_sync(crq); - else - cfq_clear_crq_is_sync(crq); - + crq->service_start = crq->queue_start = 0; + crq->in_flight = crq->accounted = crq->is_sync = 0; + crq->is_write = rw; rq->elevator_private = crq; + cfqq->alloc_limit[rw] = 0; return 0; } + put_io_context(cic->ioc); +err: spin_lock_irqsave(q->queue_lock, flags); cfqq->allocated[rw]--; - if (!(cfqq->allocated[0] + cfqq->allocated[1])) - cfq_mark_cfqq_must_alloc(cfqq); cfq_put_queue(cfqq); -queue_fail: - if (cic) - put_io_context(cic->ioc); - /* - * mark us rq allocation starved. we need to kickstart the process - * ourselves if there are no pending requests that can do it for us. - * that would be an extremely rare OOM situation - */ - cfqd->rq_starved = 1; - cfq_schedule_dispatch(cfqd); +out_lock: spin_unlock_irqrestore(q->queue_lock, flags); return 1; } -static void cfq_kick_queue(void *data) -{ - request_queue_t *q = data; - struct cfq_data *cfqd = q->elevator->elevator_data; - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - - if (cfqd->rq_starved) { - struct request_list *rl = &q->rq; - - /* - * we aren't guaranteed to get a request after this, but we - * have to be opportunistic - */ - smp_mb(); - if (waitqueue_active(&rl->wait[READ])) - wake_up(&rl->wait[READ]); - if (waitqueue_active(&rl->wait[WRITE])) - wake_up(&rl->wait[WRITE]); - } - - blk_remove_plug(q); - q->request_fn(q); - spin_unlock_irqrestore(q->queue_lock, flags); -} - -/* - * Timer running if the active_queue is currently idling inside its time slice - */ -static void cfq_idle_slice_timer(unsigned long data) -{ - struct cfq_data *cfqd = (struct cfq_data *) data; - struct cfq_queue *cfqq; - unsigned long flags; - - spin_lock_irqsave(cfqd->queue->queue_lock, flags); - - if ((cfqq = cfqd->active_queue) != NULL) { - unsigned long now = jiffies; - - /* - * expired - */ - if (time_after(now, cfqq->slice_end)) - goto expire; - - /* - * only expire and reinvoke request handler, if there are - * other queues with pending requests - */ - if (!cfq_pending_requests(cfqd)) { - cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end); - add_timer(&cfqd->idle_slice_timer); - goto out_cont; - } - - /* - * not expired and it has a request pending, let it dispatch - */ - if (!RB_EMPTY(&cfqq->sort_list)) { - cfq_mark_cfqq_must_dispatch(cfqq); - goto out_kick; - } - } -expire: - cfq_slice_expired(cfqd, 0); -out_kick: - cfq_schedule_dispatch(cfqd); -out_cont: - spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); -} - -/* - * Timer running if an idle class queue is waiting for service - */ -static void cfq_idle_class_timer(unsigned long data) -{ - struct cfq_data *cfqd = (struct cfq_data *) data; - unsigned long flags, end; - - spin_lock_irqsave(cfqd->queue->queue_lock, flags); - - /* - * race with a non-idle queue, reset timer - */ - end = cfqd->last_end_request + CFQ_IDLE_GRACE; - if (!time_after_eq(jiffies, end)) { - cfqd->idle_class_timer.expires = end; - add_timer(&cfqd->idle_class_timer); - } else - cfq_schedule_dispatch(cfqd); - - spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); -} - -static void cfq_shutdown_timer_wq(struct cfq_data *cfqd) -{ - del_timer_sync(&cfqd->idle_slice_timer); - del_timer_sync(&cfqd->idle_class_timer); - blk_sync_queue(cfqd->queue); -} - static void cfq_put_cfqd(struct cfq_data *cfqd) { request_queue_t *q = cfqd->queue; @@ -2251,9 +1487,6 @@ static void cfq_put_cfqd(struct cfq_data *cfqd) blk_put_queue(q); - cfq_shutdown_timer_wq(cfqd); - q->elevator->elevator_data = NULL; - mempool_destroy(cfqd->crq_pool); kfree(cfqd->crq_hash); kfree(cfqd->cfq_hash); @@ -2262,10 +1495,7 @@ static void cfq_put_cfqd(struct cfq_data *cfqd) static void cfq_exit_queue(elevator_t *e) { - struct cfq_data *cfqd = e->elevator_data; - - cfq_shutdown_timer_wq(cfqd); - cfq_put_cfqd(cfqd); + cfq_put_cfqd(e->elevator_data); } static int cfq_init_queue(request_queue_t *q, elevator_t *e) @@ -2278,13 +1508,7 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e) return -ENOMEM; memset(cfqd, 0, sizeof(*cfqd)); - - for (i = 0; i < CFQ_PRIO_LISTS; i++) - INIT_LIST_HEAD(&cfqd->rr_list[i]); - - INIT_LIST_HEAD(&cfqd->busy_rr); - INIT_LIST_HEAD(&cfqd->cur_rr); - INIT_LIST_HEAD(&cfqd->idle_rr); + INIT_LIST_HEAD(&cfqd->rr_list); INIT_LIST_HEAD(&cfqd->empty_list); cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); @@ -2309,32 +1533,24 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e) cfqd->queue = q; atomic_inc(&q->refcnt); - cfqd->max_queued = q->nr_requests / 4; + /* + * just set it to some high value, we want anyone to be able to queue + * some requests. fairness is handled differently + */ + q->nr_requests = 1024; + cfqd->max_queued = q->nr_requests / 16; q->nr_batching = cfq_queued; - - init_timer(&cfqd->idle_slice_timer); - cfqd->idle_slice_timer.function = cfq_idle_slice_timer; - cfqd->idle_slice_timer.data = (unsigned long) cfqd; - - init_timer(&cfqd->idle_class_timer); - cfqd->idle_class_timer.function = cfq_idle_class_timer; - cfqd->idle_class_timer.data = (unsigned long) cfqd; - - INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); - + cfqd->key_type = CFQ_KEY_TGID; + cfqd->find_best_crq = 1; atomic_set(&cfqd->ref, 1); cfqd->cfq_queued = cfq_queued; cfqd->cfq_quantum = cfq_quantum; - cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; - cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1]; + cfqd->cfq_fifo_expire_r = cfq_fifo_expire_r; + cfqd->cfq_fifo_expire_w = cfq_fifo_expire_w; + cfqd->cfq_fifo_batch_expire = cfq_fifo_rate; cfqd->cfq_back_max = cfq_back_max; cfqd->cfq_back_penalty = cfq_back_penalty; - cfqd->cfq_slice[0] = cfq_slice_async; - cfqd->cfq_slice[1] = cfq_slice_sync; - cfqd->cfq_slice_async_rq = cfq_slice_async_rq; - cfqd->cfq_slice_idle = cfq_slice_idle; - cfqd->cfq_max_depth = cfq_max_depth; return 0; out_crqpool: @@ -2379,6 +1595,7 @@ static int __init cfq_slab_setup(void) return -ENOMEM; } + /* * sysfs parts below --> */ @@ -2403,6 +1620,45 @@ cfq_var_store(unsigned int *var, const char *page, size_t count) return count; } +static ssize_t +cfq_clear_elapsed(struct cfq_data *cfqd, const char *page, size_t count) +{ + max_elapsed_dispatch = max_elapsed_crq = 0; + return count; +} + +static ssize_t +cfq_set_key_type(struct cfq_data *cfqd, const char *page, size_t count) +{ + spin_lock_irq(cfqd->queue->queue_lock); + if (!strncmp(page, "pgid", 4)) + cfqd->key_type = CFQ_KEY_PGID; + else if (!strncmp(page, "tgid", 4)) + cfqd->key_type = CFQ_KEY_TGID; + else if (!strncmp(page, "uid", 3)) + cfqd->key_type = CFQ_KEY_UID; + else if (!strncmp(page, "gid", 3)) + cfqd->key_type = CFQ_KEY_GID; + spin_unlock_irq(cfqd->queue->queue_lock); + return count; +} + +static ssize_t +cfq_read_key_type(struct cfq_data *cfqd, char *page) +{ + ssize_t len = 0; + int i; + + for (i = CFQ_KEY_PGID; i < CFQ_KEY_LAST; i++) { + if (cfqd->key_type == i) + len += sprintf(page+len, "[%s] ", cfq_key_types[i]); + else + len += sprintf(page+len, "%s ", cfq_key_types[i]); + } + len += sprintf(page+len, "\n"); + return len; +} + #define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ { \ @@ -2413,15 +1669,12 @@ static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ } SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0); SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0); -SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1); -SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1); +SHOW_FUNCTION(cfq_fifo_expire_r_show, cfqd->cfq_fifo_expire_r, 1); +SHOW_FUNCTION(cfq_fifo_expire_w_show, cfqd->cfq_fifo_expire_w, 1); +SHOW_FUNCTION(cfq_fifo_batch_expire_show, cfqd->cfq_fifo_batch_expire, 1); +SHOW_FUNCTION(cfq_find_best_show, cfqd->find_best_crq, 0); SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0); SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0); -SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1); -SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); -SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); -SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); -SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0); #undef SHOW_FUNCTION #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ @@ -2441,15 +1694,12 @@ static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \ } STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0); STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0); -STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1); -STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1); +STORE_FUNCTION(cfq_fifo_expire_r_store, &cfqd->cfq_fifo_expire_r, 1, UINT_MAX, 1); +STORE_FUNCTION(cfq_fifo_expire_w_store, &cfqd->cfq_fifo_expire_w, 1, UINT_MAX, 1); +STORE_FUNCTION(cfq_fifo_batch_expire_store, &cfqd->cfq_fifo_batch_expire, 0, UINT_MAX, 1); +STORE_FUNCTION(cfq_find_best_store, &cfqd->find_best_crq, 0, 1, 0); STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0); -STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1); -STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); -STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); -STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0); -STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); #undef STORE_FUNCTION static struct cfq_fs_entry cfq_quantum_entry = { @@ -2462,15 +1712,25 @@ static struct cfq_fs_entry cfq_queued_entry = { .show = cfq_queued_show, .store = cfq_queued_store, }; -static struct cfq_fs_entry cfq_fifo_expire_sync_entry = { +static struct cfq_fs_entry cfq_fifo_expire_r_entry = { .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_fifo_expire_sync_show, - .store = cfq_fifo_expire_sync_store, + .show = cfq_fifo_expire_r_show, + .store = cfq_fifo_expire_r_store, }; -static struct cfq_fs_entry cfq_fifo_expire_async_entry = { +static struct cfq_fs_entry cfq_fifo_expire_w_entry = { .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_fifo_expire_async_show, - .store = cfq_fifo_expire_async_store, + .show = cfq_fifo_expire_w_show, + .store = cfq_fifo_expire_w_store, +}; +static struct cfq_fs_entry cfq_fifo_batch_expire_entry = { + .attr = {.name = "fifo_batch_expire", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_fifo_batch_expire_show, + .store = cfq_fifo_batch_expire_store, +}; +static struct cfq_fs_entry cfq_find_best_entry = { + .attr = {.name = "find_best_crq", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_find_best_show, + .store = cfq_find_best_store, }; static struct cfq_fs_entry cfq_back_max_entry = { .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR }, @@ -2482,44 +1742,27 @@ static struct cfq_fs_entry cfq_back_penalty_entry = { .show = cfq_back_penalty_show, .store = cfq_back_penalty_store, }; -static struct cfq_fs_entry cfq_slice_sync_entry = { - .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_slice_sync_show, - .store = cfq_slice_sync_store, -}; -static struct cfq_fs_entry cfq_slice_async_entry = { - .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_slice_async_show, - .store = cfq_slice_async_store, -}; -static struct cfq_fs_entry cfq_slice_async_rq_entry = { - .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_slice_async_rq_show, - .store = cfq_slice_async_rq_store, +static struct cfq_fs_entry cfq_clear_elapsed_entry = { + .attr = {.name = "clear_elapsed", .mode = S_IWUSR }, + .store = cfq_clear_elapsed, }; -static struct cfq_fs_entry cfq_slice_idle_entry = { - .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_slice_idle_show, - .store = cfq_slice_idle_store, -}; -static struct cfq_fs_entry cfq_max_depth_entry = { - .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_max_depth_show, - .store = cfq_max_depth_store, +static struct cfq_fs_entry cfq_key_type_entry = { + .attr = {.name = "key_type", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_read_key_type, + .store = cfq_set_key_type, }; static struct attribute *default_attrs[] = { &cfq_quantum_entry.attr, &cfq_queued_entry.attr, - &cfq_fifo_expire_sync_entry.attr, - &cfq_fifo_expire_async_entry.attr, + &cfq_fifo_expire_r_entry.attr, + &cfq_fifo_expire_w_entry.attr, + &cfq_fifo_batch_expire_entry.attr, + &cfq_key_type_entry.attr, + &cfq_find_best_entry.attr, &cfq_back_max_entry.attr, &cfq_back_penalty_entry.attr, - &cfq_slice_sync_entry.attr, - &cfq_slice_async_entry.attr, - &cfq_slice_async_rq_entry.attr, - &cfq_slice_idle_entry.attr, - &cfq_max_depth_entry.attr, + &cfq_clear_elapsed_entry.attr, NULL, }; @@ -2589,46 +1832,21 @@ static int __init cfq_init(void) { int ret; - /* - * could be 0 on HZ < 1000 setups - */ - if (!cfq_slice_async) - cfq_slice_async = 1; - if (!cfq_slice_idle) - cfq_slice_idle = 1; - if (cfq_slab_setup()) return -ENOMEM; ret = elv_register(&iosched_cfq); - if (ret) - cfq_slab_kill(); + if (!ret) { + __module_get(THIS_MODULE); + return 0; + } + cfq_slab_kill(); return ret; } static void __exit cfq_exit(void) { - struct task_struct *g, *p; - unsigned long flags; - - read_lock_irqsave(&tasklist_lock, flags); - - /* - * iterate each process in the system, removing our io_context - */ - do_each_thread(g, p) { - struct io_context *ioc = p->io_context; - - if (ioc && ioc->cic) { - ioc->cic->exit(ioc->cic); - cfq_free_io_context(ioc->cic); - ioc->cic = NULL; - } - } while_each_thread(g, p); - - read_unlock_irqrestore(&tasklist_lock, flags); - cfq_slab_kill(); elv_unregister(&iosched_cfq); } diff --git a/trunk/drivers/block/deadline-iosched.c b/trunk/drivers/block/deadline-iosched.c index ff5201e02153..4bc2fea73273 100644 --- a/trunk/drivers/block/deadline-iosched.c +++ b/trunk/drivers/block/deadline-iosched.c @@ -760,8 +760,7 @@ static void deadline_put_request(request_queue_t *q, struct request *rq) } static int -deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio, - int gfp_mask) +deadline_set_request(request_queue_t *q, struct request *rq, int gfp_mask) { struct deadline_data *dd = q->elevator->elevator_data; struct deadline_rq *drq; diff --git a/trunk/drivers/block/elevator.c b/trunk/drivers/block/elevator.c index 98f0126a2deb..f831f08f839c 100644 --- a/trunk/drivers/block/elevator.c +++ b/trunk/drivers/block/elevator.c @@ -486,13 +486,12 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq) return NULL; } -int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio, - int gfp_mask) +int elv_set_request(request_queue_t *q, struct request *rq, int gfp_mask) { elevator_t *e = q->elevator; if (e->ops->elevator_set_req_fn) - return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask); + return e->ops->elevator_set_req_fn(q, rq, gfp_mask); rq->elevator_private = NULL; return 0; @@ -506,12 +505,12 @@ void elv_put_request(request_queue_t *q, struct request *rq) e->ops->elevator_put_req_fn(q, rq); } -int elv_may_queue(request_queue_t *q, int rw, struct bio *bio) +int elv_may_queue(request_queue_t *q, int rw) { elevator_t *e = q->elevator; if (e->ops->elevator_may_queue_fn) - return e->ops->elevator_may_queue_fn(q, rw, bio); + return e->ops->elevator_may_queue_fn(q, rw); return ELV_MQUEUE_MAY; } diff --git a/trunk/drivers/block/ll_rw_blk.c b/trunk/drivers/block/ll_rw_blk.c index 234fdcfbdf01..60e64091de1b 100644 --- a/trunk/drivers/block/ll_rw_blk.c +++ b/trunk/drivers/block/ll_rw_blk.c @@ -276,7 +276,6 @@ static inline void rq_init(request_queue_t *q, struct request *rq) rq->errors = 0; rq->rq_status = RQ_ACTIVE; rq->bio = rq->biotail = NULL; - rq->ioprio = 0; rq->buffer = NULL; rq->ref_count = 1; rq->q = q; @@ -1443,7 +1442,11 @@ void __generic_unplug_device(request_queue_t *q) if (!blk_remove_plug(q)) return; - q->request_fn(q); + /* + * was plugged, fire request_fn if queue has stuff to do + */ + if (elv_next_request(q)) + q->request_fn(q); } EXPORT_SYMBOL(__generic_unplug_device); @@ -1773,8 +1776,8 @@ static inline void blk_free_request(request_queue_t *q, struct request *rq) mempool_free(rq, q->rq.rq_pool); } -static inline struct request * -blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask) +static inline struct request *blk_alloc_request(request_queue_t *q, int rw, + int gfp_mask) { struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); @@ -1787,7 +1790,7 @@ blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask) */ rq->flags = rw; - if (!elv_set_request(q, rq, bio, gfp_mask)) + if (!elv_set_request(q, rq, gfp_mask)) return rq; mempool_free(rq, q->rq.rq_pool); @@ -1869,8 +1872,7 @@ static void freed_request(request_queue_t *q, int rw) /* * Get a free request, queue_lock must not be held */ -static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, - int gfp_mask) +static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) { struct request *rq = NULL; struct request_list *rl = &q->rq; @@ -1893,7 +1895,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, } } - switch (elv_may_queue(q, rw, bio)) { + switch (elv_may_queue(q, rw)) { case ELV_MQUEUE_NO: goto rq_starved; case ELV_MQUEUE_MAY: @@ -1918,7 +1920,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, set_queue_congested(q, rw); spin_unlock_irq(q->queue_lock); - rq = blk_alloc_request(q, rw, bio, gfp_mask); + rq = blk_alloc_request(q, rw, gfp_mask); if (!rq) { /* * Allocation failed presumably due to memory. Undo anything @@ -1959,8 +1961,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, * No available requests for this queue, unplug the device and wait for some * requests to become available. */ -static struct request *get_request_wait(request_queue_t *q, int rw, - struct bio *bio) +static struct request *get_request_wait(request_queue_t *q, int rw) { DEFINE_WAIT(wait); struct request *rq; @@ -1971,7 +1972,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw, prepare_to_wait_exclusive(&rl->wait[rw], &wait, TASK_UNINTERRUPTIBLE); - rq = get_request(q, rw, bio, GFP_NOIO); + rq = get_request(q, rw, GFP_NOIO); if (!rq) { struct io_context *ioc; @@ -2002,9 +2003,9 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask) BUG_ON(rw != READ && rw != WRITE); if (gfp_mask & __GFP_WAIT) - rq = get_request_wait(q, rw, NULL); + rq = get_request_wait(q, rw); else - rq = get_request(q, rw, NULL, gfp_mask); + rq = get_request(q, rw, gfp_mask); return rq; } @@ -2332,6 +2333,7 @@ static void __blk_put_request(request_queue_t *q, struct request *req) return; req->rq_status = RQ_INACTIVE; + req->q = NULL; req->rl = NULL; /* @@ -2460,8 +2462,6 @@ static int attempt_merge(request_queue_t *q, struct request *req, req->rq_disk->in_flight--; } - req->ioprio = ioprio_best(req->ioprio, next->ioprio); - __blk_put_request(q, next); return 1; } @@ -2514,13 +2514,11 @@ static int __make_request(request_queue_t *q, struct bio *bio) { struct request *req, *freereq = NULL; int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync; - unsigned short prio; sector_t sector; sector = bio->bi_sector; nr_sectors = bio_sectors(bio); cur_nr_sectors = bio_cur_sectors(bio); - prio = bio_prio(bio); rw = bio_data_dir(bio); sync = bio_sync(bio); @@ -2561,7 +2559,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) req->biotail->bi_next = bio; req->biotail = bio; req->nr_sectors = req->hard_nr_sectors += nr_sectors; - req->ioprio = ioprio_best(req->ioprio, prio); drive_stat_acct(req, nr_sectors, 0); if (!attempt_back_merge(q, req)) elv_merged_request(q, req); @@ -2586,7 +2583,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) req->hard_cur_sectors = cur_nr_sectors; req->sector = req->hard_sector = sector; req->nr_sectors = req->hard_nr_sectors += nr_sectors; - req->ioprio = ioprio_best(req->ioprio, prio); drive_stat_acct(req, nr_sectors, 0); if (!attempt_front_merge(q, req)) elv_merged_request(q, req); @@ -2614,7 +2610,7 @@ static int __make_request(request_queue_t *q, struct bio *bio) freereq = NULL; } else { spin_unlock_irq(q->queue_lock); - if ((freereq = get_request(q, rw, bio, GFP_ATOMIC)) == NULL) { + if ((freereq = get_request(q, rw, GFP_ATOMIC)) == NULL) { /* * READA bit set */ @@ -2622,7 +2618,7 @@ static int __make_request(request_queue_t *q, struct bio *bio) if (bio_rw_ahead(bio)) goto end_io; - freereq = get_request_wait(q, rw, bio); + freereq = get_request_wait(q, rw); } goto again; } @@ -2650,7 +2646,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) req->buffer = bio_data(bio); /* see ->buffer comment above */ req->waiting = NULL; req->bio = req->biotail = bio; - req->ioprio = prio; req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; @@ -2679,7 +2674,7 @@ static inline void blk_partition_remap(struct bio *bio) if (bdev != bdev->bd_contains) { struct hd_struct *p = bdev->bd_part; - switch (bio_data_dir(bio)) { + switch (bio->bi_rw) { case READ: p->read_sectors += bio_sectors(bio); p->reads++; @@ -2698,7 +2693,6 @@ void blk_finish_queue_drain(request_queue_t *q) { struct request_list *rl = &q->rq; struct request *rq; - int requeued = 0; spin_lock_irq(q->queue_lock); clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags); @@ -2707,13 +2701,9 @@ void blk_finish_queue_drain(request_queue_t *q) rq = list_entry_rq(q->drain_list.next); list_del_init(&rq->queuelist); - elv_requeue_request(q, rq); - requeued++; + __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); } - if (requeued) - q->request_fn(q); - spin_unlock_irq(q->queue_lock); wake_up(&rl->wait[0]); @@ -2910,7 +2900,7 @@ void submit_bio(int rw, struct bio *bio) BIO_BUG_ON(!bio->bi_size); BIO_BUG_ON(!bio->bi_io_vec); - bio->bi_rw |= rw; + bio->bi_rw = rw; if (rw & WRITE) mod_page_state(pgpgout, count); else @@ -3267,11 +3257,8 @@ void exit_io_context(void) struct io_context *ioc; local_irq_save(flags); - task_lock(current); ioc = current->io_context; current->io_context = NULL; - ioc->task = NULL; - task_unlock(current); local_irq_restore(flags); if (ioc->aic && ioc->aic->exit) @@ -3306,12 +3293,12 @@ struct io_context *get_io_context(int gfp_flags) ret = kmem_cache_alloc(iocontext_cachep, gfp_flags); if (ret) { atomic_set(&ret->refcount, 1); - ret->task = current; - ret->set_ioprio = NULL; + ret->pid = tsk->pid; ret->last_waited = jiffies; /* doesn't matter... */ ret->nr_batch_requests = 0; /* because this is 0 */ ret->aic = NULL; ret->cic = NULL; + spin_lock_init(&ret->lock); local_irq_save(flags); diff --git a/trunk/drivers/block/sx8.c b/trunk/drivers/block/sx8.c index 9db0a9e3e59c..5ed3a6379452 100644 --- a/trunk/drivers/block/sx8.c +++ b/trunk/drivers/block/sx8.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -1583,9 +1582,9 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out; #if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */ - rc = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + rc = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); if (!rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + rc = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); if (rc) { printk(KERN_ERR DRV_NAME "(%s): consistent DMA mask failure\n", pci_name(pdev)); @@ -1594,7 +1593,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) pci_dac = 1; } else { #endif - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + rc = pci_set_dma_mask(pdev, 0xffffffffULL); if (rc) { printk(KERN_ERR DRV_NAME "(%s): DMA mask failure\n", pci_name(pdev)); diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c index 374f404e81da..556264b43425 100644 --- a/trunk/drivers/input/evdev.c +++ b/trunk/drivers/input/evdev.c @@ -21,7 +21,6 @@ #include #include #include -#include struct evdev { int exist; @@ -146,41 +145,6 @@ static int evdev_open(struct inode * inode, struct file * file) return 0; } -#ifdef CONFIG_COMPAT -struct input_event_compat { - struct compat_timeval time; - __u16 type; - __u16 code; - __s32 value; -}; - -#ifdef CONFIG_X86_64 -# define COMPAT_TEST test_thread_flag(TIF_IA32) -#elif defined(CONFIG_IA64) -# define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) -#elif defined(CONFIG_ARCH_S390) -# define COMPAT_TEST test_thread_flag(TIF_31BIT) -#else -# define COMPAT_TEST test_thread_flag(TIF_32BIT) -#endif - -static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) -{ - struct evdev_list *list = file->private_data; - struct input_event_compat event; - int retval = 0; - - while (retval < count) { - if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat))) - return -EFAULT; - input_event(list->evdev->handle.dev, event.type, event.code, event.value); - retval += sizeof(struct input_event_compat); - } - - return retval; -} -#endif - static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; @@ -189,11 +153,6 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ if (!list->evdev->exist) return -ENODEV; -#ifdef CONFIG_COMPAT - if (COMPAT_TEST) - return evdev_write_compat(file, buffer, count, ppos); -#endif - while (retval < count) { if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) @@ -205,56 +164,11 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ return retval; } -#ifdef CONFIG_COMPAT -static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos) -{ - struct evdev_list *list = file->private_data; - int retval; - - if (count < sizeof(struct input_event_compat)) - return -EINVAL; - - if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) - return -EAGAIN; - - retval = wait_event_interruptible(list->evdev->wait, - list->head != list->tail || (!list->evdev->exist)); - - if (retval) - return retval; - - if (!list->evdev->exist) - return -ENODEV; - - while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) { - struct input_event *event = (struct input_event *) list->buffer + list->tail; - struct input_event_compat event_compat; - event_compat.time.tv_sec = event->time.tv_sec; - event_compat.time.tv_usec = event->time.tv_usec; - event_compat.type = event->type; - event_compat.code = event->code; - event_compat.value = event->value; - - if (copy_to_user(buffer + retval, &event_compat, - sizeof(struct input_event_compat))) return -EFAULT; - list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); - retval += sizeof(struct input_event_compat); - } - - return retval; -} -#endif - static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; int retval; -#ifdef CONFIG_COMPAT - if (COMPAT_TEST) - return evdev_read_compat(file, buffer, count, ppos); -#endif - if (count < sizeof(struct input_event)) return -EINVAL; @@ -272,7 +186,7 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count while (list->head != list->tail && retval + sizeof(struct input_event) <= count) { if (copy_to_user(buffer + retval, list->buffer + list->tail, - sizeof(struct input_event))) return -EFAULT; + sizeof(struct input_event))) return -EFAULT; list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); retval += sizeof(struct input_event); } @@ -289,7 +203,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait) (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); } -static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct evdev_list *list = file->private_data; struct evdev *evdev = list->evdev; @@ -371,267 +285,109 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) default: - if (_IOC_TYPE(cmd) != 'E') + if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) return -EINVAL; - if (_IOC_DIR(cmd) == _IOC_READ) { - - if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { - - long *bits; - int len; - - switch (_IOC_NR(cmd) & EV_MAX) { - case 0: bits = dev->evbit; len = EV_MAX; break; - case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; - case EV_REL: bits = dev->relbit; len = REL_MAX; break; - case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; - case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; - case EV_LED: bits = dev->ledbit; len = LED_MAX; break; - case EV_SND: bits = dev->sndbit; len = SND_MAX; break; - case EV_FF: bits = dev->ffbit; len = FF_MAX; break; - default: return -EINVAL; - } - len = NBITS(len) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, bits, len) ? -EFAULT : len; - } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { - int len; - len = NBITS(KEY_MAX) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->key, len) ? -EFAULT : len; + if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { + + long *bits; + int len; + + switch (_IOC_NR(cmd) & EV_MAX) { + case 0: bits = dev->evbit; len = EV_MAX; break; + case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; + case EV_REL: bits = dev->relbit; len = REL_MAX; break; + case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; + case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; + case EV_LED: bits = dev->ledbit; len = LED_MAX; break; + case EV_SND: bits = dev->sndbit; len = SND_MAX; break; + case EV_FF: bits = dev->ffbit; len = FF_MAX; break; + default: return -EINVAL; } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { - int len; - len = NBITS(LED_MAX) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->led, len) ? -EFAULT : len; - } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { - int len; - len = NBITS(SND_MAX) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->snd, len) ? -EFAULT : len; - } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { - int len; - if (!dev->name) return -ENOENT; - len = strlen(dev->name) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->name, len) ? -EFAULT : len; - } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { - int len; - if (!dev->phys) return -ENOENT; - len = strlen(dev->phys) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->phys, len) ? -EFAULT : len; - } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { - int len; - if (!dev->uniq) return -ENOENT; - len = strlen(dev->uniq) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; - } - - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { - - int t = _IOC_NR(cmd) & ABS_MAX; - - abs.value = dev->abs[t]; - abs.minimum = dev->absmin[t]; - abs.maximum = dev->absmax[t]; - abs.fuzz = dev->absfuzz[t]; - abs.flat = dev->absflat[t]; - - if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) - return -EFAULT; - - return 0; - } - + len = NBITS(len) * sizeof(long); + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user(p, bits, len) ? -EFAULT : len; } - if (_IOC_DIR(cmd) == _IOC_WRITE) { - - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { - - int t = _IOC_NR(cmd) & ABS_MAX; - - if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) - return -EFAULT; - - dev->abs[t] = abs.value; - dev->absmin[t] = abs.minimum; - dev->absmax[t] = abs.maximum; - dev->absfuzz[t] = abs.fuzz; - dev->absflat[t] = abs.flat; - - return 0; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { + int len; + len = NBITS(KEY_MAX) * sizeof(long); + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user(p, dev->key, len) ? -EFAULT : len; } - } - return -EINVAL; -} - -#ifdef CONFIG_COMPAT - -#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) -#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1) -#define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT) -#define BIT_COMPAT(x) (1UL<> OFF_COMPAT(bit)) & 1) - -#ifdef __BIG_ENDIAN -#define bit_to_user(bit, max) \ -do { \ - int i; \ - int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ - for (i = 0; i < len / sizeof(compat_long_t); i++) \ - if (copy_to_user((compat_long_t*) p + i, \ - (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ - sizeof(compat_long_t))) \ - return -EFAULT; \ - return len; \ -} while (0) -#else -#define bit_to_user(bit, max) \ -do { \ - int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ - return copy_to_user(p, (bit), len) ? -EFAULT : len; \ -} while (0) -#endif - -static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct evdev_list *list = file->private_data; - struct evdev *evdev = list->evdev; - struct input_dev *dev = evdev->handle.dev; - struct input_absinfo abs; - void __user *p = compat_ptr(arg); - - if (!evdev->exist) return -ENODEV; - - switch (cmd) { - - case EVIOCGVERSION: - case EVIOCGID: - case EVIOCGKEYCODE: - case EVIOCSKEYCODE: - case EVIOCSFF: - case EVIOCRMFF: - case EVIOCGEFFECTS: - case EVIOCGRAB: - return evdev_ioctl(file, cmd, (unsigned long) p); - - default: - if (_IOC_TYPE(cmd) != 'E') - return -EINVAL; - - if (_IOC_DIR(cmd) == _IOC_READ) { - - if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { - long *bits; - int max; - - switch (_IOC_NR(cmd) & EV_MAX) { - case 0: bits = dev->evbit; max = EV_MAX; break; - case EV_KEY: bits = dev->keybit; max = KEY_MAX; break; - case EV_REL: bits = dev->relbit; max = REL_MAX; break; - case EV_ABS: bits = dev->absbit; max = ABS_MAX; break; - case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break; - case EV_LED: bits = dev->ledbit; max = LED_MAX; break; - case EV_SND: bits = dev->sndbit; max = SND_MAX; break; - case EV_FF: bits = dev->ffbit; max = FF_MAX; break; - default: return -EINVAL; - } - bit_to_user(bits, max); - } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) - bit_to_user(dev->key, KEY_MAX); - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) - bit_to_user(dev->led, LED_MAX); + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { + int len; + len = NBITS(LED_MAX) * sizeof(long); + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user(p, dev->led, len) ? -EFAULT : len; + } - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) - bit_to_user(dev->snd, SND_MAX); + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { + int len; + len = NBITS(SND_MAX) * sizeof(long); + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user(p, dev->snd, len) ? -EFAULT : len; + } - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { - int len; - if (!dev->name) return -ENOENT; - len = strlen(dev->name) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->name, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { + int len; + if (!dev->name) return -ENOENT; + len = strlen(dev->name) + 1; + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user(p, dev->name, len) ? -EFAULT : len; + } - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { - int len; - if (!dev->phys) return -ENOENT; - len = strlen(dev->phys) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->phys, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { + int len; + if (!dev->phys) return -ENOENT; + len = strlen(dev->phys) + 1; + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user(p, dev->phys, len) ? -EFAULT : len; + } - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { - int len; - if (!dev->uniq) return -ENOENT; - len = strlen(dev->uniq) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { + int len; + if (!dev->uniq) return -ENOENT; + len = strlen(dev->uniq) + 1; + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; + } - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { - int t = _IOC_NR(cmd) & ABS_MAX; + int t = _IOC_NR(cmd) & ABS_MAX; - abs.value = dev->abs[t]; - abs.minimum = dev->absmin[t]; - abs.maximum = dev->absmax[t]; - abs.fuzz = dev->absfuzz[t]; - abs.flat = dev->absflat[t]; + abs.value = dev->abs[t]; + abs.minimum = dev->absmin[t]; + abs.maximum = dev->absmax[t]; + abs.fuzz = dev->absfuzz[t]; + abs.flat = dev->absflat[t]; - if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) - return -EFAULT; + if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) + return -EFAULT; - return 0; - } + return 0; } - if (_IOC_DIR(cmd) == _IOC_WRITE) { - - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { - int t = _IOC_NR(cmd) & ABS_MAX; + int t = _IOC_NR(cmd) & ABS_MAX; - if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) - return -EFAULT; + if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) + return -EFAULT; - dev->abs[t] = abs.value; - dev->absmin[t] = abs.minimum; - dev->absmax[t] = abs.maximum; - dev->absfuzz[t] = abs.fuzz; - dev->absflat[t] = abs.flat; + dev->abs[t] = abs.value; + dev->absmin[t] = abs.minimum; + dev->absmax[t] = abs.maximum; + dev->absfuzz[t] = abs.fuzz; + dev->absflat[t] = abs.flat; - return 0; - } + return 0; } } return -EINVAL; } -#endif static struct file_operations evdev_fops = { .owner = THIS_MODULE, @@ -640,10 +396,7 @@ static struct file_operations evdev_fops = { .poll = evdev_poll, .open = evdev_open, .release = evdev_release, - .unlocked_ioctl = evdev_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = evdev_ioctl_compat, -#endif + .ioctl = evdev_ioctl, .fasync = evdev_fasync, .flush = evdev_flush }; diff --git a/trunk/drivers/input/gameport/Kconfig b/trunk/drivers/input/gameport/Kconfig index 7524bd7d8b8f..1d93f5092904 100644 --- a/trunk/drivers/input/gameport/Kconfig +++ b/trunk/drivers/input/gameport/Kconfig @@ -49,8 +49,22 @@ config GAMEPORT_EMU10K1 To compile this driver as a module, choose M here: the module will be called emu10k1-gp. +config GAMEPORT_VORTEX + tristate "Aureal Vortex, Vortex 2 gameport support" + depends on PCI + help + Say Y here if you have an Aureal Vortex 1 or 2 card and want + to use its gameport. + + To compile this driver as a module, choose M here: the + module will be called vortex. + config GAMEPORT_FM801 tristate "ForteMedia FM801 gameport support" depends on PCI +config GAMEPORT_CS461X + tristate "Crystal SoundFusion gameport support" + depends on PCI + endif diff --git a/trunk/drivers/input/gameport/Makefile b/trunk/drivers/input/gameport/Makefile index b6f6097bd8c4..5367b4267adf 100644 --- a/trunk/drivers/input/gameport/Makefile +++ b/trunk/drivers/input/gameport/Makefile @@ -5,7 +5,9 @@ # Each configuration option enables a list of files. obj-$(CONFIG_GAMEPORT) += gameport.o +obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o obj-$(CONFIG_GAMEPORT_L4) += lightning.o obj-$(CONFIG_GAMEPORT_NS558) += ns558.o +obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o diff --git a/trunk/drivers/input/gameport/cs461x.c b/trunk/drivers/input/gameport/cs461x.c new file mode 100644 index 000000000000..d4013ff98623 --- /dev/null +++ b/trunk/drivers/input/gameport/cs461x.c @@ -0,0 +1,322 @@ +/* + The all defines and part of code (such as cs461x_*) are + contributed from ALSA 0.5.8 sources. + See http://www.alsa-project.org/ for sources + + Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610 +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Victor Krapivin"); +MODULE_LICENSE("GPL"); + +/* + These options are experimental + +#define CS461X_FULL_MAP +*/ + + +#ifndef PCI_VENDOR_ID_CIRRUS +#define PCI_VENDOR_ID_CIRRUS 0x1013 +#endif +#ifndef PCI_DEVICE_ID_CIRRUS_4610 +#define PCI_DEVICE_ID_CIRRUS_4610 0x6001 +#endif +#ifndef PCI_DEVICE_ID_CIRRUS_4612 +#define PCI_DEVICE_ID_CIRRUS_4612 0x6003 +#endif +#ifndef PCI_DEVICE_ID_CIRRUS_4615 +#define PCI_DEVICE_ID_CIRRUS_4615 0x6004 +#endif + +/* Registers */ + +#define BA0_JSPT 0x00000480 +#define BA0_JSCTL 0x00000484 +#define BA0_JSC1 0x00000488 +#define BA0_JSC2 0x0000048C +#define BA0_JSIO 0x000004A0 + +/* Bits for JSPT */ + +#define JSPT_CAX 0x00000001 +#define JSPT_CAY 0x00000002 +#define JSPT_CBX 0x00000004 +#define JSPT_CBY 0x00000008 +#define JSPT_BA1 0x00000010 +#define JSPT_BA2 0x00000020 +#define JSPT_BB1 0x00000040 +#define JSPT_BB2 0x00000080 + +/* Bits for JSCTL */ + +#define JSCTL_SP_MASK 0x00000003 +#define JSCTL_SP_SLOW 0x00000000 +#define JSCTL_SP_MEDIUM_SLOW 0x00000001 +#define JSCTL_SP_MEDIUM_FAST 0x00000002 +#define JSCTL_SP_FAST 0x00000003 +#define JSCTL_ARE 0x00000004 + +/* Data register pairs masks */ + +#define JSC1_Y1V_MASK 0x0000FFFF +#define JSC1_X1V_MASK 0xFFFF0000 +#define JSC1_Y1V_SHIFT 0 +#define JSC1_X1V_SHIFT 16 +#define JSC2_Y2V_MASK 0x0000FFFF +#define JSC2_X2V_MASK 0xFFFF0000 +#define JSC2_Y2V_SHIFT 0 +#define JSC2_X2V_SHIFT 16 + +/* JS GPIO */ + +#define JSIO_DAX 0x00000001 +#define JSIO_DAY 0x00000002 +#define JSIO_DBX 0x00000004 +#define JSIO_DBY 0x00000008 +#define JSIO_AXOE 0x00000010 +#define JSIO_AYOE 0x00000020 +#define JSIO_BXOE 0x00000040 +#define JSIO_BYOE 0x00000080 + +/* + The card initialization code is obfuscated; the module cs461x + need to be loaded after ALSA modules initialized and something + played on the CS 4610 chip (see sources for details of CS4610 + initialization code from ALSA) +*/ + +/* Card specific definitions */ + +#define CS461X_BA0_SIZE 0x2000 +#define CS461X_BA1_DATA0_SIZE 0x3000 +#define CS461X_BA1_DATA1_SIZE 0x3800 +#define CS461X_BA1_PRG_SIZE 0x7000 +#define CS461X_BA1_REG_SIZE 0x0100 + +#define BA1_SP_DMEM0 0x00000000 +#define BA1_SP_DMEM1 0x00010000 +#define BA1_SP_PMEM 0x00020000 +#define BA1_SP_REG 0x00030000 + +#define BA1_DWORD_SIZE (13 * 1024 + 512) +#define BA1_MEMORY_COUNT 3 + +/* + Only one CS461x card is still suppoted; the code requires + redesign to avoid this limitatuion. +*/ + +static unsigned long ba0_addr; +static unsigned int __iomem *ba0; + +#ifdef CS461X_FULL_MAP +static unsigned long ba1_addr; +static union ba1_t { + struct { + unsigned int __iomem *data0; + unsigned int __iomem *data1; + unsigned int __iomem *pmem; + unsigned int __iomem *reg; + } name; + unsigned int __iomem *idx[4]; +} ba1; + +static void cs461x_poke(unsigned long reg, unsigned int val) +{ + writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); +} + +static unsigned int cs461x_peek(unsigned long reg) +{ + return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); +} + +#endif + +static void cs461x_pokeBA0(unsigned long reg, unsigned int val) +{ + writel(val, &ba0[reg >> 2]); +} + +static unsigned int cs461x_peekBA0(unsigned long reg) +{ + return readl(&ba0[reg >> 2]); +} + +static int cs461x_free(struct pci_dev *pdev) +{ + struct gameport *port = pci_get_drvdata(pdev); + + if (port) + gameport_unregister_port(port); + + if (ba0) iounmap(ba0); +#ifdef CS461X_FULL_MAP + if (ba1.name.data0) iounmap(ba1.name.data0); + if (ba1.name.data1) iounmap(ba1.name.data1); + if (ba1.name.pmem) iounmap(ba1.name.pmem); + if (ba1.name.reg) iounmap(ba1.name.reg); +#endif + return 0; +} + +static void cs461x_gameport_trigger(struct gameport *gameport) +{ + cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); +} + +static unsigned char cs461x_gameport_read(struct gameport *gameport) +{ + return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io); +} + +static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) +{ + unsigned js1, js2, jst; + + js1 = cs461x_peekBA0(BA0_JSC1); + js2 = cs461x_peekBA0(BA0_JSC2); + jst = cs461x_peekBA0(BA0_JSPT); + + *buttons = (~jst >> 4) & 0x0F; + + axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; + axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; + axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; + axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; + + for(jst=0;jst<4;++jst) + if(axes[jst]==0xFFFF) axes[jst] = -1; + return 0; +} + +static int cs461x_gameport_open(struct gameport *gameport, int mode) +{ + switch (mode) { + case GAMEPORT_MODE_COOKED: + case GAMEPORT_MODE_RAW: + return 0; + default: + return -1; + } + return 0; +} + +static struct pci_device_id cs461x_pci_tbl[] = { + { PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */ + { PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */ + { PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */ + { 0, } +}; +MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl); + +static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int rc; + struct gameport* port; + + rc = pci_enable_device(pdev); + if (rc) { + printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n", + pdev->bus->number, pdev->devfn, rc); + return rc; + } + + ba0_addr = pci_resource_start(pdev, 0); +#ifdef CS461X_FULL_MAP + ba1_addr = pci_resource_start(pdev, 1); +#endif + if (ba0_addr == 0 || ba0_addr == ~0 +#ifdef CS461X_FULL_MAP + || ba1_addr == 0 || ba1_addr == ~0 +#endif + ) { + printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr); +#ifdef CS461X_FULL_MAP + printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr); +#endif + cs461x_free(pdev); + return -ENOMEM; + } + + ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE); +#ifdef CS461X_FULL_MAP + ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE); + ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE); + ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); + ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); + + if (ba0 == NULL || ba1.name.data0 == NULL || + ba1.name.data1 == NULL || ba1.name.pmem == NULL || + ba1.name.reg == NULL) { + cs461x_free(pdev); + return -ENOMEM; + } +#else + if (ba0 == NULL) { + cs461x_free(pdev); + return -ENOMEM; + } +#endif + + if (!(port = gameport_allocate_port())) { + printk(KERN_ERR "cs461x: Memory allocation failed\n"); + cs461x_free(pdev); + return -ENOMEM; + } + + pci_set_drvdata(pdev, port); + + port->open = cs461x_gameport_open; + port->trigger = cs461x_gameport_trigger; + port->read = cs461x_gameport_read; + port->cooked_read = cs461x_gameport_cooked_read; + + gameport_set_name(port, "CS416x"); + gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); + port->dev.parent = &pdev->dev; + + cs461x_pokeBA0(BA0_JSIO, 0xFF); // ? + cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); + + gameport_register_port(port); + + return 0; +} + +static void __devexit cs461x_pci_remove(struct pci_dev *pdev) +{ + cs461x_free(pdev); +} + +static struct pci_driver cs461x_pci_driver = { + .name = "CS461x_gameport", + .id_table = cs461x_pci_tbl, + .probe = cs461x_pci_probe, + .remove = __devexit_p(cs461x_pci_remove), +}; + +static int __init cs461x_init(void) +{ + return pci_register_driver(&cs461x_pci_driver); +} + +static void __exit cs461x_exit(void) +{ + pci_unregister_driver(&cs461x_pci_driver); +} + +module_init(cs461x_init); +module_exit(cs461x_exit); + diff --git a/trunk/drivers/input/gameport/ns558.c b/trunk/drivers/input/gameport/ns558.c index 1ab5f2dc8a2a..7c5c6318eeb9 100644 --- a/trunk/drivers/input/gameport/ns558.c +++ b/trunk/drivers/input/gameport/ns558.c @@ -258,18 +258,18 @@ static int __init ns558_init(void) { int i = 0; - if (pnp_register_driver(&ns558_pnp_driver) >= 0) - pnp_registered = 1; - /* - * Probe ISA ports after PnP, so that PnP ports that are already - * enabled get detected as PnP. This may be suboptimal in multi-device - * configurations, but saves hassle with simple setups. + * Probe ISA ports first so that PnP gets to choose free port addresses + * not occupied by the ISA ports. */ while (ns558_isa_portlist[i]) ns558_isa_probe(ns558_isa_portlist[i++]); + if (pnp_register_driver(&ns558_pnp_driver) >= 0) + pnp_registered = 1; + + return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; } diff --git a/trunk/drivers/input/gameport/vortex.c b/trunk/drivers/input/gameport/vortex.c new file mode 100644 index 000000000000..36b0309c8bf6 --- /dev/null +++ b/trunk/drivers/input/gameport/vortex.c @@ -0,0 +1,186 @@ +/* + * $Id: vortex.c,v 1.5 2002/07/01 15:39:30 vojtech Exp $ + * + * Copyright (c) 2000-2001 Vojtech Pavlik + * + * Based on the work of: + * Raymond Ingles + */ + +/* + * Trident 4DWave and Aureal Vortex gameport driver for Linux + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver"); +MODULE_LICENSE("GPL"); + +#define VORTEX_GCR 0x0c /* Gameport control register */ +#define VORTEX_LEG 0x08 /* Legacy port location */ +#define VORTEX_AXD 0x10 /* Axes start */ +#define VORTEX_DATA_WAIT 20 /* 20 ms */ + +struct vortex { + struct gameport *gameport; + struct pci_dev *dev; + unsigned char __iomem *base; + unsigned char __iomem *io; +}; + +static unsigned char vortex_read(struct gameport *gameport) +{ + struct vortex *vortex = gameport->port_data; + return readb(vortex->io + VORTEX_LEG); +} + +static void vortex_trigger(struct gameport *gameport) +{ + struct vortex *vortex = gameport->port_data; + writeb(0xff, vortex->io + VORTEX_LEG); +} + +static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons) +{ + struct vortex *vortex = gameport->port_data; + int i; + + *buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf; + + for (i = 0; i < 4; i++) { + axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32)); + if (axes[i] == 0x1fff) axes[i] = -1; + } + + return 0; +} + +static int vortex_open(struct gameport *gameport, int mode) +{ + struct vortex *vortex = gameport->port_data; + + switch (mode) { + case GAMEPORT_MODE_COOKED: + writeb(0x40, vortex->io + VORTEX_GCR); + msleep(VORTEX_DATA_WAIT); + return 0; + case GAMEPORT_MODE_RAW: + writeb(0x00, vortex->io + VORTEX_GCR); + return 0; + default: + return -1; + } + + return 0; +} + +static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct vortex *vortex; + struct gameport *port; + int i; + + vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL); + port = gameport_allocate_port(); + if (!vortex || !port) { + printk(KERN_ERR "vortex: Memory allocation failed.\n"); + kfree(vortex); + gameport_free_port(port); + return -ENOMEM; + } + + for (i = 0; i < 6; i++) + if (~pci_resource_flags(dev, i) & IORESOURCE_IO) + break; + + pci_enable_device(dev); + + vortex->dev = dev; + vortex->gameport = port; + vortex->base = ioremap(pci_resource_start(vortex->dev, i), + pci_resource_len(vortex->dev, i)); + vortex->io = vortex->base + id->driver_data; + + pci_set_drvdata(dev, vortex); + + port->port_data = vortex; + port->fuzz = 64; + + gameport_set_name(port, "AU88x0"); + gameport_set_phys(port, "pci%s/gameport0", pci_name(dev)); + port->dev.parent = &dev->dev; + port->read = vortex_read; + port->trigger = vortex_trigger; + port->cooked_read = vortex_cooked_read; + port->open = vortex_open; + + gameport_register_port(port); + + return 0; +} + +static void __devexit vortex_remove(struct pci_dev *dev) +{ + struct vortex *vortex = pci_get_drvdata(dev); + + gameport_unregister_port(vortex->gameport); + iounmap(vortex->base); + kfree(vortex); +} + +static struct pci_device_id vortex_id_table[] = { + { 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 }, + { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 }, + { 0 } +}; + +static struct pci_driver vortex_driver = { + .name = "vortex_gameport", + .id_table = vortex_id_table, + .probe = vortex_probe, + .remove = __devexit_p(vortex_remove), +}; + +static int __init vortex_init(void) +{ + return pci_register_driver(&vortex_driver); +} + +static void __exit vortex_exit(void) +{ + pci_unregister_driver(&vortex_driver); +} + +module_init(vortex_init); +module_exit(vortex_exit); diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c index 7c4b4d37b3e6..83c77c990dda 100644 --- a/trunk/drivers/input/input.c +++ b/trunk/drivers/input/input.c @@ -219,24 +219,10 @@ void input_release_device(struct input_handle *handle) int input_open_device(struct input_handle *handle) { - struct input_dev *dev = handle->dev; - int err; - - err = down_interruptible(&dev->sem); - if (err) - return err; - handle->open++; - - if (!dev->users++ && dev->open) - err = dev->open(dev); - - if (err) - handle->open--; - - up(&dev->sem); - - return err; + if (handle->dev->open) + return handle->dev->open(handle->dev); + return 0; } int input_flush_device(struct input_handle* handle, struct file* file) @@ -249,17 +235,10 @@ int input_flush_device(struct input_handle* handle, struct file* file) void input_close_device(struct input_handle *handle) { - struct input_dev *dev = handle->dev; - input_release_device(handle); - - down(&dev->sem); - - if (!--dev->users && dev->close) - dev->close(dev); + if (handle->dev->close) + handle->dev->close(handle->dev); handle->open--; - - up(&dev->sem); } static void input_link_handle(struct input_handle *handle) @@ -436,8 +415,6 @@ void input_register_device(struct input_dev *dev) set_bit(EV_SYN, dev->evbit); - init_MUTEX(&dev->sem); - /* * If delay and period are pre-set by the driver, then autorepeating * is handled by the driver itself and we don't do it in input.c. @@ -697,8 +674,6 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in return (count > cnt) ? cnt : count; } -static struct file_operations input_fileops; - static int __init input_proc_init(void) { struct proc_dir_entry *entry; @@ -713,8 +688,6 @@ static int __init input_proc_init(void) return -ENOMEM; } entry->owner = THIS_MODULE; - input_fileops = *entry->proc_fops; - entry->proc_fops = &input_fileops; entry->proc_fops->poll = input_devices_poll; entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); if (entry == NULL) { diff --git a/trunk/drivers/input/joydev.c b/trunk/drivers/input/joydev.c index ff8e1bbd0e13..39775fc380c7 100644 --- a/trunk/drivers/input/joydev.c +++ b/trunk/drivers/input/joydev.c @@ -285,33 +285,48 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); } -static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) +static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + struct joydev_list *list = file->private_data; + struct joydev *joydev = list->joydev; struct input_dev *dev = joydev->handle.dev; + void __user *argp = (void __user *)arg; int i, j; + if (!joydev->exist) return -ENODEV; + switch (cmd) { case JS_SET_CAL: return copy_from_user(&joydev->glue.JS_CORR, argp, - sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; + sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; case JS_GET_CAL: return copy_to_user(argp, &joydev->glue.JS_CORR, - sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; + sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; case JS_SET_TIMEOUT: - return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); + return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); case JS_GET_TIMEOUT: - return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); + return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); + case JS_SET_TIMELIMIT: + return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); + case JS_GET_TIMELIMIT: + return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); + case JS_SET_ALL: + return copy_from_user(&joydev->glue, argp, + sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; + case JS_GET_ALL: + return copy_to_user(argp, &joydev->glue, + sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; case JSIOCGVERSION: - return put_user(JS_VERSION, (__u32 __user *) argp); + return put_user(JS_VERSION, (__u32 __user *) arg); case JSIOCGAXES: - return put_user(joydev->nabs, (__u8 __user *) argp); + return put_user(joydev->nabs, (__u8 __user *) arg); case JSIOCGBUTTONS: - return put_user(joydev->nkey, (__u8 __user *) argp); + return put_user(joydev->nkey, (__u8 __user *) arg); case JSIOCSCORR: if (copy_from_user(joydev->corr, argp, - sizeof(joydev->corr[0]) * joydev->nabs)) + sizeof(struct js_corr) * joydev->nabs)) return -EFAULT; for (i = 0; i < joydev->nabs; i++) { j = joydev->abspam[i]; @@ -320,7 +335,7 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __u return 0; case JSIOCGCORR: return copy_to_user(argp, joydev->corr, - sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; + sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0; case JSIOCSAXMAP: if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) return -EFAULT; @@ -356,84 +371,6 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __u return -EINVAL; } -#ifdef CONFIG_COMPAT -static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct joydev_list *list = file->private_data; - struct joydev *joydev = list->joydev; - void __user *argp = (void __user *)arg; - s32 tmp32; - struct JS_DATA_SAVE_TYPE_32 ds32; - int err; - - if (!joydev->exist) return -ENODEV; - switch(cmd) { - case JS_SET_TIMELIMIT: - err = get_user(tmp32, (s32 __user *) arg); - if (err == 0) - joydev->glue.JS_TIMELIMIT = tmp32; - break; - case JS_GET_TIMELIMIT: - tmp32 = joydev->glue.JS_TIMELIMIT; - err = put_user(tmp32, (s32 __user *) arg); - break; - - case JS_SET_ALL: - err = copy_from_user(&ds32, argp, - sizeof(ds32)) ? -EFAULT : 0; - if (err == 0) { - joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; - joydev->glue.BUSY = ds32.BUSY; - joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; - joydev->glue.JS_TIMELIMIT = ds32.JS_TIMELIMIT; - joydev->glue.JS_SAVE = ds32.JS_SAVE; - joydev->glue.JS_CORR = ds32.JS_CORR; - } - break; - - case JS_GET_ALL: - ds32.JS_TIMEOUT = joydev->glue.JS_TIMEOUT; - ds32.BUSY = joydev->glue.BUSY; - ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME; - ds32.JS_TIMELIMIT = joydev->glue.JS_TIMELIMIT; - ds32.JS_SAVE = joydev->glue.JS_SAVE; - ds32.JS_CORR = joydev->glue.JS_CORR; - - err = copy_to_user(argp, &ds32, - sizeof(ds32)) ? -EFAULT : 0; - break; - - default: - err = joydev_ioctl_common(joydev, cmd, argp); - } - return err; -} -#endif /* CONFIG_COMPAT */ - -static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct joydev_list *list = file->private_data; - struct joydev *joydev = list->joydev; - void __user *argp = (void __user *)arg; - - if (!joydev->exist) return -ENODEV; - - switch(cmd) { - case JS_SET_TIMELIMIT: - return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); - case JS_GET_TIMELIMIT: - return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); - case JS_SET_ALL: - return copy_from_user(&joydev->glue, argp, - sizeof(joydev->glue)) ? -EFAULT : 0; - case JS_GET_ALL: - return copy_to_user(argp, &joydev->glue, - sizeof(joydev->glue)) ? -EFAULT : 0; - default: - return joydev_ioctl_common(joydev, cmd, argp); - } -} - static struct file_operations joydev_fops = { .owner = THIS_MODULE, .read = joydev_read, @@ -442,9 +379,6 @@ static struct file_operations joydev_fops = { .open = joydev_open, .release = joydev_release, .ioctl = joydev_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = joydev_compat_ioctl, -#endif .fasync = joydev_fasync, }; diff --git a/trunk/drivers/input/joystick/a3d.c b/trunk/drivers/input/joystick/a3d.c index bf34f75b9467..ad39fe4bf35f 100644 --- a/trunk/drivers/input/joystick/a3d.c +++ b/trunk/drivers/input/joystick/a3d.c @@ -185,7 +185,7 @@ static void a3d_poll(struct gameport *gameport) a3d->reads++; if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length || data[0] != a3d->mode || a3d_csum(data, a3d->length)) - a3d->bads++; + a3d->bads++; else a3d_read(a3d, data); } diff --git a/trunk/drivers/input/joystick/adi.c b/trunk/drivers/input/joystick/adi.c index 265962956c63..83f6dafc1716 100644 --- a/trunk/drivers/input/joystick/adi.c +++ b/trunk/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 }; static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; 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 }; -static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; +static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; @@ -183,7 +183,7 @@ static void adi_move_bits(struct adi_port *port, int length) int i; struct adi *adi = port->adi; - adi[0].idx = adi[1].idx = 0; + adi[0].idx = adi[1].idx = 0; if (adi[0].ret <= 0 || adi[1].ret <= 0) return; if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return; diff --git a/trunk/drivers/input/joystick/amijoy.c b/trunk/drivers/input/joystick/amijoy.c index 033456bb9fe0..cf36ca9b92f3 100644 --- a/trunk/drivers/input/joystick/amijoy.c +++ b/trunk/drivers/input/joystick/amijoy.c @@ -51,8 +51,7 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of , (default is __obsolete_setup("amijoy="); -static int amijoy_used; -static DECLARE_MUTEX(amijoy_sem); +static int amijoy_used[2] = { 0, 0 }; static struct input_dev amijoy_dev[2]; static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; @@ -85,30 +84,26 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp) static int amijoy_open(struct input_dev *dev) { - int err; + int *used = dev->private; - err = down_interruptible(&amijoy_sem); - if (err) - return err; + if ((*used)++) + return 0; - if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { + if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { + (*used)--; printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); - err = -EBUSY; - goto out; + return -EBUSY; } - amijoy_used++; -out: - up(&amijoy_sem); - return err; + return 0; } static void amijoy_close(struct input_dev *dev) { - down(&amijoysem); - if (!--amijoy_used) + int *used = dev->private; + + if (!--(*used)) free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); - up(&amijoy_sem); } static int __init amijoy_init(void) @@ -143,6 +138,8 @@ static int __init amijoy_init(void) amijoy_dev[i].id.product = 0x0003; amijoy_dev[i].id.version = 0x0100; + amijoy_dev[i].private = amijoy_used + i; + input_register_device(amijoy_dev + i); printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); } diff --git a/trunk/drivers/input/joystick/db9.c b/trunk/drivers/input/joystick/db9.c index fbd3eed07f90..cfdd3acf06a1 100644 --- a/trunk/drivers/input/joystick/db9.c +++ b/trunk/drivers/input/joystick/db9.c @@ -87,7 +87,7 @@ __obsolete_setup("db9_3="); #define DB9_NORMAL 0x0a #define DB9_NOSELECT 0x08 -#define DB9_MAX_DEVICES 2 +#define DB9_MAX_DEVICES 2 #define DB9_GENESIS6_DELAY 14 #define DB9_REFRESH_TIME HZ/100 @@ -98,7 +98,6 @@ struct db9 { struct pardevice *pd; int mode; int used; - struct semaphore sem; char phys[2][32]; }; @@ -504,11 +503,6 @@ static int db9_open(struct input_dev *dev) { struct db9 *db9 = dev->private; struct parport *port = db9->pd->port; - int err; - - err = down_interruptible(&db9->sem); - if (err) - return err; if (!db9->used++) { parport_claim(db9->pd); @@ -520,7 +514,6 @@ static int db9_open(struct input_dev *dev) mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); } - up(&db9->sem); return 0; } @@ -529,14 +522,12 @@ static void db9_close(struct input_dev *dev) struct db9 *db9 = dev->private; struct parport *port = db9->pd->port; - down(&db9->sem); if (!--db9->used) { - del_timer_sync(&db9->timer); + del_timer(&db9->timer); parport_write_control(port, 0x00); parport_data_forward(port); parport_release(db9->pd); } - up(&db9->sem); } static struct db9 __init *db9_probe(int *config, int nargs) @@ -572,12 +563,12 @@ static struct db9 __init *db9_probe(int *config, int nargs) } } - if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) { + if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) { parport_put_port(pp); return NULL; } + memset(db9, 0, sizeof(struct db9)); - init_MUTEX(&db9->sem); db9->mode = config[1]; init_timer(&db9->timer); db9->timer.data = (long) db9; diff --git a/trunk/drivers/input/joystick/gamecon.c b/trunk/drivers/input/joystick/gamecon.c index 95bbdd302aad..8732f52bdd08 100644 --- a/trunk/drivers/input/joystick/gamecon.c +++ b/trunk/drivers/input/joystick/gamecon.c @@ -1,12 +1,12 @@ /* * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux * - * Copyright (c) 1999-2004 Vojtech Pavlik - * Copyright (c) 2004 Peter Nelson + * Copyright (c) 1999-2004 Vojtech Pavlik + * Copyright (c) 2004 Peter Nelson * * Based on the work of: - * Andree Borrmann John Dahlstrom - * David Kuder Nathan Hand + * Andree Borrmann John Dahlstrom + * David Kuder Nathan Hand */ /* @@ -81,7 +81,6 @@ struct gc { struct timer_list timer; unsigned char pads[GC_MAX + 1]; int used; - struct semaphore sem; char phys[5][32]; }; @@ -434,7 +433,7 @@ static void gc_timer(unsigned long private) gc_psx_read_packet(gc, data_psx, data); for (i = 0; i < 5; i++) { - switch (data[i]) { + switch (data[i]) { case GC_PSX_RUMBLE: @@ -504,33 +503,22 @@ static void gc_timer(unsigned long private) static int gc_open(struct input_dev *dev) { struct gc *gc = dev->private; - int err; - - err = down_interruptible(&gc->sem); - if (err) - return err; - if (!gc->used++) { parport_claim(gc->pd); parport_write_control(gc->pd->port, 0x04); mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); } - - up(&gc->sem); return 0; } static void gc_close(struct input_dev *dev) { struct gc *gc = dev->private; - - down(&gc->sem); if (!--gc->used) { - del_timer_sync(&gc->timer); + del_timer(&gc->timer); parport_write_control(gc->pd->port, 0x00); parport_release(gc->pd); } - up(&gc->sem); } static struct gc __init *gc_probe(int *config, int nargs) @@ -554,12 +542,11 @@ static struct gc __init *gc_probe(int *config, int nargs) return NULL; } - if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) { + if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) { parport_put_port(pp); return NULL; } - - init_MUTEX(&gc->sem); + memset(gc, 0, sizeof(struct gc)); gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); diff --git a/trunk/drivers/input/joystick/gf2k.c b/trunk/drivers/input/joystick/gf2k.c index 7d969420066c..ad13f09a4e71 100644 --- a/trunk/drivers/input/joystick/gf2k.c +++ b/trunk/drivers/input/joystick/gf2k.c @@ -329,7 +329,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) for (i = 0; i < gf2k_axes[gf2k->id]; i++) { gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : - gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; + gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; gf2k->dev.absmin[gf2k_abs[i]] = 32; gf2k->dev.absfuzz[gf2k_abs[i]] = 8; gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; diff --git a/trunk/drivers/input/joystick/grip_mp.c b/trunk/drivers/input/joystick/grip_mp.c index 0da7bd133ccf..42e5005d621f 100644 --- a/trunk/drivers/input/joystick/grip_mp.c +++ b/trunk/drivers/input/joystick/grip_mp.c @@ -171,7 +171,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa *packet = 0; raw_data = gameport_read(gameport); if (raw_data & 1) - return IO_RETRY; + return IO_RETRY; for (i = 0; i < 64; i++) { raw_data = gameport_read(gameport); diff --git a/trunk/drivers/input/joystick/iforce/iforce-main.c b/trunk/drivers/input/joystick/iforce/iforce-main.c index e31b7b93fde2..028f3513629a 100644 --- a/trunk/drivers/input/joystick/iforce/iforce-main.c +++ b/trunk/drivers/input/joystick/iforce/iforce-main.c @@ -78,7 +78,6 @@ static struct iforce_device iforce_device[] = { { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? - { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } }; diff --git a/trunk/drivers/input/joystick/iforce/iforce-usb.c b/trunk/drivers/input/joystick/iforce/iforce-usb.c index 6369a24684fe..617c0b0e5a39 100644 --- a/trunk/drivers/input/joystick/iforce/iforce-usb.c +++ b/trunk/drivers/input/joystick/iforce/iforce-usb.c @@ -229,7 +229,6 @@ static struct usb_device_id iforce_usb_ids [] = { { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ - { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ { } /* Terminating entry */ }; diff --git a/trunk/drivers/input/joystick/spaceball.c b/trunk/drivers/input/joystick/spaceball.c index a436f2220856..ec0a2a64d49c 100644 --- a/trunk/drivers/input/joystick/spaceball.c +++ b/trunk/drivers/input/joystick/spaceball.c @@ -4,8 +4,8 @@ * Copyright (c) 1999-2001 Vojtech Pavlik * * Based on the work of: - * David Thompson - * Joseph Krahn + * David Thompson + * Joseph Krahn */ /* diff --git a/trunk/drivers/input/joystick/spaceorb.c b/trunk/drivers/input/joystick/spaceorb.c index 01fd2e4791ae..874367bfab08 100644 --- a/trunk/drivers/input/joystick/spaceorb.c +++ b/trunk/drivers/input/joystick/spaceorb.c @@ -4,7 +4,7 @@ * Copyright (c) 1999-2001 Vojtech Pavlik * * Based on the work of: - * David Thompson + * David Thompson */ /* diff --git a/trunk/drivers/input/joystick/tmdc.c b/trunk/drivers/input/joystick/tmdc.c index 9eb9954cac6e..aaee52ceb920 100644 --- a/trunk/drivers/input/joystick/tmdc.c +++ b/trunk/drivers/input/joystick/tmdc.c @@ -79,7 +79,7 @@ static short tmdc_btn_pad[TMDC_BTN] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR }; static short tmdc_btn_joy[TMDC_BTN] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE, - BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; + BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; static short tmdc_btn_fm[TMDC_BTN] = { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 }; static short tmdc_btn_at[TMDC_BTN] = diff --git a/trunk/drivers/input/joystick/turbografx.c b/trunk/drivers/input/joystick/turbografx.c index 28100d461cb7..dd88b9cb49fa 100644 --- a/trunk/drivers/input/joystick/turbografx.c +++ b/trunk/drivers/input/joystick/turbografx.c @@ -84,7 +84,6 @@ static struct tgfx { char phys[7][32]; int sticks; int used; - struct semaphore sem; } *tgfx_base[3]; /* @@ -100,7 +99,7 @@ static void tgfx_timer(unsigned long private) for (i = 0; i < 7; i++) if (tgfx->sticks & (1 << i)) { - dev = tgfx->dev + i; + dev = tgfx->dev + i; parport_write_data(tgfx->pd->port, ~(1 << i)); data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; @@ -123,34 +122,23 @@ static void tgfx_timer(unsigned long private) static int tgfx_open(struct input_dev *dev) { - struct tgfx *tgfx = dev->private; - int err; - - err = down_interruptible(&tgfx->sem); - if (err) - return err; - - if (!tgfx->used++) { + struct tgfx *tgfx = dev->private; + if (!tgfx->used++) { parport_claim(tgfx->pd); parport_write_control(tgfx->pd->port, 0x04); - mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); + mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); } - - up(&tgfx->sem); - return 0; + return 0; } static void tgfx_close(struct input_dev *dev) { - struct tgfx *tgfx = dev->private; - - down(&tgfx->sem); - if (!--tgfx->used) { - del_timer_sync(&tgfx->timer); + struct tgfx *tgfx = dev->private; + if (!--tgfx->used) { + del_timer(&tgfx->timer); parport_write_control(tgfx->pd->port, 0x00); - parport_release(tgfx->pd); + parport_release(tgfx->pd); } - up(&tgfx->sem); } /* @@ -178,12 +166,11 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs) return NULL; } - if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) { + if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) { parport_put_port(pp); return NULL; } - - init_MUTEX(&tgfx->sem); + memset(tgfx, 0, sizeof(struct tgfx)); tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); diff --git a/trunk/drivers/input/keyboard/atkbd.c b/trunk/drivers/input/keyboard/atkbd.c index 4d4985b59abf..82fad9a23ace 100644 --- a/trunk/drivers/input/keyboard/atkbd.c +++ b/trunk/drivers/input/keyboard/atkbd.c @@ -227,7 +227,7 @@ static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *a { \ return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ } \ -static struct device_attribute atkbd_attr_##_name = \ +static struct device_attribute atkbd_attr_##_name = \ __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); ATKBD_DEFINE_ATTR(extra); @@ -388,7 +388,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, value = atkbd->release ? 0 : (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); - switch (value) { /* Workaround Toshiba laptop multiple keypress */ + switch (value) { /* Workaround Toshiba laptop multiple keypress */ case 0: atkbd->last = 0; break; @@ -894,7 +894,7 @@ static int atkbd_reconnect(struct serio *serio) if (atkbd->write) { param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) - | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); + | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); if (atkbd_probe(atkbd)) return -1; diff --git a/trunk/drivers/input/keyboard/corgikbd.c b/trunk/drivers/input/keyboard/corgikbd.c index a8551711e8d6..0f1220a0ceb5 100644 --- a/trunk/drivers/input/keyboard/corgikbd.c +++ b/trunk/drivers/input/keyboard/corgikbd.c @@ -39,7 +39,6 @@ #define CORGI_KEY_CALENDER KEY_F1 #define CORGI_KEY_ADDRESS KEY_F2 #define CORGI_KEY_FN KEY_F3 -#define CORGI_KEY_CANCEL KEY_F4 #define CORGI_KEY_OFF KEY_SUSPEND #define CORGI_KEY_EXOK KEY_F5 #define CORGI_KEY_EXCANCEL KEY_F6 @@ -47,7 +46,6 @@ #define CORGI_KEY_EXJOGUP KEY_F8 #define CORGI_KEY_JAP1 KEY_LEFTCTRL #define CORGI_KEY_JAP2 KEY_LEFTALT -#define CORGI_KEY_MAIL KEY_F10 #define CORGI_KEY_OK KEY_F11 #define CORGI_KEY_MENU KEY_F12 #define CORGI_HINGE_0 KEY_KP0 @@ -61,8 +59,8 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = { 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 */ 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 */ 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 */ - 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 */ - 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 */ + 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 */ + 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 */ CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ }; diff --git a/trunk/drivers/input/keyboard/lkkbd.c b/trunk/drivers/input/keyboard/lkkbd.c index 098963c7cdd6..2694ff2b5beb 100644 --- a/trunk/drivers/input/keyboard/lkkbd.c +++ b/trunk/drivers/input/keyboard/lkkbd.c @@ -15,10 +15,10 @@ * information given below, I will _not_ be liable! * * RJ10 pinout: To DE9: Or DB25: - * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD) - * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND) - * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD) - * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!! + * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD) + * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND) + * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD) + * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!! * * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For * RJ10, it's like this: diff --git a/trunk/drivers/input/keyboard/locomokbd.c b/trunk/drivers/input/keyboard/locomokbd.c index 8935290256b3..d3e9dd6a13cd 100644 --- a/trunk/drivers/input/keyboard/locomokbd.c +++ b/trunk/drivers/input/keyboard/locomokbd.c @@ -42,7 +42,7 @@ MODULE_AUTHOR("John Lenz "); MODULE_DESCRIPTION("LoCoMo keyboard driver"); MODULE_LICENSE("GPL"); -#define LOCOMOKBD_NUMKEYS 128 +#define LOCOMOKBD_NUMKEYS 128 #define KEY_ACTIVITY KEY_F16 #define KEY_CONTACT KEY_F18 @@ -61,7 +61,7 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = { KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */ 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */ KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */ - KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */ + KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */ }; #define KB_ROWS 16 @@ -82,7 +82,7 @@ struct locomokbd { struct locomo_dev *ldev; unsigned long base; spinlock_t lock; - + struct timer_list timer; }; @@ -95,7 +95,7 @@ static inline void locomokbd_charge_all(unsigned long membase) static inline void locomokbd_activate_all(unsigned long membase) { unsigned long r; - + locomo_writel(0, membase + LOCOMO_KSC); r = locomo_readl(membase + LOCOMO_KIC); r &= 0xFEFF; @@ -127,7 +127,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col) */ /* Scan the hardware keyboard and push any changes up through the input layer */ -static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) +static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) { unsigned int row, col, rowd, scancode; unsigned long flags; @@ -138,7 +138,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * if (regs) input_regs(&locomokbd->input, regs); - + locomokbd_charge_all(membase); num_pressed = 0; @@ -146,9 +146,9 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * locomokbd_activate_col(membase, col); udelay(KB_DELAY); - + rowd = ~locomo_readl(membase + LOCOMO_KIB); - for (row = 0; row < KB_ROWS; row++) { + for (row = 0; row < KB_ROWS; row++ ) { scancode = SCANCODE(col, row); if (rowd & KB_ROWMASK(row)) { num_pressed += 1; @@ -170,7 +170,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * spin_unlock_irqrestore(&locomokbd->lock, flags); } -/* +/* * LoCoMo keyboard interrupt handler. */ 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) memset(locomokbd, 0, sizeof(struct locomokbd)); /* try and claim memory region */ - if (!request_mem_region((unsigned long) dev->mapbase, - dev->length, + if (!request_mem_region((unsigned long) dev->mapbase, + dev->length, LOCOMO_DRIVER_NAME(dev))) { ret = -EBUSY; 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) locomokbd->timer.data = (unsigned long) locomokbd; locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - + init_input_dev(&locomokbd->input); locomokbd->input.keycode = locomokbd->keycode; locomokbd->input.keycodesize = sizeof(unsigned char); @@ -271,11 +271,11 @@ static int locomokbd_probe(struct locomo_dev *dev) static int locomokbd_remove(struct locomo_dev *dev) { struct locomokbd *locomokbd = locomo_get_drvdata(dev); - + free_irq(dev->irq[0], locomokbd); del_timer_sync(&locomokbd->timer); - + input_unregister_device(&locomokbd->input); locomo_set_drvdata(dev, NULL); diff --git a/trunk/drivers/input/keyboard/maple_keyb.c b/trunk/drivers/input/keyboard/maple_keyb.c index eecbde294f1f..859ed771ee0a 100644 --- a/trunk/drivers/input/keyboard/maple_keyb.c +++ b/trunk/drivers/input/keyboard/maple_keyb.c @@ -1,6 +1,6 @@ /* * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ - * SEGA Dreamcast keyboard driver + * SEGA Dreamcast keyboard driver * Based on drivers/usb/usbkbd.c */ @@ -40,6 +40,7 @@ struct dc_kbd { struct input_dev dev; unsigned char new[8]; unsigned char old[8]; + int open; }; @@ -94,6 +95,22 @@ static void dc_kbd_callback(struct mapleq *mq) } } + +static int dc_kbd_open(struct input_dev *dev) +{ + struct dc_kbd *kbd = dev->private; + kbd->open++; + return 0; +} + + +static void dc_kbd_close(struct input_dev *dev) +{ + struct dc_kbd *kbd = dev->private; + kbd->open--; +} + + static int dc_kbd_connect(struct maple_device *dev) { int i; @@ -116,6 +133,9 @@ static int dc_kbd_connect(struct maple_device *dev) clear_bit(0, kbd->dev.keybit); kbd->dev.private = kbd; + kbd->dev.open = dc_kbd_open; + kbd->dev.close = dc_kbd_close; + kbd->dev.event = NULL; kbd->dev.name = dev->product_name; kbd->dev.id.bustype = BUS_MAPLE; diff --git a/trunk/drivers/input/misc/uinput.c b/trunk/drivers/input/misc/uinput.c index 98710997aaaa..158c8e845ff9 100644 --- a/trunk/drivers/input/misc/uinput.c +++ b/trunk/drivers/input/misc/uinput.c @@ -298,11 +298,9 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz /* check if absmin/absmax/absfuzz/absflat are filled as * told in Documentation/input/input-programming.txt */ if (test_bit(EV_ABS, dev->evbit)) { - int err = uinput_validate_absbits(dev); - if (err < 0) { - retval = err; + retval = uinput_validate_absbits(dev); + if (retval < 0) kfree(dev->name); - } } exit: diff --git a/trunk/drivers/input/mouse/Makefile b/trunk/drivers/input/mouse/Makefile index c4909b49337d..a7864195806a 100644 --- a/trunk/drivers/input/mouse/Makefile +++ b/trunk/drivers/input/mouse/Makefile @@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o -psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o +psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o diff --git a/trunk/drivers/input/mouse/alps.c b/trunk/drivers/input/mouse/alps.c index a12e98158a75..7bf4be733e9a 100644 --- a/trunk/drivers/input/mouse/alps.c +++ b/trunk/drivers/input/mouse/alps.c @@ -30,11 +30,10 @@ #define ALPS_DUALPOINT 0x01 #define ALPS_WHEEL 0x02 -#define ALPS_FW_BK_1 0x04 +#define ALPS_FW_BK 0x04 #define ALPS_4BTN 0x08 #define ALPS_OLDPROTO 0x10 #define ALPS_PASS 0x20 -#define ALPS_FW_BK_2 0x40 static struct alps_model_info alps_model_data[] = { { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ @@ -44,11 +43,11 @@ static struct alps_model_info alps_model_data[] = { { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ - { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ + { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK }, /* NEC Versa L320 */ { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, - { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ + { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ @@ -62,11 +61,11 @@ static struct alps_model_info alps_model_data[] = { /* * ALPS abolute Mode - new format - * - * byte 0: 1 ? ? ? 1 ? ? ? + * + * byte 0: 1 ? ? ? 1 ? ? ? * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 * byte 2: 0 x10 x9 x8 x7 ? fin ges - * byte 3: 0 y9 y8 y7 1 M R L + * byte 3: 0 y9 y8 y7 1 M R L * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 * @@ -82,12 +81,11 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) struct input_dev *dev = &psmouse->dev; struct input_dev *dev2 = &priv->dev2; int x, y, z, ges, fin, left, right, middle; - int back = 0, forward = 0; input_regs(dev, regs); if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ - input_report_key(dev2, BTN_LEFT, packet[0] & 1); + input_report_key(dev2, BTN_LEFT, packet[0] & 1); input_report_key(dev2, BTN_RIGHT, packet[0] & 2); input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); input_report_rel(dev2, REL_X, @@ -114,18 +112,6 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) z = packet[5]; } - if (priv->i->flags & ALPS_FW_BK_1) { - back = packet[2] & 4; - forward = packet[0] & 0x10; - } - - if (priv->i->flags & ALPS_FW_BK_2) { - back = packet[3] & 4; - forward = packet[2] & 4; - if ((middle = forward && back)) - forward = back = 0; - } - ges = packet[2] & 1; fin = packet[2] & 2; @@ -169,12 +155,13 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) input_report_abs(dev, ABS_PRESSURE, z); input_report_key(dev, BTN_TOOL_FINGER, z > 0); + if (priv->i->flags & ALPS_WHEEL) input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); - if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { - input_report_key(dev, BTN_FORWARD, forward); - input_report_key(dev, BTN_BACK, back); + if (priv->i->flags & ALPS_FW_BK) { + input_report_key(dev, BTN_FORWARD, packet[0] & 0x10); + input_report_key(dev, BTN_BACK, packet[2] & 0x04); } input_sync(dev); @@ -270,6 +257,7 @@ static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *vers static int alps_passthrough_mode(struct psmouse *psmouse, int enable) { struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[3]; int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; if (ps2_command(ps2dev, NULL, cmd) || @@ -279,7 +267,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, int enable) return -1; /* we may get 3 more bytes, just ignore them */ - ps2_drain(ps2dev, 3, 100); + ps2_command(ps2dev, param, 0x0300); return 0; } @@ -437,7 +425,7 @@ int alps_init(struct psmouse *psmouse) psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL); } - if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { + if (priv->i->flags & ALPS_FW_BK) { psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); } @@ -448,8 +436,8 @@ int alps_init(struct psmouse *psmouse) priv->dev2.id.bustype = BUS_I8042; priv->dev2.id.vendor = 0x0002; priv->dev2.id.product = PSMOUSE_ALPS; - priv->dev2.id.version = 0x0000; - + priv->dev2.id.version = 0x0000; + priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); @@ -473,15 +461,17 @@ int alps_init(struct psmouse *psmouse) int alps_detect(struct psmouse *psmouse, int set_properties) { int version; - struct alps_model_info *model; + struct alps_model_info *model; if (!(model = alps_get_model(psmouse, &version))) return -1; if (set_properties) { psmouse->vendor = "ALPS"; - psmouse->name = model->flags & ALPS_DUALPOINT ? - "DualPoint TouchPad" : "GlidePoint"; + if (model->flags & ALPS_DUALPOINT) + psmouse->name = "DualPoint TouchPad"; + else + psmouse->name = "GlidePoint"; psmouse->model = version; } return 0; diff --git a/trunk/drivers/input/mouse/amimouse.c b/trunk/drivers/input/mouse/amimouse.c index e994849efb8f..7baa09cca7c5 100644 --- a/trunk/drivers/input/mouse/amimouse.c +++ b/trunk/drivers/input/mouse/amimouse.c @@ -33,6 +33,7 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Amiga mouse driver"); MODULE_LICENSE("GPL"); +static int amimouse_used = 0; static int amimouse_lastx, amimouse_lasty; static struct input_dev amimouse_dev; @@ -80,12 +81,16 @@ static int amimouse_open(struct input_dev *dev) { unsigned short joy0dat; + if (amimouse_used++) + return 0; + joy0dat = custom.joy0dat; amimouse_lastx = joy0dat & 0xff; amimouse_lasty = joy0dat >> 8; if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { + amimouse_used--; printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); return -EBUSY; } @@ -95,7 +100,8 @@ static int amimouse_open(struct input_dev *dev) static void amimouse_close(struct input_dev *dev) { - free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); + if (!--amimouse_used) + free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); } static int __init amimouse_init(void) diff --git a/trunk/drivers/input/mouse/inport.c b/trunk/drivers/input/mouse/inport.c index 1f62c0134010..ca4e96886627 100644 --- a/trunk/drivers/input/mouse/inport.c +++ b/trunk/drivers/input/mouse/inport.c @@ -17,18 +17,18 @@ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -87,23 +87,29 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); __obsolete_setup("inport_irq="); +static int inport_used; + static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int inport_open(struct input_dev *dev) { - if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) - return -EBUSY; - outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); - outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); + if (!inport_used++) { + if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) + return -EBUSY; + outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); + outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); + } return 0; } static void inport_close(struct input_dev *dev) { - outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); - outb(INPORT_MODE_BASE, INPORT_DATA_PORT); - free_irq(inport_irq, NULL); + if (!--inport_used) { + outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); + outb(INPORT_MODE_BASE, INPORT_DATA_PORT); + free_irq(inport_irq, NULL); + } } static struct input_dev inport_dev = { @@ -114,11 +120,11 @@ static struct input_dev inport_dev = { .close = inport_close, .name = INPORT_NAME, .phys = "isa023c/input0", - .id = { - .bustype = BUS_ISA, - .vendor = INPORT_VENDOR, - .product = 0x0001, - .version = 0x0100, + .id = { + .bustype = BUS_ISA, + .vendor = INPORT_VENDOR, + .product = 0x0001, + .version = 0x0100, }, }; diff --git a/trunk/drivers/input/mouse/lifebook.c b/trunk/drivers/input/mouse/lifebook.c deleted file mode 100644 index bd9df9b28325..000000000000 --- a/trunk/drivers/input/mouse/lifebook.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Fujitsu B-series Lifebook PS/2 TouchScreen driver - * - * Copyright (c) 2005 Vojtech Pavlik - * Copyright (c) 2005 Kenan Esau - * - * TouchScreen detection, absolute mode setting and packet layout is taken from - * Harald Hoyer's description of the device. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include "psmouse.h" -#include "lifebook.h" - -static struct dmi_system_id lifebook_dmi_table[] = { - { - .ident = "Lifebook B", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), - }, - }, - { } -}; - - -static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs) -{ - unsigned char *packet = psmouse->packet; - struct input_dev *dev = &psmouse->dev; - - if (psmouse->pktcnt != 3) - return PSMOUSE_GOOD_DATA; - - input_regs(dev, regs); - - /* calculate X and Y */ - if ((packet[0] & 0x08) == 0x00) { - input_report_abs(dev, ABS_X, - (packet[1] | ((packet[0] & 0x30) << 4))); - input_report_abs(dev, ABS_Y, - 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); - } else { - input_report_rel(dev, REL_X, - ((packet[0] & 0x10) ? packet[1] - 256 : packet[1])); - input_report_rel(dev, REL_Y, - -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2])); - } - - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - input_report_key(dev, BTN_TOUCH, packet[0] & 0x04); - - input_sync(dev); - - return PSMOUSE_FULL_PACKET; -} - -static int lifebook_absolute_mode(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param; - - if (psmouse_reset(psmouse)) - return -1; - - /* - Enable absolute output -- ps2_command fails always but if - you leave this call out the touchsreen will never send - absolute coordinates - */ - param = 0x07; - ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); - - return 0; -} - -static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution) -{ - unsigned char params[] = { 0, 1, 2, 2, 3 }; - - if (resolution == 0 || resolution > 400) - resolution = 400; - - ps2_command(&psmouse->ps2dev, ¶ms[resolution / 100], PSMOUSE_CMD_SETRES); - psmouse->resolution = 50 << params[resolution / 100]; -} - -static void lifebook_disconnect(struct psmouse *psmouse) -{ - psmouse_reset(psmouse); -} - -int lifebook_detect(struct psmouse *psmouse, int set_properties) -{ - if (!dmi_check_system(lifebook_dmi_table)) - return -1; - - if (set_properties) { - psmouse->vendor = "Fujitsu"; - psmouse->name = "Lifebook TouchScreen"; - } - - return 0; -} - -int lifebook_init(struct psmouse *psmouse) -{ - if (lifebook_absolute_mode(psmouse)) - return -1; - - psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); - psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); - psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); - input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0); - input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0); - - psmouse->protocol_handler = lifebook_process_byte; - psmouse->set_resolution = lifebook_set_resolution; - psmouse->disconnect = lifebook_disconnect; - psmouse->reconnect = lifebook_absolute_mode; - psmouse->pktsize = 3; - - return 0; -} - diff --git a/trunk/drivers/input/mouse/lifebook.h b/trunk/drivers/input/mouse/lifebook.h deleted file mode 100644 index be1c0943825d..000000000000 --- a/trunk/drivers/input/mouse/lifebook.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Fujitsu B-series Lifebook PS/2 TouchScreen driver - * - * Copyright (c) 2005 Vojtech Pavlik - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#ifndef _LIFEBOOK_H -#define _LIFEBOOK_H - -int lifebook_detect(struct psmouse *psmouse, int set_properties); -int lifebook_init(struct psmouse *psmouse); - -#endif diff --git a/trunk/drivers/input/mouse/logibm.c b/trunk/drivers/input/mouse/logibm.c index 8b5243167227..77eb83e87f61 100644 --- a/trunk/drivers/input/mouse/logibm.c +++ b/trunk/drivers/input/mouse/logibm.c @@ -18,18 +18,18 @@ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -77,11 +77,16 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); __obsolete_setup("logibm_irq="); +static int logibm_used = 0; + static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int logibm_open(struct input_dev *dev) { + if (logibm_used++) + return 0; if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) { + logibm_used--; printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq); return -EBUSY; } @@ -91,6 +96,8 @@ static int logibm_open(struct input_dev *dev) static void logibm_close(struct input_dev *dev) { + if (--logibm_used) + return; outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); free_irq(logibm_irq, NULL); } @@ -160,7 +167,7 @@ static int __init logibm_init(void) outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); input_register_device(&logibm_dev); - + printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq); return 0; diff --git a/trunk/drivers/input/mouse/maplemouse.c b/trunk/drivers/input/mouse/maplemouse.c index e90c60cbbf05..12dc0ef5020f 100644 --- a/trunk/drivers/input/mouse/maplemouse.c +++ b/trunk/drivers/input/mouse/maplemouse.c @@ -1,6 +1,6 @@ /* * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $ - * SEGA Dreamcast mouse driver + * SEGA Dreamcast mouse driver * Based on drivers/usb/usbmouse.c */ @@ -15,51 +15,80 @@ MODULE_AUTHOR("YAEGASHI Takeshi "); MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); +struct dc_mouse { + struct input_dev dev; + int open; +}; + + static void dc_mouse_callback(struct mapleq *mq) { int buttons, relx, rely, relz; struct maple_device *mapledev = mq->dev; - struct input_dev *dev = mapledev->private_data; + struct dc_mouse *mouse = mapledev->private_data; + struct input_dev *dev = &mouse->dev; unsigned char *res = mq->recvbuf; buttons = ~res[8]; - relx = *(unsigned short *)(res + 12) - 512; - rely = *(unsigned short *)(res + 14) - 512; - relz = *(unsigned short *)(res + 16) - 512; + relx=*(unsigned short *)(res+12)-512; + rely=*(unsigned short *)(res+14)-512; + relz=*(unsigned short *)(res+16)-512; - input_report_key(dev, BTN_LEFT, buttons & 4); - input_report_key(dev, BTN_MIDDLE, buttons & 9); - input_report_key(dev, BTN_RIGHT, buttons & 2); + input_report_key(dev, BTN_LEFT, buttons&4); + input_report_key(dev, BTN_MIDDLE, buttons&9); + input_report_key(dev, BTN_RIGHT, buttons&2); input_report_rel(dev, REL_X, relx); input_report_rel(dev, REL_Y, rely); input_report_rel(dev, REL_WHEEL, relz); input_sync(dev); } + +static int dc_mouse_open(struct input_dev *dev) +{ + struct dc_mouse *mouse = dev->private; + mouse->open++; + return 0; +} + + +static void dc_mouse_close(struct input_dev *dev) +{ + struct dc_mouse *mouse = dev->private; + mouse->open--; +} + + static int dc_mouse_connect(struct maple_device *dev) { unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); - struct input_dev *input_dev; + struct dc_mouse *mouse; - if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL))) + if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL))) return -1; + memset(mouse, 0, sizeof(struct dc_mouse)); + + dev->private_data = mouse; - dev->private_data = input_dev; + mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); + mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); + mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); - memset(input_dev, 0, sizeof(struct dc_mouse)); - init_input_dev(input_dev); - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); + init_input_dev(&mouse->dev); - input_dev->name = dev->product_name; - input_dev->id.bustype = BUS_MAPLE; + mouse->dev.private = mouse; + mouse->dev.open = dc_mouse_open; + mouse->dev.close = dc_mouse_close; + mouse->dev.event = NULL; - input_register_device(input_dev); + mouse->dev.name = dev->product_name; + mouse->dev.id.bustype = BUS_MAPLE; + + input_register_device(&mouse->dev); maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE); - printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name); + printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, mouse->dev.name); return 0; } @@ -67,10 +96,10 @@ static int dc_mouse_connect(struct maple_device *dev) static void dc_mouse_disconnect(struct maple_device *dev) { - struct input_dev *input_dev = dev->private_data; + struct dc_mouse *mouse = dev->private_data; - input_unregister_device(input_dev); - kfree(input_dev); + input_unregister_device(&mouse->dev); + kfree(mouse); } diff --git a/trunk/drivers/input/mouse/pc110pad.c b/trunk/drivers/input/mouse/pc110pad.c index 93393d5c0078..0c74918fe254 100644 --- a/trunk/drivers/input/mouse/pc110pad.c +++ b/trunk/drivers/input/mouse/pc110pad.c @@ -4,7 +4,7 @@ * Copyright (c) 2000-2001 Vojtech Pavlik * * Based on the work of: - * Alan Cox Robin O'Leary + * Alan Cox Robin O'Leary */ /* @@ -56,6 +56,7 @@ static int pc110pad_io = 0x15e0; static struct input_dev pc110pad_dev; static int pc110pad_data[3]; static int pc110pad_count; +static int pc110pad_used; static char *pc110pad_name = "IBM PC110 TouchPad"; static char *pc110pad_phys = "isa15e0/input0"; @@ -73,7 +74,7 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) if (pc110pad_count < 3) return IRQ_HANDLED; - + input_regs(&pc110pad_dev, regs); input_report_key(&pc110pad_dev, BTN_TOUCH, pc110pad_data[0] & 0x01); @@ -89,11 +90,15 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) static void pc110pad_close(struct input_dev *dev) { - outb(PC110PAD_OFF, pc110pad_io + 2); + if (!--pc110pad_used) + outb(PC110PAD_OFF, pc110pad_io + 2); } static int pc110pad_open(struct input_dev *dev) { + if (pc110pad_used++) + return 0; + pc110pad_interrupt(0,NULL,NULL); pc110pad_interrupt(0,NULL,NULL); pc110pad_interrupt(0,NULL,NULL); @@ -140,7 +145,7 @@ static int __init pc110pad_init(void) pc110pad_dev.absmax[ABS_X] = 0x1ff; pc110pad_dev.absmax[ABS_Y] = 0x0ff; - + pc110pad_dev.open = pc110pad_open; pc110pad_dev.close = pc110pad_close; @@ -151,17 +156,17 @@ static int __init pc110pad_init(void) pc110pad_dev.id.product = 0x0001; pc110pad_dev.id.version = 0x0100; - input_register_device(&pc110pad_dev); + input_register_device(&pc110pad_dev); printk(KERN_INFO "input: %s at %#x irq %d\n", pc110pad_name, pc110pad_io, pc110pad_irq); - + return 0; } - + static void __exit pc110pad_exit(void) { - input_unregister_device(&pc110pad_dev); + input_unregister_device(&pc110pad_dev); outb(PC110PAD_OFF, pc110pad_io + 2); diff --git a/trunk/drivers/input/mouse/psmouse-base.c b/trunk/drivers/input/mouse/psmouse-base.c index 19785a6c5abd..019034b21a0b 100644 --- a/trunk/drivers/input/mouse/psmouse-base.c +++ b/trunk/drivers/input/mouse/psmouse-base.c @@ -24,7 +24,6 @@ #include "synaptics.h" #include "logips2pp.h" #include "alps.h" -#include "lifebook.h" #define DRIVER_DESC "PS/2 mouse driver" @@ -32,9 +31,10 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -static unsigned int psmouse_max_proto = PSMOUSE_AUTO; +static unsigned int psmouse_max_proto = -1U; static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); +static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL }; #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) #define param_set_proto_abbrev psmouse_set_maxproto #define param_get_proto_abbrev psmouse_get_maxproto @@ -57,7 +57,6 @@ static unsigned int psmouse_resetafter; module_param_named(resetafter, psmouse_resetafter, uint, 0644); MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); -PSMOUSE_DEFINE_ATTR(protocol); PSMOUSE_DEFINE_ATTR(rate); PSMOUSE_DEFINE_ATTR(resolution); PSMOUSE_DEFINE_ATTR(resetafter); @@ -68,23 +67,7 @@ __obsolete_setup("psmouse_smartscroll="); __obsolete_setup("psmouse_resetafter="); __obsolete_setup("psmouse_rate="); -/* - * psmouse_sem protects all operations changing state of mouse - * (connecting, disconnecting, changing rate or resolution via - * sysfs). We could use a per-device semaphore but since there - * rarely more than one PS/2 mouse connected and since semaphore - * is taken in "slow" paths it is not worth it. - */ -static DECLARE_MUTEX(psmouse_sem); - -struct psmouse_protocol { - enum psmouse_type type; - char *name; - char *alias; - int maxproto; - int (*detect)(struct psmouse *, int); - int (*init)(struct psmouse *); -}; +static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" }; /* * psmouse_process_byte() analyzes the PS/2 data stream and reports @@ -424,15 +407,12 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) */ static int ps2bare_detect(struct psmouse *psmouse, int set_properties) { - if (set_properties) { - if (!psmouse->vendor) psmouse->vendor = "Generic"; - if (!psmouse->name) psmouse->name = "Mouse"; - } + if (!psmouse->vendor) psmouse->vendor = "Generic"; + if (!psmouse->name) psmouse->name = "Mouse"; return 0; } - /* * psmouse_extensions() probes for any extensions to the basic PS/2 protocol * the mouse may have. @@ -443,17 +423,6 @@ static int psmouse_extensions(struct psmouse *psmouse, { int synaptics_hardware = 0; -/* - * We always check for lifebook because it does not disturb mouse - * (it only checks DMI information). - */ - if (lifebook_detect(psmouse, set_properties) == 0) { - if (max_proto > PSMOUSE_IMEX) { - if (!set_properties || lifebook_init(psmouse) == 0) - return PSMOUSE_LIFEBOOK; - } - } - /* * Try Kensington ThinkingMouse (we try first, because synaptics probe * upsets the thinkingmouse). @@ -537,103 +506,6 @@ static int psmouse_extensions(struct psmouse *psmouse, return PSMOUSE_PS2; } -static struct psmouse_protocol psmouse_protocols[] = { - { - .type = PSMOUSE_PS2, - .name = "PS/2", - .alias = "bare", - .maxproto = 1, - .detect = ps2bare_detect, - }, - { - .type = PSMOUSE_PS2PP, - .name = "PS2++", - .alias = "logitech", - .detect = ps2pp_init, - }, - { - .type = PSMOUSE_THINKPS, - .name = "ThinkPS/2", - .alias = "thinkps", - .detect = thinking_detect, - }, - { - .type = PSMOUSE_GENPS, - .name = "GenPS/2", - .alias = "genius", - .detect = genius_detect, - }, - { - .type = PSMOUSE_IMPS, - .name = "ImPS/2", - .alias = "imps", - .maxproto = 1, - .detect = intellimouse_detect, - }, - { - .type = PSMOUSE_IMEX, - .name = "ImExPS/2", - .alias = "exps", - .maxproto = 1, - .detect = im_explorer_detect, - }, - { - .type = PSMOUSE_SYNAPTICS, - .name = "SynPS/2", - .alias = "synaptics", - .detect = synaptics_detect, - .init = synaptics_init, - }, - { - .type = PSMOUSE_ALPS, - .name = "AlpsPS/2", - .alias = "alps", - .detect = alps_detect, - .init = alps_init, - }, - { - .type = PSMOUSE_LIFEBOOK, - .name = "LBPS/2", - .alias = "lifebook", - .init = lifebook_init, - }, - { - .type = PSMOUSE_AUTO, - .name = "auto", - .alias = "any", - .maxproto = 1, - }, -}; - -static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) - if (psmouse_protocols[i].type == type) - return &psmouse_protocols[i]; - - WARN_ON(1); - return &psmouse_protocols[0]; -} - -static struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len) -{ - struct psmouse_protocol *p; - int i; - - for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) { - p = &psmouse_protocols[i]; - - if ((strlen(p->name) == len && !strncmp(p->name, name, len)) || - (strlen(p->alias) == len && !strncmp(p->alias, name, len))) - return &psmouse_protocols[i]; - } - - return NULL; -} - - /* * psmouse_probe() probes for a PS/2 mouse. */ @@ -781,84 +653,30 @@ static void psmouse_cleanup(struct serio *serio) static void psmouse_disconnect(struct serio *serio) { - struct psmouse *psmouse, *parent = NULL; + struct psmouse *psmouse, *parent; - psmouse = serio_get_drvdata(serio); - - device_remove_file(&serio->dev, &psmouse_attr_protocol); device_remove_file(&serio->dev, &psmouse_attr_rate); device_remove_file(&serio->dev, &psmouse_attr_resolution); device_remove_file(&serio->dev, &psmouse_attr_resetafter); - down(&psmouse_sem); - + psmouse = serio_get_drvdata(serio); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { parent = serio_get_drvdata(serio->parent); - psmouse_deactivate(parent); + if (parent->pt_deactivate) + parent->pt_deactivate(parent); } if (psmouse->disconnect) psmouse->disconnect(psmouse); - if (parent && parent->pt_deactivate) - parent->pt_deactivate(parent); - psmouse_set_state(psmouse, PSMOUSE_IGNORE); input_unregister_device(&psmouse->dev); serio_close(serio); serio_set_drvdata(serio, NULL); kfree(psmouse); - - if (parent) - psmouse_activate(parent); - - up(&psmouse_sem); -} - -static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto) -{ - memset(&psmouse->dev, 0, sizeof(struct input_dev)); - - init_input_dev(&psmouse->dev); - - psmouse->dev.private = psmouse; - psmouse->dev.dev = &psmouse->ps2dev.serio->dev; - - psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); - psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); - - psmouse->set_rate = psmouse_set_rate; - psmouse->set_resolution = psmouse_set_resolution; - psmouse->protocol_handler = psmouse_process_byte; - psmouse->pktsize = 3; - - if (proto && (proto->detect || proto->init)) { - if (proto->detect && proto->detect(psmouse, 1) < 0) - return -1; - - if (proto->init && proto->init(psmouse) < 0) - return -1; - - psmouse->type = proto->type; - } - else - psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); - - sprintf(psmouse->devname, "%s %s %s", - psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); - - psmouse->dev.name = psmouse->devname; - psmouse->dev.phys = psmouse->phys; - psmouse->dev.id.bustype = BUS_I8042; - psmouse->dev.id.vendor = 0x0002; - psmouse->dev.id.product = psmouse->type; - psmouse->dev.id.version = psmouse->model; - - return 0; } /* @@ -870,8 +688,6 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) struct psmouse *psmouse, *parent = NULL; int retval; - down(&psmouse_sem); - /* * If this is a pass-through port deactivate parent so the device * connected to this port can be successfully identified @@ -881,14 +697,20 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse_deactivate(parent); } - if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) { + if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) { retval = -ENOMEM; goto out; } + memset(psmouse, 0, sizeof(struct psmouse)); + ps2_init(&psmouse->ps2dev, serio); sprintf(psmouse->phys, "%s/input0", serio->phys); - + psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); + psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); + psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); + psmouse->dev.private = psmouse; + psmouse->dev.dev = &serio->dev; psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); serio_set_drvdata(serio, psmouse); @@ -912,10 +734,25 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse->resolution = psmouse_resolution; psmouse->resetafter = psmouse_resetafter; psmouse->smartscroll = psmouse_smartscroll; + psmouse->set_rate = psmouse_set_rate; + psmouse->set_resolution = psmouse_set_resolution; + psmouse->protocol_handler = psmouse_process_byte; + psmouse->pktsize = 3; - psmouse_switch_protocol(psmouse, NULL); + psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); + + sprintf(psmouse->devname, "%s %s %s", + psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name); + + psmouse->dev.name = psmouse->devname; + psmouse->dev.phys = psmouse->phys; + psmouse->dev.id.bustype = BUS_I8042; + psmouse->dev.id.vendor = 0x0002; + psmouse->dev.id.product = psmouse->type; + psmouse->dev.id.version = psmouse->model; input_register_device(&psmouse->dev); + printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); @@ -925,7 +762,6 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) if (parent && parent->pt_activate) parent->pt_activate(parent); - device_create_file(&serio->dev, &psmouse_attr_protocol); device_create_file(&serio->dev, &psmouse_attr_rate); device_create_file(&serio->dev, &psmouse_attr_resolution); device_create_file(&serio->dev, &psmouse_attr_resetafter); @@ -935,11 +771,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) retval = 0; out: - /* If this is a pass-through port the parent needs to be re-activated */ + /* If this is a pass-through port the parent awaits to be activated */ if (parent) psmouse_activate(parent); - up(&psmouse_sem); return retval; } @@ -956,8 +791,6 @@ static int psmouse_reconnect(struct serio *serio) return -1; } - down(&psmouse_sem); - if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { parent = serio_get_drvdata(serio->parent); psmouse_deactivate(parent); @@ -990,7 +823,6 @@ static int psmouse_reconnect(struct serio *serio) if (parent) psmouse_activate(parent); - up(&psmouse_sem); return rc; } @@ -1061,109 +893,26 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun if (serio->drv != &psmouse_drv) { retval = -ENODEV; - goto out_unpin; - } - - retval = down_interruptible(&psmouse_sem); - if (retval) - goto out_unpin; - - if (psmouse->state == PSMOUSE_IGNORE) { - retval = -ENODEV; - goto out_up; + goto out; } if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { parent = serio_get_drvdata(serio->parent); psmouse_deactivate(parent); } - psmouse_deactivate(psmouse); retval = handler(psmouse, buf, count); - if (retval != -ENODEV) - psmouse_activate(psmouse); - + psmouse_activate(psmouse); if (parent) psmouse_activate(parent); - out_up: - up(&psmouse_sem); - out_unpin: +out: serio_unpin_driver(serio); return retval; } -static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf) -{ - return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name); -} - -static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count) -{ - struct serio *serio = psmouse->ps2dev.serio; - struct psmouse *parent = NULL; - struct psmouse_protocol *proto; - int retry = 0; - - if (!(proto = psmouse_protocol_by_name(buf, count))) - return -EINVAL; - - if (psmouse->type == proto->type) - return count; - - while (serio->child) { - if (++retry > 3) { - printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n"); - return -EIO; - } - - up(&psmouse_sem); - serio_unpin_driver(serio); - serio_unregister_child_port(serio); - serio_pin_driver_uninterruptible(serio); - down(&psmouse_sem); - - if (serio->drv != &psmouse_drv) - return -ENODEV; - - if (psmouse->type == proto->type) - return count; /* switched by other thread */ - } - - if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); - if (parent->pt_deactivate) - parent->pt_deactivate(parent); - } - - if (psmouse->disconnect) - psmouse->disconnect(psmouse); - - psmouse_set_state(psmouse, PSMOUSE_IGNORE); - input_unregister_device(&psmouse->dev); - - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - - if (psmouse_switch_protocol(psmouse, proto) < 0) { - psmouse_reset(psmouse); - /* default to PSMOUSE_PS2 */ - psmouse_switch_protocol(psmouse, &psmouse_protocols[0]); - } - - psmouse_initialize(psmouse); - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - - input_register_device(&psmouse->dev); - printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); - - if (parent && parent->pt_activate) - parent->pt_activate(parent); - - return count; -} - static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) { return sprintf(buf, "%d\n", psmouse->rate); @@ -1220,26 +969,34 @@ static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char * static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) { - struct psmouse_protocol *proto; + int i; if (!val) return -EINVAL; - proto = psmouse_protocol_by_name(val, strlen(val)); + if (!strncmp(val, "any", 3)) { + *((unsigned int *)kp->arg) = -1U; + return 0; + } - if (!proto || !proto->maxproto) - return -EINVAL; + for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) { + if (!psmouse_proto_abbrev[i]) + continue; - *((unsigned int *)kp->arg) = proto->type; + if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) { + *((unsigned int *)kp->arg) = i; + return 0; + } + } - return 0; \ + return -EINVAL; \ } static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) { - int type = *((unsigned int *)kp->arg); - - return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name); + return sprintf(buffer, "%s\n", + psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ? + psmouse_proto_abbrev[psmouse_max_proto] : "any"); } static int __init psmouse_init(void) diff --git a/trunk/drivers/input/mouse/psmouse.h b/trunk/drivers/input/mouse/psmouse.h index 86691cf43433..79e17a0c4664 100644 --- a/trunk/drivers/input/mouse/psmouse.h +++ b/trunk/drivers/input/mouse/psmouse.h @@ -77,8 +77,6 @@ enum psmouse_type { PSMOUSE_IMEX, PSMOUSE_SYNAPTICS, PSMOUSE_ALPS, - PSMOUSE_LIFEBOOK, - PSMOUSE_AUTO /* This one should always be last */ }; int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); @@ -101,7 +99,7 @@ static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute { \ return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ } \ -static struct device_attribute psmouse_attr_##_name = \ +static struct device_attribute psmouse_attr_##_name = \ __ATTR(_name, S_IWUSR | S_IRUGO, \ psmouse_do_show_##_name, psmouse_do_set_##_name); diff --git a/trunk/drivers/input/mouse/rpcmouse.c b/trunk/drivers/input/mouse/rpcmouse.c index 8fe1212b8fd7..7280f68afcee 100644 --- a/trunk/drivers/input/mouse/rpcmouse.c +++ b/trunk/drivers/input/mouse/rpcmouse.c @@ -59,7 +59,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) b = (short) (__raw_readl(0xe0310000) ^ 0x70); dx = x - rpcmouse_lastx; - dy = y - rpcmouse_lasty; + dy = y - rpcmouse_lasty; rpcmouse_lastx = x; rpcmouse_lasty = y; diff --git a/trunk/drivers/input/mouse/vsxxxaa.c b/trunk/drivers/input/mouse/vsxxxaa.c index f024be9b44d2..b2cb101c8110 100644 --- a/trunk/drivers/input/mouse/vsxxxaa.c +++ b/trunk/drivers/input/mouse/vsxxxaa.c @@ -1,7 +1,7 @@ /* * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) - * DEC VSXXX-GA mouse (rectangular mouse, with ball) - * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) + * DEC VSXXX-GA mouse (rectangular mouse, with ball) + * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) * * Copyright (C) 2003-2004 by Jan-Benedict Glaw * diff --git a/trunk/drivers/input/mousedev.c b/trunk/drivers/input/mousedev.c index c6194a9dd174..062848ac7e6b 100644 --- a/trunk/drivers/input/mousedev.c +++ b/trunk/drivers/input/mousedev.c @@ -220,7 +220,6 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h struct mousedev_list *list; struct mousedev_motion *p; unsigned long flags; - int wake_readers = 0; list_for_each_entry(list, &mousedev->list, node) { spin_lock_irqsave(&list->packet_lock, flags); @@ -256,14 +255,11 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h spin_unlock_irqrestore(&list->packet_lock, flags); - if (list->ready) { + if (list->ready) kill_fasync(&list->fasync, SIGIO, POLL_IN); - wake_readers = 1; - } } - if (wake_readers) - wake_up_interruptible(&mousedev->wait); + wake_up_interruptible(&mousedev->wait); } static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) diff --git a/trunk/drivers/input/serio/libps2.c b/trunk/drivers/input/serio/libps2.c index d4c990f7c85e..c978657068c5 100644 --- a/trunk/drivers/input/serio/libps2.c +++ b/trunk/drivers/input/serio/libps2.c @@ -29,7 +29,6 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(ps2_init); EXPORT_SYMBOL(ps2_sendbyte); -EXPORT_SYMBOL(ps2_drain); EXPORT_SYMBOL(ps2_command); EXPORT_SYMBOL(ps2_schedule_command); EXPORT_SYMBOL(ps2_handle_ack); @@ -46,11 +45,11 @@ struct ps2work { /* - * ps2_sendbyte() sends a byte to the device and waits for acknowledge. - * It doesn't handle retransmission, though it could - because if there - * is a need for retransmissions device has to be replaced anyway. + * ps2_sendbyte() sends a byte to the mouse, and waits for acknowledge. + * It doesn't handle retransmission, though it could - because when there would + * be need for retransmissions, the mouse has to be replaced anyway. * - * ps2_sendbyte() can only be called from a process context. + * ps2_sendbyte() can only be called from a process context */ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) @@ -72,91 +71,6 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) return -ps2dev->nak; } -/* - * ps2_drain() waits for device to transmit requested number of bytes - * and discards them. - */ - -void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) -{ - if (maxbytes > sizeof(ps2dev->cmdbuf)) { - WARN_ON(1); - maxbytes = sizeof(ps2dev->cmdbuf); - } - - down(&ps2dev->cmd_sem); - - serio_pause_rx(ps2dev->serio); - ps2dev->flags = PS2_FLAG_CMD; - ps2dev->cmdcnt = maxbytes; - serio_continue_rx(ps2dev->serio); - - wait_event_timeout(ps2dev->wait, - !(ps2dev->flags & PS2_FLAG_CMD), - msecs_to_jiffies(timeout)); - up(&ps2dev->cmd_sem); -} - -/* - * ps2_is_keyboard_id() checks received ID byte against the list of - * known keyboard IDs. - */ - -static inline int ps2_is_keyboard_id(char id_byte) -{ - static char keyboard_ids[] = { - 0xab, /* Regular keyboards */ - 0xac, /* NCD Sun keyboard */ - 0x2b, /* Trust keyboard, translated */ - 0x5d, /* Trust keyboard */ - 0x60, /* NMB SGI keyboard, translated */ - 0x47, /* NMB SGI keyboard */ - }; - - return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL; -} - -/* - * ps2_adjust_timeout() is called after receiving 1st byte of command - * response and tries to reduce remaining timeout to speed up command - * completion. - */ - -static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) -{ - switch (command) { - case PS2_CMD_RESET_BAT: - /* - * Device has sent the first response byte after - * reset command, reset is thus done, so we can - * shorten the timeout. - * The next byte will come soon (keyboard) or not - * at all (mouse). - */ - if (timeout > msecs_to_jiffies(100)) - timeout = msecs_to_jiffies(100); - break; - - case PS2_CMD_GETID: - /* - * If device behind the port is not a keyboard there - * won't be 2nd byte of ID response. - */ - if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) { - serio_pause_rx(ps2dev->serio); - ps2dev->flags = ps2dev->cmdcnt = 0; - serio_continue_rx(ps2dev->serio); - timeout = 0; - } - break; - - default: - break; - } - - return timeout; -} - /* * ps2_command() sends a command and its parameters to the mouse, * then waits for the response and puts it in the param array. @@ -172,11 +86,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) int rc = -1; int i; - if (receive > sizeof(ps2dev->cmdbuf)) { - WARN_ON(1); - return -1; - } - down(&ps2dev->cmd_sem); serio_pause_rx(ps2dev->serio); @@ -192,9 +101,10 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) * ACKing the reset command, and so it can take a long * time before the ACK arrrives. */ - if (ps2_sendbyte(ps2dev, command & 0xff, - command == PS2_CMD_RESET_BAT ? 1000 : 200)) - goto out; + if (command & 0xff) + if (ps2_sendbyte(ps2dev, command & 0xff, + command == PS2_CMD_RESET_BAT ? 1000 : 200)) + goto out; for (i = 0; i < send; i++) if (ps2_sendbyte(ps2dev, param[i], 200)) @@ -210,7 +120,33 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) if (ps2dev->cmdcnt && timeout > 0) { - timeout = ps2_adjust_timeout(ps2dev, command, timeout); + if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) { + /* + * Device has sent the first response byte + * after a reset command, reset is thus done, + * shorten the timeout. The next byte will come + * soon (keyboard) or not at all (mouse). + */ + timeout = msecs_to_jiffies(100); + } + + if (command == PS2_CMD_GETID && + ps2dev->cmdbuf[receive - 1] != 0xab && /* Regular keyboards */ + ps2dev->cmdbuf[receive - 1] != 0xac && /* NCD Sun keyboard */ + ps2dev->cmdbuf[receive - 1] != 0x2b && /* Trust keyboard, translated */ + ps2dev->cmdbuf[receive - 1] != 0x5d && /* Trust keyboard */ + ps2dev->cmdbuf[receive - 1] != 0x60 && /* NMB SGI keyboard, translated */ + ps2dev->cmdbuf[receive - 1] != 0x47) { /* NMB SGI keyboard */ + /* + * Device behind the port is not a keyboard + * so we don't need to wait for the 2nd byte + * of ID response. + */ + serio_pause_rx(ps2dev->serio); + ps2dev->flags = ps2dev->cmdcnt = 0; + serio_continue_rx(ps2dev->serio); + } + wait_event_timeout(ps2dev->wait, !(ps2dev->flags & PS2_FLAG_CMD), timeout); } @@ -224,7 +160,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) rc = 0; - out: +out: serio_pause_rx(ps2dev->serio); ps2dev->flags = 0; serio_continue_rx(ps2dev->serio); diff --git a/trunk/drivers/input/touchscreen/elo.c b/trunk/drivers/input/touchscreen/elo.c index 3cdc9cab688d..546ce599334e 100644 --- a/trunk/drivers/input/touchscreen/elo.c +++ b/trunk/drivers/input/touchscreen/elo.c @@ -226,7 +226,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0); break; - + case 1: /* 6-byte protocol */ input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0); diff --git a/trunk/drivers/input/touchscreen/h3600_ts_input.c b/trunk/drivers/input/touchscreen/h3600_ts_input.c index bcfa1e36f957..acb9137a0226 100644 --- a/trunk/drivers/input/touchscreen/h3600_ts_input.c +++ b/trunk/drivers/input/touchscreen/h3600_ts_input.c @@ -89,9 +89,9 @@ MODULE_LICENSE("GPL"); #define H3600_SCANCODE_Q 4 /* 4 -> Q button */ #define H3600_SCANCODE_START 5 /* 5 -> start menu */ #define H3600_SCANCODE_UP 6 /* 6 -> up */ -#define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ -#define H3600_SCANCODE_LEFT 8 /* 8 -> left */ -#define H3600_SCANCODE_DOWN 9 /* 9 -> down */ +#define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ +#define H3600_SCANCODE_LEFT 8 /* 8 -> left */ +#define H3600_SCANCODE_DOWN 9 /* 9 -> down */ static char *h3600_name = "H3600 TouchScreen"; @@ -113,7 +113,7 @@ struct h3600_dev { static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs) { - int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; + int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; struct input_dev *dev = (struct input_dev *) dev_id; input_regs(dev, regs); @@ -125,7 +125,7 @@ static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs * static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) { - int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; + int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; struct input_dev *dev = (struct input_dev *) dev_id; /* @@ -145,8 +145,8 @@ static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs * static int flite_brightness = 25; enum flite_pwr { - FLITE_PWR_OFF = 0, - FLITE_PWR_ON = 1 + FLITE_PWR_OFF = 0, + FLITE_PWR_ON = 1 }; /* @@ -157,9 +157,9 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) struct h3600_dev *ts = dev->private; /* Must be in this order */ - ts->serio->write(ts->serio, 1); + ts->serio->write(ts->serio, 1); ts->serio->write(ts->serio, pwr); - ts->serio->write(ts->serio, brightness); + ts->serio->write(ts->serio, brightness); return 0; } @@ -169,26 +169,26 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, { struct input_dev *dev = (struct input_dev *) data; - switch (req) { - case PM_SUSPEND: /* enter D1-D3 */ - suspended = 1; - h3600_flite_power(dev, FLITE_PWR_OFF); - break; - case PM_BLANK: - if (!suspended) - h3600_flite_power(dev, FLITE_PWR_OFF); - break; - case PM_RESUME: /* enter D0 */ - /* same as unblank */ - case PM_UNBLANK: - if (suspended) { - //initSerial(); - suspended = 0; - } - h3600_flite_power(dev, FLITE_PWR_ON); - break; - } - return 0; + switch (req) { + case PM_SUSPEND: /* enter D1-D3 */ + suspended = 1; + h3600_flite_power(dev, FLITE_PWR_OFF); + break; + case PM_BLANK: + if (!suspended) + h3600_flite_power(dev, FLITE_PWR_OFF); + break; + case PM_RESUME: /* enter D0 */ + /* same as unblank */ + case PM_UNBLANK: + if (suspended) { + //initSerial(); + suspended = 0; + } + h3600_flite_power(dev, FLITE_PWR_ON); + break; + } + return 0; } #endif @@ -199,25 +199,25 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, */ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) { - struct input_dev *dev = &ts->dev; + struct input_dev *dev = &ts->dev; static int touched = 0; int key, down = 0; input_regs(dev, regs); - switch (ts->event) { - /* - Buttons - returned as a single byte - 7 6 5 4 3 2 1 0 - S x x x N N N N + switch (ts->event) { + /* + Buttons - returned as a single byte + 7 6 5 4 3 2 1 0 + S x x x N N N N - S switch state ( 0=pressed 1=released) - x Unused. - NNNN switch number 0-15 + S switch state ( 0=pressed 1=released) + x Unused. + NNNN switch number 0-15 - Note: This is true for non interrupt generated key events. - */ - case KEYBD_ID: + Note: This is true for non interrupt generated key events. + */ + case KEYBD_ID: down = (ts->buf[0] & 0x80) ? 0 : 1; switch (ts->buf[0] & 0x7f) { @@ -229,40 +229,40 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) break; case H3600_SCANCODE_CONTACTS: key = KEY_PROG2; - break; + break; case H3600_SCANCODE_Q: key = KEY_Q; - break; + break; case H3600_SCANCODE_START: key = KEY_PROG3; - break; + break; case H3600_SCANCODE_UP: key = KEY_UP; - break; + break; case H3600_SCANCODE_RIGHT: key = KEY_RIGHT; - break; + break; case H3600_SCANCODE_LEFT: key = KEY_LEFT; - break; + break; case H3600_SCANCODE_DOWN: key = KEY_DOWN; - break; + break; default: key = 0; } - if (key) - input_report_key(dev, key, down); - break; - /* - * Native touchscreen event data is formatted as shown below:- - * - * +-------+-------+-------+-------+ - * | Xmsb | Xlsb | Ymsb | Ylsb | - * +-------+-------+-------+-------+ - * byte 0 1 2 3 - */ - case TOUCHS_ID: + if (key) + input_report_key(dev, key, down); + break; + /* + * Native touchscreen event data is formatted as shown below:- + * + * +-------+-------+-------+-------+ + * | Xmsb | Xlsb | Ymsb | Ylsb | + * +-------+-------+-------+-------+ + * byte 0 1 2 3 + */ + case TOUCHS_ID: if (!touched) { input_report_key(dev, BTN_TOUCH, 1); touched = 1; @@ -272,19 +272,19 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) unsigned short x, y; x = ts->buf[0]; x <<= 8; x += ts->buf[1]; - y = ts->buf[2]; y <<= 8; y += ts->buf[3]; + y = ts->buf[2]; y <<= 8; y += ts->buf[3]; - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); } else { - input_report_key(dev, BTN_TOUCH, 0); + input_report_key(dev, BTN_TOUCH, 0); touched = 0; } - break; + break; default: /* Send a non input event elsewhere */ break; - } + } input_sync(dev); } @@ -293,7 +293,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) * h3600ts_event() handles events from the input module. */ static int h3600ts_event(struct input_dev *dev, unsigned int type, - unsigned int code, int value) + unsigned int code, int value) { struct h3600_dev *ts = dev->private; @@ -332,41 +332,41 @@ static int state; static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs) { - struct h3600_dev *ts = serio_get_drvdata(serio); + struct h3600_dev *ts = serio_get_drvdata(serio); /* - * We have a new frame coming in. - */ + * We have a new frame coming in. + */ switch (state) { case STATE_SOF: - if (data == CHAR_SOF) - state = STATE_ID; + if (data == CHAR_SOF) + state = STATE_ID; break; - case STATE_ID: + case STATE_ID: ts->event = (data & 0xf0) >> 4; ts->len = (data & 0xf); ts->idx = 0; if (ts->event >= MAX_ID) { state = STATE_SOF; - break; + break; } ts->chksum = data; - state = (ts->len > 0) ? STATE_DATA : STATE_EOF; + state = (ts->len > 0) ? STATE_DATA : STATE_EOF; break; case STATE_DATA: ts->chksum += data; ts->buf[ts->idx]= data; - if (++ts->idx == ts->len) - state = STATE_EOF; + if(++ts->idx == ts->len) + state = STATE_EOF; break; case STATE_EOF: - state = STATE_SOF; - if (data == CHAR_EOF || data == ts->chksum) + state = STATE_SOF; + if (data == CHAR_EOF || data == ts->chksum) h3600ts_process_packet(ts, regs); - break; - default: - printk("Error3\n"); - break; + break; + default: + printk("Error3\n"); + break; } return IRQ_HANDLED; @@ -390,10 +390,10 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) init_input_dev(&ts->dev); /* Device specific stuff */ - set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); - set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); + set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); + set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); - if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, + if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, "h3600_action", &ts->dev)) { 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) return -EBUSY; } - if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, + if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, "h3600_suspend", &ts->dev)) { free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); @@ -433,7 +433,7 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) sprintf(ts->phys, "%s/input0", serio->phys); - ts->dev.event = h3600ts_event; + ts->dev.event = h3600ts_event; ts->dev.private = ts; ts->dev.name = h3600_name; ts->dev.phys = ts->phys; @@ -446,8 +446,8 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) { - free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts); - free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts); + free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts); + free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts); serio_set_drvdata(serio, NULL); kfree(ts); return err; diff --git a/trunk/drivers/input/touchscreen/mk712.c b/trunk/drivers/input/touchscreen/mk712.c index afaaebe5225b..2d14a57a05e5 100644 --- a/trunk/drivers/input/touchscreen/mk712.c +++ b/trunk/drivers/input/touchscreen/mk712.c @@ -17,7 +17,7 @@ * found in Gateway AOL Connected Touchpad computers. * * Documentation for ICS MK712 can be found at: - * http://www.icst.com/pdf/mk712.pdf + * http://www.icst.com/pdf/mk712.pdf */ /* @@ -77,6 +77,7 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller"); #define MK712_READ_ONE_POINT 0x20 #define MK712_POWERUP 0x40 +static int mk712_used = 0; static struct input_dev mk712_dev; static DEFINE_SPINLOCK(mk712_lock); @@ -129,14 +130,17 @@ static int mk712_open(struct input_dev *dev) spin_lock_irqsave(&mk712_lock, flags); - outb(0, mk712_io + MK712_CONTROL); /* Reset */ + if (!mk712_used++) { - outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | - MK712_INT_ON_CHANGE_IN_TOUCH_STATUS | - MK712_ENABLE_PERIODIC_CONVERSIONS | - MK712_POWERUP, mk712_io + MK712_CONTROL); + outb(0, mk712_io + MK712_CONTROL); /* Reset */ - outb(10, mk712_io + MK712_RATE); /* 187 points per second */ + outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | + MK712_INT_ON_CHANGE_IN_TOUCH_STATUS | + MK712_ENABLE_PERIODIC_CONVERSIONS | + MK712_POWERUP, mk712_io + MK712_CONTROL); + + outb(10, mk712_io + MK712_RATE); /* 187 points per second */ + } spin_unlock_irqrestore(&mk712_lock, flags); @@ -149,7 +153,8 @@ static void mk712_close(struct input_dev *dev) spin_lock_irqsave(&mk712_lock, flags); - outb(0, mk712_io + MK712_CONTROL); + if (!--mk712_used) + outb(0, mk712_io + MK712_CONTROL); spin_unlock_irqrestore(&mk712_lock, flags); } diff --git a/trunk/drivers/media/video/Kconfig b/trunk/drivers/media/video/Kconfig index 1b70f8b0feb9..f9383e7f34ff 100644 --- a/trunk/drivers/media/video/Kconfig +++ b/trunk/drivers/media/video/Kconfig @@ -7,7 +7,7 @@ menu "Video For Linux" comment "Video Adapters" -config TUNER_MULTI_I2C +config CONFIG_TUNER_MULTI_I2C bool "Enable support for multiple I2C devices on Video Adapters (EXPERIMENTAL)" depends on VIDEO_DEV && EXPERIMENTAL ---help--- diff --git a/trunk/drivers/net/3c523.c b/trunk/drivers/net/3c523.c index 9e1fe2e0478c..1247a25f1093 100644 --- a/trunk/drivers/net/3c523.c +++ b/trunk/drivers/net/3c523.c @@ -1274,7 +1274,6 @@ module_param_array(irq, int, NULL, 0); module_param_array(io, int, NULL, 0); MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)"); MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)"); -MODULE_LICENSE("GPL"); int init_module(void) { diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 2b55687f6ee9..47e158fa5aac 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -1320,7 +1320,7 @@ config FORCEDETH config CS89x0 tristate "CS89x0 support" - depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105 + depends on NET_PCI && (ISA || ARCH_IXDP2X01) ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a network (Ethernet) card of this type, say Y and read the diff --git a/trunk/drivers/net/b44.c b/trunk/drivers/net/b44.c index f1bd45e3da31..3fe8ba992c38 100644 --- a/trunk/drivers/net/b44.c +++ b/trunk/drivers/net/b44.c @@ -1285,9 +1285,6 @@ static int b44_open(struct net_device *dev) b44_init_hw(bp); bp->flags |= B44_FLAG_INIT_COMPLETE; - netif_carrier_off(dev); - b44_check_phy(bp); - spin_unlock_irq(&bp->lock); init_timer(&bp->timer); diff --git a/trunk/drivers/net/cs89x0.c b/trunk/drivers/net/cs89x0.c index b96d6fb1929e..25e4495de79e 100644 --- a/trunk/drivers/net/cs89x0.c +++ b/trunk/drivers/net/cs89x0.c @@ -174,13 +174,6 @@ static unsigned int cs8900_irq_map[] = {1,0,0,0}; #include static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; -#elif defined(CONFIG_ARCH_PNX0105) -#include -#include -#define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */ -#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */ -static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0}; -static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0}; #else static unsigned int netcard_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; @@ -438,30 +431,6 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) #endif } -#ifdef CONFIG_ARCH_PNX0105 - initialize_ebi(); - - /* Map GPIO registers for the pins connected to the CS8900a. */ - if (map_cirrus_gpio() < 0) - return -ENODEV; - - reset_cirrus(); - - /* Map event-router registers. */ - if (map_event_router() < 0) - return -ENODEV; - - enable_cirrus_irq(); - - unmap_cirrus_gpio(); - unmap_event_router(); - - dev->base_addr = ioaddr; - - for (i = 0 ; i < 3 ; i++) - readreg(dev, 0); -#endif - /* Grab the region so we can find another board if autoIRQ fails. */ /* WTF is going on here? */ if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { @@ -703,7 +672,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); } else { i = lp->isa_config & INT_NO_MASK; if (lp->chip_type == CS8900) { -#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) +#ifdef CONFIG_ARCH_IXDP2X01 i = cs8900_irq_map[0]; #else /* Translate the IRQ using the IRQ mapping table. */ @@ -1176,7 +1145,7 @@ net_open(struct net_device *dev) int i; int ret; -#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX0105) /* uses irq#1, so this won't work */ +#ifndef CONFIG_SH_HICOSH4 /* uses irq#1, so this won't work */ if (dev->irq < 2) { /* Allow interrupts to be generated by the chip */ /* Cirrus' release had this: */ @@ -1207,7 +1176,7 @@ net_open(struct net_device *dev) else #endif { -#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105) +#ifndef CONFIG_ARCH_IXDP2X01 if (((1 << dev->irq) & lp->irq_map) == 0) { printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", dev->name, dev->irq, lp->irq_map); @@ -1292,9 +1261,6 @@ net_open(struct net_device *dev) case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); } -#ifdef CONFIG_ARCH_PNX0105 - result = A_CNF_10B_T; -#endif if (!result) { printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name); release_irq: diff --git a/trunk/drivers/net/cs89x0.h b/trunk/drivers/net/cs89x0.h index bd3ad8e6cce9..b0ef7ad2baad 100644 --- a/trunk/drivers/net/cs89x0.h +++ b/trunk/drivers/net/cs89x0.h @@ -16,7 +16,7 @@ #include -#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) +#ifdef CONFIG_ARCH_IXDP2X01 /* IXDP2401/IXDP2801 uses dword-aligned register addressing */ #define CS89x0_PORT(reg) ((reg) * 2) #else diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c index 1e56c8eea35f..cfaa6b2bf345 100644 --- a/trunk/drivers/net/e100.c +++ b/trunk/drivers/net/e100.c @@ -1093,16 +1093,11 @@ static int e100_phy_init(struct nic *nic) } if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) { - /* enable/disable MDI/MDI-X auto-switching. - MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */ - if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) || - (nic->mac == mac_82551_10) || (nic->mii.force_media) || - !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled)) - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0); - else - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH); - } + (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && + (nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) + /* enable/disable MDI/MDI-X auto-switching */ + mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, + nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); return 0; } @@ -1671,10 +1666,8 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs) if(stat_ack & stat_ack_rnr) nic->ru_running = RU_SUSPENDED; - if(likely(netif_rx_schedule_prep(netdev))) { - e100_disable_irq(nic); - __netif_rx_schedule(netdev); - } + e100_disable_irq(nic); + netif_rx_schedule(netdev); return IRQ_HANDLED; } @@ -2342,11 +2335,11 @@ static int __devinit e100_probe(struct pci_dev *pdev, goto err_out_iounmap; } + e100_phy_init(nic); + if((err = e100_eeprom_load(nic))) goto err_out_free; - e100_phy_init(nic); - memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); if(!is_valid_ether_addr(netdev->dev_addr)) { DPRINTK(PROBE, ERR, "Invalid MAC address from " diff --git a/trunk/drivers/net/e1000/e1000.h b/trunk/drivers/net/e1000/e1000.h index 092757bc721f..af1e82c5b808 100644 --- a/trunk/drivers/net/e1000/e1000.h +++ b/trunk/drivers/net/e1000/e1000.h @@ -140,7 +140,7 @@ struct e1000_adapter; #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define AUTO_ALL_MODES 0 -#define E1000_EEPROM_82544_APM 0x0004 +#define E1000_EEPROM_82544_APM 0x0400 #define E1000_EEPROM_APME 0x0400 #ifndef E1000_MASTER_SLAVE @@ -159,7 +159,7 @@ struct e1000_adapter; * so a DMA handle can be stored along with the buffer */ struct e1000_buffer { struct sk_buff *skb; - dma_addr_t dma; + uint64_t dma; unsigned long time_stamp; uint16_t length; uint16_t next_to_watch; diff --git a/trunk/drivers/net/e1000/e1000_ethtool.c b/trunk/drivers/net/e1000/e1000_ethtool.c index f133ff0b0b94..237247f74df4 100644 --- a/trunk/drivers/net/e1000/e1000_ethtool.c +++ b/trunk/drivers/net/e1000/e1000_ethtool.c @@ -105,7 +105,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { static int e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; if(hw->media_type == e1000_media_type_copper) { @@ -141,9 +141,9 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) SUPPORTED_FIBRE | SUPPORTED_Autoneg); - ecmd->advertising = (ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | - ADVERTISED_Autoneg); + ecmd->advertising = (SUPPORTED_1000baseT_Full | + SUPPORTED_FIBRE | + SUPPORTED_Autoneg); ecmd->port = PORT_FIBRE; @@ -179,24 +179,13 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) static int e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; if(ecmd->autoneg == AUTONEG_ENABLE) { hw->autoneg = 1; - if(hw->media_type == e1000_media_type_fiber) - hw->autoneg_advertised = ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | - ADVERTISED_Autoneg; - else - hw->autoneg_advertised = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Full| - ADVERTISED_Autoneg | - ADVERTISED_TP; - ecmd->advertising = hw->autoneg_advertised; + hw->autoneg_advertised = 0x002F; + ecmd->advertising = 0x002F; } else if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) return -EINVAL; @@ -217,7 +206,7 @@ static void e1000_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; pause->autoneg = @@ -237,7 +226,7 @@ static int e1000_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; adapter->fc_autoneg = pause->autoneg; @@ -270,14 +259,14 @@ e1000_set_pauseparam(struct net_device *netdev, static uint32_t e1000_get_rx_csum(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; return adapter->rx_csum; } static int e1000_set_rx_csum(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; adapter->rx_csum = data; if(netif_running(netdev)) { @@ -297,7 +286,7 @@ e1000_get_tx_csum(struct net_device *netdev) static int e1000_set_tx_csum(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; if(adapter->hw.mac_type < e1000_82543) { if (!data) @@ -317,8 +306,8 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data) static int e1000_set_tso(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev_priv(netdev); - if((adapter->hw.mac_type < e1000_82544) || + struct e1000_adapter *adapter = netdev->priv; + if ((adapter->hw.mac_type < e1000_82544) || (adapter->hw.mac_type == e1000_82547)) return data ? -EINVAL : 0; @@ -333,14 +322,14 @@ e1000_set_tso(struct net_device *netdev, uint32_t data) static uint32_t e1000_get_msglevel(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; return adapter->msg_enable; } static void e1000_set_msglevel(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; adapter->msg_enable = data; } @@ -355,7 +344,7 @@ static void e1000_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; uint32_t *regs_buff = p; uint16_t phy_data; @@ -443,7 +432,7 @@ e1000_get_regs(struct net_device *netdev, static int e1000_get_eeprom_len(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; return adapter->hw.eeprom.word_size * 2; } @@ -451,7 +440,7 @@ static int e1000_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, uint8_t *bytes) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; int first_word, last_word; @@ -497,7 +486,7 @@ static int e1000_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, uint8_t *bytes) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; void *ptr; @@ -558,7 +547,7 @@ static void e1000_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; strncpy(drvinfo->driver, e1000_driver_name, 32); strncpy(drvinfo->version, e1000_driver_version, 32); @@ -574,7 +563,7 @@ static void e1000_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; struct e1000_desc_ring *rxdr = &adapter->rx_ring; @@ -595,7 +584,7 @@ static int e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; struct e1000_desc_ring *rxdr = &adapter->rx_ring; @@ -662,9 +651,6 @@ e1000_set_ringparam(struct net_device *netdev, E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ value = E1000_READ_REG(&adapter->hw, R); \ if(value != (test[pat] & W & M)) { \ - DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \ - "0x%08X expected 0x%08X\n", \ - E1000_##R, value, (test[pat] & W & M)); \ *data = (adapter->hw.mac_type < e1000_82543) ? \ E1000_82542_##R : E1000_##R; \ return 1; \ @@ -677,9 +663,7 @@ e1000_set_ringparam(struct net_device *netdev, uint32_t value; \ E1000_WRITE_REG(&adapter->hw, R, W & M); \ value = E1000_READ_REG(&adapter->hw, R); \ - if((W & M) != (value & M)) { \ - DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ - "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \ + if ((W & M) != (value & M)) { \ *data = (adapter->hw.mac_type < e1000_82543) ? \ E1000_82542_##R : E1000_##R; \ return 1; \ @@ -689,33 +673,18 @@ e1000_set_ringparam(struct net_device *netdev, static int e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) { - uint32_t value, before, after; - uint32_t i, toggle; + uint32_t value; + uint32_t i; /* The status register is Read Only, so a write should fail. * Some bits that get toggled are ignored. */ - switch (adapter->hw.mac_type) { - case e1000_82573: - toggle = 0x7FFFF033; - break; - default: - toggle = 0xFFFFF833; - break; - } - - before = E1000_READ_REG(&adapter->hw, STATUS); - value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle); - E1000_WRITE_REG(&adapter->hw, STATUS, toggle); - after = E1000_READ_REG(&adapter->hw, STATUS) & toggle; - if(value != after) { - DPRINTK(DRV, ERR, "failed STATUS register test got: " - "0x%08X expected: 0x%08X\n", after, value); + value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833)); + E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF)); + if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) { *data = 1; return 1; } - /* restore previous status */ - E1000_WRITE_REG(&adapter->hw, STATUS, before); REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF); REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF); @@ -797,7 +766,7 @@ e1000_test_intr(int irq, struct pt_regs *regs) { struct net_device *netdev = (struct net_device *) data; - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR); @@ -1245,7 +1214,6 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter) case e1000_82541_rev_2: case e1000_82547: case e1000_82547_rev_2: - case e1000_82573: return e1000_integrated_phy_loopback(adapter); break; @@ -1454,7 +1422,7 @@ static void e1000_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, uint64_t *data) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; boolean_t if_running = netif_running(netdev); if(eth_test->flags == ETH_TEST_FL_OFFLINE) { @@ -1514,7 +1482,7 @@ e1000_diag_test(struct net_device *netdev, static void e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1559,7 +1527,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1620,31 +1588,22 @@ e1000_led_blink_callback(unsigned long data) static int e1000_phys_id(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); - if(adapter->hw.mac_type < e1000_82573) { - if(!adapter->blink_timer.function) { - init_timer(&adapter->blink_timer); - adapter->blink_timer.function = e1000_led_blink_callback; - adapter->blink_timer.data = (unsigned long) adapter; - } - e1000_setup_led(&adapter->hw); - mod_timer(&adapter->blink_timer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&adapter->blink_timer); - } - else { - E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE | - E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK | - (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) | - (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) | - (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT))); - msleep_interruptible(data * 1000); + if(!adapter->blink_timer.function) { + init_timer(&adapter->blink_timer); + adapter->blink_timer.function = e1000_led_blink_callback; + adapter->blink_timer.data = (unsigned long) adapter; } + e1000_setup_led(&adapter->hw); + mod_timer(&adapter->blink_timer, jiffies); + + msleep_interruptible(data * 1000); + del_timer_sync(&adapter->blink_timer); e1000_led_off(&adapter->hw); clear_bit(E1000_LED_ON, &adapter->led_status); e1000_cleanup_led(&adapter->hw); @@ -1655,7 +1614,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data) static int e1000_nway_reset(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; if(netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); @@ -1673,7 +1632,7 @@ static void e1000_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, uint64_t *data) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; int i; e1000_update_stats(adapter); diff --git a/trunk/drivers/net/e1000/e1000_hw.c b/trunk/drivers/net/e1000/e1000_hw.c index 045f5426ab9a..723589b28be5 100644 --- a/trunk/drivers/net/e1000/e1000_hw.c +++ b/trunk/drivers/net/e1000/e1000_hw.c @@ -354,27 +354,18 @@ e1000_set_media_type(struct e1000_hw *hw) hw->media_type = e1000_media_type_internal_serdes; break; default: - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - hw->media_type = e1000_media_type_fiber; - break; - case e1000_82573: - /* The STATUS_TBIMODE bit is reserved or reused for the this - * device. - */ - hw->media_type = e1000_media_type_copper; - break; - default: + if(hw->mac_type >= e1000_82543) { status = E1000_READ_REG(hw, STATUS); - if (status & E1000_STATUS_TBIMODE) { + if(status & E1000_STATUS_TBIMODE) { hw->media_type = e1000_media_type_fiber; /* tbi_compatibility not valid on fiber */ hw->tbi_compatibility_en = FALSE; } else { hw->media_type = e1000_media_type_copper; } - break; + } else { + /* This is an 82542 (fiber only) */ + hw->media_type = e1000_media_type_fiber; } } } @@ -1198,9 +1189,9 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw) ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); if(ret_val) return ret_val; - } + } - return E1000_SUCCESS; + return E1000_SUCCESS; } diff --git a/trunk/drivers/net/e1000/e1000_hw.h b/trunk/drivers/net/e1000/e1000_hw.h index 93e9f8788751..a0263ee96c6b 100644 --- a/trunk/drivers/net/e1000/e1000_hw.h +++ b/trunk/drivers/net/e1000/e1000_hw.h @@ -66,7 +66,6 @@ typedef enum { e1000_eeprom_spi, e1000_eeprom_microwire, e1000_eeprom_flash, - e1000_eeprom_none, /* No NVM support */ e1000_num_eeprom_types } e1000_eeprom_type; diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c index cb7f051a60ad..137226d98d47 100644 --- a/trunk/drivers/net/e1000/e1000_main.c +++ b/trunk/drivers/net/e1000/e1000_main.c @@ -29,8 +29,6 @@ #include "e1000.h" /* Change Log - * 6.0.58 4/20/05 - * o Accepted ethtool cleanup patch from Stephen Hemminger * 6.0.44+ 2/15/05 * o applied Anton's patch to resolve tx hang in hardware * o Applied Andrew Mortons patch - e1000 stops working after resume @@ -43,9 +41,9 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "6.0.60-k2"DRIVERNAPI +#define DRV_VERSION "6.0.54-k2"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; -char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; +char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * @@ -519,7 +517,7 @@ e1000_probe(struct pci_dev *pdev, SET_NETDEV_DEV(netdev, &pdev->dev); pci_set_drvdata(pdev, netdev); - adapter = netdev_priv(netdev); + adapter = netdev->priv; adapter->netdev = netdev; adapter->pdev = pdev; adapter->hw.back = adapter; @@ -740,7 +738,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; uint32_t manc, swsm; flush_scheduled_work(); @@ -873,7 +871,7 @@ e1000_sw_init(struct e1000_adapter *adapter) static int e1000_open(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; int err; /* allocate transmit descriptors */ @@ -921,7 +919,7 @@ e1000_open(struct net_device *netdev) static int e1000_close(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; e1000_down(adapter); @@ -1601,7 +1599,7 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter) static int e1000_set_mac(struct net_device *netdev, void *p) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct sockaddr *addr = p; if(!is_valid_ether_addr(addr->sa_data)) @@ -1636,7 +1634,7 @@ e1000_set_mac(struct net_device *netdev, void *p) static void e1000_set_multi(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; struct dev_mc_list *mc_ptr; unsigned long flags; @@ -2215,7 +2213,7 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb) static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; unsigned int tx_flags = 0; @@ -2346,7 +2344,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) static void e1000_tx_timeout(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; /* Do the reset outside of interrupt context */ schedule_work(&adapter->tx_timeout_task); @@ -2355,7 +2353,7 @@ e1000_tx_timeout(struct net_device *netdev) static void e1000_tx_timeout_task(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; e1000_down(adapter); e1000_up(adapter); @@ -2372,7 +2370,7 @@ e1000_tx_timeout_task(struct net_device *netdev) static struct net_device_stats * e1000_get_stats(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; e1000_update_stats(adapter); return &adapter->net_stats; @@ -2389,7 +2387,7 @@ e1000_get_stats(struct net_device *netdev) static int e1000_change_mtu(struct net_device *netdev, int new_mtu) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || @@ -2600,7 +2598,7 @@ static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs) { struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; uint32_t icr = E1000_READ_REG(hw, ICR); #ifndef CONFIG_E1000_NAPI @@ -2663,7 +2661,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) static int e1000_clean(struct net_device *netdev, int *budget) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; int work_to_do = min(*budget, netdev->quota); int tx_cleaned; int work_done = 0; @@ -2674,8 +2672,8 @@ e1000_clean(struct net_device *netdev, int *budget) *budget -= work_done; netdev->quota -= work_done; + /* If no Tx and no Rx work done, exit the polling mode */ if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { - /* If no Tx and not enough Rx work done, exit the polling mode */ netif_rx_complete(netdev); e1000_irq_enable(adapter); return 0; @@ -2771,13 +2769,13 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) i = tx_ring->next_to_clean; eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); - DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" + DPRINTK(TX_ERR, ERR, "Detected Tx Unit Hang\n" " TDH <%x>\n" " TDT <%x>\n" " next_to_use <%x>\n" " next_to_clean <%x>\n" "buffer_info[next_to_clean]\n" - " dma <%zx>\n" + " dma <%llx>\n" " time_stamp <%lx>\n" " next_to_watch <%x>\n" " jiffies <%lx>\n" @@ -2996,7 +2994,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.middle.status_error); + staterr = rx_desc->wb.middle.status_error; while(staterr & E1000_RXD_STAT_DD) { buffer_info = &rx_ring->buffer_info[i]; @@ -3067,16 +3065,16 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) #ifdef CONFIG_E1000_NAPI if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->wb.middle.vlan) & - E1000_RXD_SPC_VLAN_MASK); + le16_to_cpu(rx_desc->wb.middle.vlan & + E1000_RXD_SPC_VLAN_MASK)); } else { netif_receive_skb(skb); } #else /* CONFIG_E1000_NAPI */ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { vlan_hwaccel_rx(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->wb.middle.vlan) & - E1000_RXD_SPC_VLAN_MASK); + le16_to_cpu(rx_desc->wb.middle.vlan & + E1000_RXD_SPC_VLAN_MASK)); } else { netif_rx(skb); } @@ -3089,7 +3087,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) if(unlikely(++i == rx_ring->count)) i = 0; rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.middle.status_error); + staterr = rx_desc->wb.middle.status_error; } rx_ring->next_to_clean = i; adapter->alloc_rx_buf(adapter); @@ -3373,12 +3371,11 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; struct mii_ioctl_data *data = if_mii(ifr); int retval; uint16_t mii_reg; uint16_t spddplx; - unsigned long flags; if(adapter->hw.media_type != e1000_media_type_copper) return -EOPNOTSUPP; @@ -3388,29 +3385,22 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) data->phy_id = adapter->hw.phy_addr; break; case SIOCGMIIREG: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_irqsave(&adapter->stats_lock, flags); - if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, - &data->val_out)) { - spin_unlock_irqrestore(&adapter->stats_lock, flags); + if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, + &data->val_out)) return -EIO; - } - spin_unlock_irqrestore(&adapter->stats_lock, flags); break; case SIOCSMIIREG: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - if(data->reg_num & ~(0x1F)) + if (data->reg_num & ~(0x1F)) return -EFAULT; mii_reg = data->val_in; - spin_lock_irqsave(&adapter->stats_lock, flags); - if(e1000_write_phy_reg(&adapter->hw, data->reg_num, - mii_reg)) { - spin_unlock_irqrestore(&adapter->stats_lock, flags); + if (e1000_write_phy_reg(&adapter->hw, data->reg_num, + mii_reg)) return -EIO; - } - if(adapter->hw.phy_type == e1000_phy_m88) { + if (adapter->hw.phy_type == e1000_phy_m88) { switch (data->reg_num) { case PHY_CTRL: if(mii_reg & MII_CR_POWER_DOWN) @@ -3430,12 +3420,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) HALF_DUPLEX; retval = e1000_set_spd_dplx(adapter, spddplx); - if(retval) { - spin_unlock_irqrestore( - &adapter->stats_lock, - flags); + if(retval) return retval; - } } if(netif_running(adapter->netdev)) { e1000_down(adapter); @@ -3445,11 +3431,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) break; case M88E1000_PHY_SPEC_CTRL: case M88E1000_EXT_PHY_SPEC_CTRL: - if(e1000_phy_reset(&adapter->hw)) { - spin_unlock_irqrestore( - &adapter->stats_lock, flags); + if (e1000_phy_reset(&adapter->hw)) return -EIO; - } break; } } else { @@ -3465,7 +3448,6 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) break; } } - spin_unlock_irqrestore(&adapter->stats_lock, flags); break; default: return -EOPNOTSUPP; @@ -3522,7 +3504,7 @@ e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value) static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; uint32_t ctrl, rctl; e1000_irq_disable(adapter); @@ -3562,7 +3544,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; uint32_t vfta, index; if((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && @@ -3578,7 +3560,7 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; uint32_t vfta, index; e1000_irq_disable(adapter); @@ -3619,13 +3601,6 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) { adapter->hw.autoneg = 0; - /* Fiber NICs only allow 1000 gbps Full duplex */ - if((adapter->hw.media_type == e1000_media_type_fiber) && - spddplx != (SPEED_1000 + DUPLEX_FULL)) { - DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; - } - switch(spddplx) { case SPEED_10 + DUPLEX_HALF: adapter->hw.forced_speed_duplex = e1000_10_half; @@ -3672,7 +3647,7 @@ static int e1000_suspend(struct pci_dev *pdev, uint32_t state) { struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; uint32_t wufc = adapter->wol; @@ -3765,12 +3740,12 @@ static int e1000_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - uint32_t manc, ret_val, swsm; + struct e1000_adapter *adapter = netdev->priv; + uint32_t manc, ret, swsm; pci_set_power_state(pdev, 0); pci_restore_state(pdev); - ret_val = pci_enable_device(pdev); + ret = pci_enable_device(pdev); pci_set_master(pdev); pci_enable_wake(pdev, 3, 0); @@ -3813,7 +3788,7 @@ e1000_resume(struct pci_dev *pdev) static void e1000_netpoll(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = netdev->priv; disable_irq(adapter->pdev->irq); e1000_intr(adapter->pdev->irq, netdev, NULL); enable_irq(adapter->pdev->irq); diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c index 64f0f697c958..4ebcd052e150 100644 --- a/trunk/drivers/net/forcedeth.c +++ b/trunk/drivers/net/forcedeth.c @@ -82,9 +82,6 @@ * 0.31: 14 Nov 2004: ethtool support for getting/setting link * capabilities. * 0.32: 16 Apr 2005: RX_ERROR4 handling added. - * 0.33: 16 May 2005: Support for MCP51 added. - * 0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics. - * 0.35: 26 Jun 2005: Support for MCP55 added. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -96,7 +93,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.35" +#define FORCEDETH_VERSION "0.32" #define DRV_NAME "forcedeth" #include @@ -2008,9 +2005,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i /* handle different descriptor versions */ if (pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 || pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 || - pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3 || - pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || - pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) + pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3) np->desc_ver = DESC_VER_1; else np->desc_ver = DESC_VER_2; @@ -2220,84 +2215,56 @@ static struct pci_device_id pci_tbl[] = { .device = PCI_DEVICE_ID_NVIDIA_NVENET_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, }, { /* nForce3 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_5, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, }, { /* nForce3 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_6, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, }, { /* nForce3 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_7, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, }, { /* CK804 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_8, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, }, { /* CK804 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_9, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, }, { /* MCP04 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_10, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, }, { /* MCP04 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_11, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, - }, - { /* MCP51 Ethernet Controller */ - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NVENET_12, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, - }, - { /* MCP51 Ethernet Controller */ - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NVENET_13, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, - }, - { /* MCP55 Ethernet Controller */ - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NVENET_14, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, - }, - { /* MCP55 Ethernet Controller */ - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NVENET_15, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, }, {0,}, }; diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c index 6518334b9280..b43b2b11aacd 100644 --- a/trunk/drivers/net/gianfar.c +++ b/trunk/drivers/net/gianfar.c @@ -1,4 +1,4 @@ -/* +/* * drivers/net/gianfar.c * * Gianfar Ethernet Driver @@ -22,9 +22,10 @@ * B-V +1.62 * * Theory of operation - * This driver is designed for the non-CPM ethernet controllers - * on the 85xx and 83xx family of integrated processors - * + * This driver is designed for the Triple-speed Ethernet + * controllers on the Freescale 8540/8560 integrated processors, + * as well as the Fast Ethernet Controller on the 8540. + * * The driver is initialized through platform_device. Structures which * define the configuration needed by the board are defined in a * board structure in arch/ppc/platforms (though I do not @@ -38,12 +39,12 @@ * * The Gianfar Ethernet Controller uses a ring of buffer * descriptors. The beginning is indicated by a register - * pointing to the physical address of the start of the ring. - * The end is determined by a "wrap" bit being set in the + * pointing to the physical address of the start of the ring. + * The end is determined by a "wrap" bit being set in the * last descriptor of the ring. * * When a packet is received, the RXF bit in the - * IEVENT register is set, triggering an interrupt when the + * IEVENT register is set, triggering an interrupt when the * corresponding bit in the IMASK register is also set (if * interrupt coalescing is active, then the interrupt may not * happen immediately, but will wait until either a set number @@ -51,7 +52,7 @@ * interrupt handler will signal there is work to be done, and * exit. Without NAPI, the packet(s) will be handled * immediately. Both methods will start at the last known empty - * descriptor, and process every subsequent descriptor until there + * descriptor, and process every subsequent descriptor until there * are none left with data (NAPI will stop after a set number of * packets to give time to other tasks, but will eventually * process all the packets). The data arrives inside a @@ -82,13 +83,9 @@ #include #include #include -#include #include #include #include -#include -#include -#include #include #include @@ -126,7 +123,7 @@ static int gfar_set_mac_address(struct net_device *dev); static int gfar_change_mtu(struct net_device *dev, int new_mtu); static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs); -static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs); +irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void gfar_phy_change(void *data); @@ -142,12 +139,9 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); #ifdef CONFIG_GFAR_NAPI static int gfar_poll(struct net_device *dev, int *budget); #endif -int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); +static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); static void gfar_phy_startup_timer(unsigned long data); -static void gfar_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp); -static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); extern struct ethtool_ops gfar_ethtool_ops; @@ -155,13 +149,6 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc"); MODULE_DESCRIPTION("Gianfar Ethernet Driver"); MODULE_LICENSE("GPL"); -int gfar_uses_fcb(struct gfar_private *priv) -{ - if (priv->vlan_enable || priv->rx_csum_enable) - return 1; - else - return 0; -} static int gfar_probe(struct device *device) { u32 tempval; @@ -172,6 +159,7 @@ static int gfar_probe(struct device *device) struct resource *r; int idx; int err = 0; + int dev_ethtool_ops = 0; einfo = (struct gianfar_platform_data *) pdev->dev.platform_data; @@ -277,69 +265,15 @@ static int gfar_probe(struct device *device) dev->mtu = 1500; dev->set_multicast_list = gfar_set_multi; - dev->ethtool_ops = &gfar_ethtool_ops; - - if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { - priv->rx_csum_enable = 1; - dev->features |= NETIF_F_IP_CSUM; - } else - priv->rx_csum_enable = 0; - - priv->vlgrp = NULL; + /* Index into the array of possible ethtool + * ops to catch all 4 possibilities */ + if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) == 0) + dev_ethtool_ops += 1; - if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { - dev->vlan_rx_register = gfar_vlan_rx_register; - dev->vlan_rx_kill_vid = gfar_vlan_rx_kill_vid; + if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE) == 0) + dev_ethtool_ops += 2; - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - - priv->vlan_enable = 1; - } - - if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { - priv->extended_hash = 1; - priv->hash_width = 9; - - priv->hash_regs[0] = &priv->regs->igaddr0; - priv->hash_regs[1] = &priv->regs->igaddr1; - priv->hash_regs[2] = &priv->regs->igaddr2; - priv->hash_regs[3] = &priv->regs->igaddr3; - priv->hash_regs[4] = &priv->regs->igaddr4; - priv->hash_regs[5] = &priv->regs->igaddr5; - priv->hash_regs[6] = &priv->regs->igaddr6; - priv->hash_regs[7] = &priv->regs->igaddr7; - priv->hash_regs[8] = &priv->regs->gaddr0; - priv->hash_regs[9] = &priv->regs->gaddr1; - priv->hash_regs[10] = &priv->regs->gaddr2; - priv->hash_regs[11] = &priv->regs->gaddr3; - priv->hash_regs[12] = &priv->regs->gaddr4; - priv->hash_regs[13] = &priv->regs->gaddr5; - priv->hash_regs[14] = &priv->regs->gaddr6; - priv->hash_regs[15] = &priv->regs->gaddr7; - - } else { - priv->extended_hash = 0; - priv->hash_width = 8; - - priv->hash_regs[0] = &priv->regs->gaddr0; - priv->hash_regs[1] = &priv->regs->gaddr1; - priv->hash_regs[2] = &priv->regs->gaddr2; - priv->hash_regs[3] = &priv->regs->gaddr3; - priv->hash_regs[4] = &priv->regs->gaddr4; - priv->hash_regs[5] = &priv->regs->gaddr5; - priv->hash_regs[6] = &priv->regs->gaddr6; - priv->hash_regs[7] = &priv->regs->gaddr7; - } - - if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_PADDING) - priv->padding = DEFAULT_PADDING; - else - priv->padding = 0; - - dev->hard_header_len += priv->padding; - - if (dev->features & NETIF_F_IP_CSUM) - dev->hard_header_len += GMAC_FCB_LEN; + dev->ethtool_ops = gfar_op_array[dev_ethtool_ops]; priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; #ifdef CONFIG_GFAR_BUFSTASH @@ -355,9 +289,6 @@ static int gfar_probe(struct device *device) priv->rxcount = DEFAULT_RXCOUNT; priv->rxtime = DEFAULT_RXTIME; - /* Enable most messages by default */ - priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; - err = register_netdev(dev); if (err) { @@ -429,9 +360,8 @@ static int init_phy(struct net_device *dev) GFP_KERNEL); if(NULL == mii_info) { - if (netif_msg_ifup(priv)) - printk(KERN_ERR "%s: Could not allocate mii_info\n", - dev->name); + printk(KERN_ERR "%s: Could not allocate mii_info\n", + dev->name); return -ENOMEM; } @@ -480,8 +410,7 @@ static int init_phy(struct net_device *dev) curphy = get_phy_info(priv->mii_info); if (curphy == NULL) { - if (netif_msg_ifup(priv)) - printk(KERN_ERR "%s: No PHY found\n", dev->name); + printk(KERN_ERR "%s: No PHY found\n", dev->name); err = -1; goto no_phy; } @@ -492,7 +421,7 @@ static int init_phy(struct net_device *dev) if(curphy->init) { err = curphy->init(priv->mii_info); - if (err) + if (err) goto phy_init_fail; } @@ -517,14 +446,14 @@ static void init_registers(struct net_device *dev) gfar_write(&priv->regs->imask, IMASK_INIT_CLEAR); /* Init hash registers to zero */ - gfar_write(&priv->regs->igaddr0, 0); - gfar_write(&priv->regs->igaddr1, 0); - gfar_write(&priv->regs->igaddr2, 0); - gfar_write(&priv->regs->igaddr3, 0); - gfar_write(&priv->regs->igaddr4, 0); - gfar_write(&priv->regs->igaddr5, 0); - gfar_write(&priv->regs->igaddr6, 0); - gfar_write(&priv->regs->igaddr7, 0); + gfar_write(&priv->regs->iaddr0, 0); + gfar_write(&priv->regs->iaddr1, 0); + gfar_write(&priv->regs->iaddr2, 0); + gfar_write(&priv->regs->iaddr3, 0); + gfar_write(&priv->regs->iaddr4, 0); + gfar_write(&priv->regs->iaddr5, 0); + gfar_write(&priv->regs->iaddr6, 0); + gfar_write(&priv->regs->iaddr7, 0); gfar_write(&priv->regs->gaddr0, 0); gfar_write(&priv->regs->gaddr1, 0); @@ -535,6 +464,9 @@ static void init_registers(struct net_device *dev) gfar_write(&priv->regs->gaddr6, 0); gfar_write(&priv->regs->gaddr7, 0); + /* Zero out rctrl */ + gfar_write(&priv->regs->rctrl, 0x00000000); + /* Zero out the rmon mib registers if it has them */ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { memset((void *) &(priv->regs->rmon), 0, @@ -565,14 +497,20 @@ static void init_registers(struct net_device *dev) gfar_write(&priv->regs->tbipa, TBIPA_VALUE); } - -/* Halt the receive and transmit queues */ -void gfar_halt(struct net_device *dev) +void stop_gfar(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); struct gfar *regs = priv->regs; + unsigned long flags; u32 tempval; + /* Lock it down */ + spin_lock_irqsave(&priv->lock, flags); + + /* Tell the kernel the link is down */ + priv->mii_info->link = 0; + adjust_link(dev); + /* Mask all interrupts */ gfar_write(®s->imask, IMASK_INIT_CLEAR); @@ -595,29 +533,13 @@ void gfar_halt(struct net_device *dev) tempval = gfar_read(®s->maccfg1); tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); gfar_write(®s->maccfg1, tempval); -} - -void stop_gfar(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar *regs = priv->regs; - unsigned long flags; - - /* Lock it down */ - spin_lock_irqsave(&priv->lock, flags); - - /* Tell the kernel the link is down */ - priv->mii_info->link = 0; - adjust_link(dev); - - gfar_halt(dev); if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { /* Clear any pending interrupts */ mii_clear_phy_interrupt(priv->mii_info); /* Disable PHY Interrupts */ - mii_configure_phy_interrupt(priv->mii_info, + mii_configure_phy_interrupt(priv->mii_info, MII_INTERRUPT_DISABLED); } @@ -644,7 +566,7 @@ void stop_gfar(struct net_device *dev) sizeof(struct txbd8)*priv->tx_ring_size + sizeof(struct rxbd8)*priv->rx_ring_size, priv->tx_bd_base, - gfar_read(®s->tbase0)); + gfar_read(®s->tbase)); } /* If there are any tx skbs or rx skbs still around, free them. @@ -698,34 +620,6 @@ void free_skb_resources(struct gfar_private *priv) } } -void gfar_start(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar *regs = priv->regs; - u32 tempval; - - /* Enable Rx and Tx in MACCFG1 */ - tempval = gfar_read(®s->maccfg1); - tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); - gfar_write(®s->maccfg1, tempval); - - /* Initialize DMACTRL to have WWR and WOP */ - tempval = gfar_read(&priv->regs->dmactrl); - tempval |= DMACTRL_INIT_SETTINGS; - gfar_write(&priv->regs->dmactrl, tempval); - - /* Clear THLT, so that the DMA starts polling now */ - gfar_write(®s->tstat, TSTAT_CLEAR_THALT); - - /* Make sure we aren't stopped */ - tempval = gfar_read(&priv->regs->dmactrl); - tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); - gfar_write(&priv->regs->dmactrl, tempval); - - /* Unmask the interrupts we look for */ - gfar_write(®s->imask, IMASK_DEFAULT); -} - /* Bring the controller up and running */ int startup_gfar(struct net_device *dev) { @@ -736,34 +630,33 @@ int startup_gfar(struct net_device *dev) int i; struct gfar_private *priv = netdev_priv(dev); struct gfar *regs = priv->regs; + u32 tempval; int err = 0; - u32 rctrl = 0; gfar_write(®s->imask, IMASK_INIT_CLEAR); /* Allocate memory for the buffer descriptors */ - vaddr = (unsigned long) dma_alloc_coherent(NULL, + vaddr = (unsigned long) dma_alloc_coherent(NULL, sizeof (struct txbd8) * priv->tx_ring_size + sizeof (struct rxbd8) * priv->rx_ring_size, &addr, GFP_KERNEL); if (vaddr == 0) { - if (netif_msg_ifup(priv)) - printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n", - dev->name); + printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n", + dev->name); return -ENOMEM; } priv->tx_bd_base = (struct txbd8 *) vaddr; /* enet DMA only understands physical addresses */ - gfar_write(®s->tbase0, addr); + gfar_write(®s->tbase, addr); /* Start the rx descriptor ring where the tx ring leaves off */ addr = addr + sizeof (struct txbd8) * priv->tx_ring_size; vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size; priv->rx_bd_base = (struct rxbd8 *) vaddr; - gfar_write(®s->rbase0, addr); + gfar_write(®s->rbase, addr); /* Setup the skbuff rings */ priv->tx_skbuff = @@ -771,9 +664,8 @@ int startup_gfar(struct net_device *dev) priv->tx_ring_size, GFP_KERNEL); if (priv->tx_skbuff == NULL) { - if (netif_msg_ifup(priv)) - printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", - dev->name); + printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", + dev->name); err = -ENOMEM; goto tx_skb_fail; } @@ -786,9 +678,8 @@ int startup_gfar(struct net_device *dev) priv->rx_ring_size, GFP_KERNEL); if (priv->rx_skbuff == NULL) { - if (netif_msg_ifup(priv)) - printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", - dev->name); + printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", + dev->name); err = -ENOMEM; goto rx_skb_fail; } @@ -835,13 +726,12 @@ int startup_gfar(struct net_device *dev) /* If the device has multiple interrupts, register for * them. Otherwise, only register for the one */ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - /* Install our interrupt handlers for Error, + /* Install our interrupt handlers for Error, * Transmit, and Receive */ if (request_irq(priv->interruptError, gfar_error, 0, "enet_error", dev) < 0) { - if (netif_msg_intr(priv)) - printk(KERN_ERR "%s: Can't get IRQ %d\n", - dev->name, priv->interruptError); + printk(KERN_ERR "%s: Can't get IRQ %d\n", + dev->name, priv->interruptError); err = -1; goto err_irq_fail; @@ -849,9 +739,8 @@ int startup_gfar(struct net_device *dev) if (request_irq(priv->interruptTransmit, gfar_transmit, 0, "enet_tx", dev) < 0) { - if (netif_msg_intr(priv)) - printk(KERN_ERR "%s: Can't get IRQ %d\n", - dev->name, priv->interruptTransmit); + printk(KERN_ERR "%s: Can't get IRQ %d\n", + dev->name, priv->interruptTransmit); err = -1; @@ -860,9 +749,8 @@ int startup_gfar(struct net_device *dev) if (request_irq(priv->interruptReceive, gfar_receive, 0, "enet_rx", dev) < 0) { - if (netif_msg_intr(priv)) - printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n", - dev->name, priv->interruptReceive); + printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n", + dev->name, priv->interruptReceive); err = -1; goto rx_irq_fail; @@ -870,9 +758,8 @@ int startup_gfar(struct net_device *dev) } else { if (request_irq(priv->interruptTransmit, gfar_interrupt, 0, "gfar_interrupt", dev) < 0) { - if (netif_msg_intr(priv)) - printk(KERN_ERR "%s: Can't get IRQ %d\n", - dev->name, priv->interruptError); + printk(KERN_ERR "%s: Can't get IRQ %d\n", + dev->name, priv->interruptError); err = -1; goto err_irq_fail; @@ -900,22 +787,28 @@ int startup_gfar(struct net_device *dev) else gfar_write(®s->rxic, 0); - if (priv->rx_csum_enable) - rctrl |= RCTRL_CHECKSUMMING; + init_waitqueue_head(&priv->rxcleanupq); - if (priv->extended_hash) - rctrl |= RCTRL_EXTHASH; + /* Enable Rx and Tx in MACCFG1 */ + tempval = gfar_read(®s->maccfg1); + tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); + gfar_write(®s->maccfg1, tempval); - if (priv->vlan_enable) - rctrl |= RCTRL_VLAN; + /* Initialize DMACTRL to have WWR and WOP */ + tempval = gfar_read(&priv->regs->dmactrl); + tempval |= DMACTRL_INIT_SETTINGS; + gfar_write(&priv->regs->dmactrl, tempval); - /* Init rctrl based on our settings */ - gfar_write(&priv->regs->rctrl, rctrl); + /* Clear THLT, so that the DMA starts polling now */ + gfar_write(®s->tstat, TSTAT_CLEAR_THALT); - if (dev->features & NETIF_F_IP_CSUM) - gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM); + /* Make sure we aren't stopped */ + tempval = gfar_read(&priv->regs->dmactrl); + tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); + gfar_write(&priv->regs->dmactrl, tempval); - gfar_start(dev); + /* Unmask the interrupts we look for */ + gfar_write(®s->imask, IMASK_DEFAULT); return 0; @@ -931,7 +824,7 @@ int startup_gfar(struct net_device *dev) sizeof(struct txbd8)*priv->tx_ring_size + sizeof(struct rxbd8)*priv->rx_ring_size, priv->tx_bd_base, - gfar_read(®s->tbase0)); + gfar_read(®s->tbase)); if (priv->mii_info->phyinfo->close) priv->mii_info->phyinfo->close(priv->mii_info); @@ -964,62 +857,11 @@ static int gfar_enet_open(struct net_device *dev) return err; } -static struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp) -{ - struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN); - - memset(fcb, 0, GMAC_FCB_LEN); - - /* Flag the bd so the controller looks for the FCB */ - bdp->status |= TXBD_TOE; - - return fcb; -} - -static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) -{ - int len; - - /* If we're here, it's a IP packet with a TCP or UDP - * payload. We set it to checksum, using a pseudo-header - * we provide - */ - fcb->ip = 1; - fcb->tup = 1; - fcb->ctu = 1; - fcb->nph = 1; - - /* Notify the controller what the protocol is */ - if (skb->nh.iph->protocol == IPPROTO_UDP) - fcb->udp = 1; - - /* l3os is the distance between the start of the - * frame (skb->data) and the start of the IP hdr. - * l4os is the distance between the start of the - * l3 hdr and the l4 hdr */ - fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN); - fcb->l4os = (u16)(skb->h.raw - skb->nh.raw); - - len = skb->nh.iph->tot_len - fcb->l4os; - - /* Provide the pseudoheader csum */ - fcb->phcs = ~csum_tcpudp_magic(skb->nh.iph->saddr, - skb->nh.iph->daddr, len, - skb->nh.iph->protocol, 0); -} - -void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb) -{ - fcb->vln = 1; - fcb->vlctl = vlan_tx_tag_get(skb); -} - /* This is called by the kernel when a frame is ready for transmission. */ /* It is pointed to by the dev->hard_start_xmit function pointer */ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct txfcb *fcb = NULL; struct txbd8 *txbdp; /* Update transmit stats */ @@ -1034,24 +876,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Clear all but the WRAP status flags */ txbdp->status &= TXBD_WRAP; - /* Set up checksumming */ - if ((dev->features & NETIF_F_IP_CSUM) - && (CHECKSUM_HW == skb->ip_summed)) { - fcb = gfar_add_fcb(skb, txbdp); - gfar_tx_checksum(skb, fcb); - } - - if (priv->vlan_enable && - unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) { - if (NULL == fcb) - fcb = gfar_add_fcb(skb, txbdp); - - gfar_tx_vlan(skb, fcb); - } - /* Set buffer length and pointer */ txbdp->length = skb->len; - txbdp->bufPtr = dma_map_single(NULL, skb->data, + txbdp->bufPtr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); /* Save the skb pointer so we can free it later */ @@ -1145,78 +972,15 @@ int gfar_set_mac_address(struct net_device *dev) } -/* Enables and disables VLAN insertion/extraction */ -static void gfar_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct gfar_private *priv = netdev_priv(dev); - unsigned long flags; - u32 tempval; - - spin_lock_irqsave(&priv->lock, flags); - - priv->vlgrp = grp; - - if (grp) { - /* Enable VLAN tag insertion */ - tempval = gfar_read(&priv->regs->tctrl); - tempval |= TCTRL_VLINS; - - gfar_write(&priv->regs->tctrl, tempval); - - /* Enable VLAN tag extraction */ - tempval = gfar_read(&priv->regs->rctrl); - tempval |= RCTRL_VLEX; - gfar_write(&priv->regs->rctrl, tempval); - } else { - /* Disable VLAN tag insertion */ - tempval = gfar_read(&priv->regs->tctrl); - tempval &= ~TCTRL_VLINS; - gfar_write(&priv->regs->tctrl, tempval); - - /* Disable VLAN tag extraction */ - tempval = gfar_read(&priv->regs->rctrl); - tempval &= ~RCTRL_VLEX; - gfar_write(&priv->regs->rctrl, tempval); - } - - spin_unlock_irqrestore(&priv->lock, flags); -} - - -static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) -{ - struct gfar_private *priv = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->vlgrp) - priv->vlgrp->vlan_devices[vid] = NULL; - - spin_unlock_irqrestore(&priv->lock, flags); -} - - static int gfar_change_mtu(struct net_device *dev, int new_mtu) { int tempsize, tempval; struct gfar_private *priv = netdev_priv(dev); int oldsize = priv->rx_buffer_size; - int frame_size = new_mtu + ETH_HLEN; - - if (priv->vlan_enable) - frame_size += VLAN_ETH_HLEN; - - if (gfar_uses_fcb(priv)) - frame_size += GMAC_FCB_LEN; - - frame_size += priv->padding; + int frame_size = new_mtu + 18; if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) { - if (netif_msg_drv(priv)) - printk(KERN_ERR "%s: Invalid MTU setting\n", - dev->name); + printk(KERN_ERR "%s: Invalid MTU setting\n", dev->name); return -EINVAL; } @@ -1356,7 +1120,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) skb->dev = dev; bdp->bufPtr = dma_map_single(NULL, skb->data, - priv->rx_buffer_size + RXBUF_ALIGNMENT, + priv->rx_buffer_size + RXBUF_ALIGNMENT, DMA_FROM_DEVICE); bdp->length = 0; @@ -1426,10 +1190,11 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) __netif_rx_schedule(dev); } else { - if (netif_msg_rx_err(priv)) - printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n", - dev->name, gfar_read(&priv->regs->ievent), - gfar_read(&priv->regs->imask)); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n", + dev->name, gfar_read(&priv->regs->ievent), + gfar_read(&priv->regs->imask)); +#endif } #else @@ -1444,43 +1209,15 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) else gfar_write(&priv->regs->rxic, 0); + /* Just in case we need to wake the ring param changer */ + priv->rxclean = 1; + spin_unlock(&priv->lock); #endif return IRQ_HANDLED; } -static inline int gfar_rx_vlan(struct sk_buff *skb, - struct vlan_group *vlgrp, unsigned short vlctl) -{ -#ifdef CONFIG_GFAR_NAPI - return vlan_hwaccel_receive_skb(skb, vlgrp, vlctl); -#else - return vlan_hwaccel_rx(skb, vlgrp, vlctl); -#endif -} - -static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb) -{ - /* If valid headers were found, and valid sums - * were verified, then we tell the kernel that no - * checksumming is necessary. Otherwise, it is */ - if (fcb->cip && !fcb->eip && fcb->ctu && !fcb->etu) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; -} - - -static inline struct rxfcb *gfar_get_fcb(struct sk_buff *skb) -{ - struct rxfcb *fcb = (struct rxfcb *)skb->data; - - /* Remove the FCB from the skb */ - skb_pull(skb, GMAC_FCB_LEN); - - return fcb; -} /* gfar_process_frame() -- handle one incoming packet if skb * isn't NULL. */ @@ -1488,51 +1225,35 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length) { struct gfar_private *priv = netdev_priv(dev); - struct rxfcb *fcb = NULL; if (skb == NULL) { - if (netif_msg_rx_err(priv)) - printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name); +#ifdef BRIEF_GFAR_ERRORS + printk(KERN_WARNING "%s: Missing skb!!.\n", + dev->name); +#endif priv->stats.rx_dropped++; priv->extra_stats.rx_skbmissing++; } else { - int ret; - /* Prep the skb for the packet */ skb_put(skb, length); - /* Grab the FCB if there is one */ - if (gfar_uses_fcb(priv)) - fcb = gfar_get_fcb(skb); - - /* Remove the padded bytes, if there are any */ - if (priv->padding) - skb_pull(skb, priv->padding); - - if (priv->rx_csum_enable) - gfar_rx_checksum(skb, fcb); - /* Tell the skb what kind of packet this is */ skb->protocol = eth_type_trans(skb, dev); /* Send the packet up the stack */ - if (unlikely(priv->vlgrp && fcb->vln)) - ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl); - else - ret = RECEIVE(skb); - - if (NET_RX_DROP == ret) + if (RECEIVE(skb) == NET_RX_DROP) { priv->extra_stats.kernel_dropped++; + } } return 0; } /* gfar_clean_rx_ring() -- Processes each frame in the rx ring - * until the budget/quota has been reached. Returns the number + * until the budget/quota has been reached. Returns the number * of frames handled */ -int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) +static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) { struct rxbd8 *bdp; struct sk_buff *skb; @@ -1634,6 +1355,9 @@ static int gfar_poll(struct net_device *dev, int *budget) mk_ic_value(priv->rxcount, priv->rxtime)); else gfar_write(&priv->regs->rxic, 0); + + /* Signal to the ring size changer that it's safe to go */ + priv->rxclean = 1; } return (rx_work_limit < 0) ? 1 : 0; @@ -1669,8 +1393,10 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (events & IEVENT_CRL) priv->stats.tx_aborted_errors++; if (events & IEVENT_XFUN) { - if (netif_msg_tx_err(priv)) - printk(KERN_WARNING "%s: tx underrun. dropped packet\n", dev->name); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_WARNING "%s: tx underrun. dropped packet\n", + dev->name); +#endif priv->stats.tx_dropped++; priv->extra_stats.tx_underrun++; @@ -1689,30 +1415,36 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); #endif - if (netif_msg_rx_err(priv)) - printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", - dev->name, - gfar_read(&priv->regs->rstat)); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name, + gfar_read(&priv->regs->rstat)); +#endif } if (events & IEVENT_BABR) { priv->stats.rx_errors++; priv->extra_stats.rx_babr++; - if (netif_msg_rx_err(priv)) - printk(KERN_DEBUG "%s: babbling error\n", dev->name); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: babbling error\n", dev->name); +#endif } if (events & IEVENT_EBERR) { priv->extra_stats.eberr++; - if (netif_msg_rx_err(priv)) - printk(KERN_DEBUG "%s: EBERR\n", dev->name); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: EBERR\n", dev->name); +#endif + } + if (events & IEVENT_RXC) { +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: control frame\n", dev->name); +#endif } - if ((events & IEVENT_RXC) && (netif_msg_rx_err(priv))) - printk(KERN_DEBUG "%s: control frame\n", dev->name); if (events & IEVENT_BABT) { priv->extra_stats.tx_babt++; - if (netif_msg_rx_err(priv)) - printk(KERN_DEBUG "%s: babt error\n", dev->name); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: babt error\n", dev->name); +#endif } return IRQ_HANDLED; @@ -1778,7 +1510,7 @@ static void gfar_phy_timer(unsigned long data) * If, after GFAR_AN_TIMEOUT seconds, it has not * finished, we switch to forced. * Either way, once the process has completed, we either - * request the interrupt, or switch the timer over to + * request the interrupt, or switch the timer over to * using gfar_phy_timer to check status */ static void gfar_phy_startup_timer(unsigned long data) { @@ -1803,9 +1535,8 @@ static void gfar_phy_startup_timer(unsigned long data) /* Forcing failed! Give up */ if(result) { - if (netif_msg_link(priv)) - printk(KERN_ERR "%s: Forcing failed!\n", - mii_info->dev->name); + printk(KERN_ERR "%s: Forcing failed!\n", + mii_info->dev->name); return; } } @@ -1815,17 +1546,16 @@ static void gfar_phy_startup_timer(unsigned long data) /* Grab the PHY interrupt, if necessary/possible */ if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { - if (request_irq(priv->einfo->interruptPHY, + if (request_irq(priv->einfo->interruptPHY, phy_interrupt, - SA_SHIRQ, - "phy_interrupt", + SA_SHIRQ, + "phy_interrupt", mii_info->dev) < 0) { - if (netif_msg_intr(priv)) - printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", - mii_info->dev->name, + printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", + mii_info->dev->name, priv->einfo->interruptPHY); } else { - mii_configure_phy_interrupt(priv->mii_info, + mii_configure_phy_interrupt(priv->mii_info, MII_INTERRUPT_ENABLED); return; } @@ -1862,17 +1592,15 @@ static void adjust_link(struct net_device *dev) tempval &= ~(MACCFG2_FULL_DUPLEX); gfar_write(®s->maccfg2, tempval); - if (netif_msg_link(priv)) - printk(KERN_INFO "%s: Half Duplex\n", - dev->name); + printk(KERN_INFO "%s: Half Duplex\n", + dev->name); } else { tempval = gfar_read(®s->maccfg2); tempval |= MACCFG2_FULL_DUPLEX; gfar_write(®s->maccfg2, tempval); - if (netif_msg_link(priv)) - printk(KERN_INFO "%s: Full Duplex\n", - dev->name); + printk(KERN_INFO "%s: Full Duplex\n", + dev->name); } priv->oldduplex = mii_info->duplex; @@ -1894,32 +1622,27 @@ static void adjust_link(struct net_device *dev) gfar_write(®s->maccfg2, tempval); break; default: - if (netif_msg_link(priv)) - printk(KERN_WARNING - "%s: Ack! Speed (%d) is not 10/100/1000!\n", - dev->name, mii_info->speed); + printk(KERN_WARNING + "%s: Ack! Speed (%d) is not 10/100/1000!\n", + dev->name, mii_info->speed); break; } - if (netif_msg_link(priv)) - printk(KERN_INFO "%s: Speed %dBT\n", dev->name, - mii_info->speed); + printk(KERN_INFO "%s: Speed %dBT\n", dev->name, + mii_info->speed); priv->oldspeed = mii_info->speed; } if (!priv->oldlink) { - if (netif_msg_link(priv)) - printk(KERN_INFO "%s: Link is up\n", dev->name); + printk(KERN_INFO "%s: Link is up\n", dev->name); priv->oldlink = 1; netif_carrier_on(dev); netif_schedule(dev); } } else { if (priv->oldlink) { - if (netif_msg_link(priv)) - printk(KERN_INFO "%s: Link is down\n", - dev->name); + printk(KERN_INFO "%s: Link is down\n", dev->name); priv->oldlink = 0; priv->oldspeed = 0; priv->oldduplex = -1; @@ -1941,9 +1664,8 @@ static void gfar_set_multi(struct net_device *dev) u32 tempval; if(dev->flags & IFF_PROMISC) { - if (netif_msg_drv(priv)) - printk(KERN_INFO "%s: Entering promiscuous mode.\n", - dev->name); + printk(KERN_INFO "%s: Entering promiscuous mode.\n", + dev->name); /* Set RCTRL to PROM */ tempval = gfar_read(®s->rctrl); tempval |= RCTRL_PROM; @@ -1957,14 +1679,6 @@ static void gfar_set_multi(struct net_device *dev) if(dev->flags & IFF_ALLMULTI) { /* Set the hash to rx all multicast frames */ - gfar_write(®s->igaddr0, 0xffffffff); - gfar_write(®s->igaddr1, 0xffffffff); - gfar_write(®s->igaddr2, 0xffffffff); - gfar_write(®s->igaddr3, 0xffffffff); - gfar_write(®s->igaddr4, 0xffffffff); - gfar_write(®s->igaddr5, 0xffffffff); - gfar_write(®s->igaddr6, 0xffffffff); - gfar_write(®s->igaddr7, 0xffffffff); gfar_write(®s->gaddr0, 0xffffffff); gfar_write(®s->gaddr1, 0xffffffff); gfar_write(®s->gaddr2, 0xffffffff); @@ -1975,14 +1689,6 @@ static void gfar_set_multi(struct net_device *dev) gfar_write(®s->gaddr7, 0xffffffff); } else { /* zero out the hash */ - gfar_write(®s->igaddr0, 0x0); - gfar_write(®s->igaddr1, 0x0); - gfar_write(®s->igaddr2, 0x0); - gfar_write(®s->igaddr3, 0x0); - gfar_write(®s->igaddr4, 0x0); - gfar_write(®s->igaddr5, 0x0); - gfar_write(®s->igaddr6, 0x0); - gfar_write(®s->igaddr7, 0x0); gfar_write(®s->gaddr0, 0x0); gfar_write(®s->gaddr1, 0x0); gfar_write(®s->gaddr2, 0x0); @@ -2021,15 +1727,16 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr) { u32 tempval; struct gfar_private *priv = netdev_priv(dev); + struct gfar *regs = priv->regs; + u32 *hash = ®s->gaddr0; u32 result = ether_crc(MAC_ADDR_LEN, addr); - int width = priv->hash_width; - u8 whichbit = (result >> (32 - width)) & 0x1f; - u8 whichreg = result >> (32 - width + 5); + u8 whichreg = ((result >> 29) & 0x7); + u8 whichbit = ((result >> 24) & 0x1f); u32 value = (1 << (31-whichbit)); - tempval = gfar_read(priv->hash_regs[whichreg]); + tempval = gfar_read(&hash[whichreg]); tempval |= value; - gfar_write(priv->hash_regs[whichreg], tempval); + gfar_write(&hash[whichreg], tempval); return; } @@ -2047,9 +1754,10 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK); /* Hmm... */ - if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv)) - printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n", - dev->name, events, gfar_read(&priv->regs->imask)); +#if defined (BRIEF_GFAR_ERRORS) || defined (VERBOSE_GFAR_ERRORS) + printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n", + dev->name, events, gfar_read(&priv->regs->imask)); +#endif /* Update the error counters */ if (events & IEVENT_TXE) { @@ -2060,17 +1768,19 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) if (events & IEVENT_CRL) priv->stats.tx_aborted_errors++; if (events & IEVENT_XFUN) { - if (netif_msg_tx_err(priv)) - printk(KERN_DEBUG "%s: underrun. packet dropped.\n", - dev->name); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: underrun. packet dropped.\n", + dev->name); +#endif priv->stats.tx_dropped++; priv->extra_stats.tx_underrun++; /* Reactivate the Tx Queues */ gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); } - if (netif_msg_tx_err(priv)) - printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); +#endif } if (events & IEVENT_BSY) { priv->stats.rx_errors++; @@ -2083,31 +1793,35 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); #endif - if (netif_msg_rx_err(priv)) - printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", - dev->name, - gfar_read(&priv->regs->rstat)); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name, + gfar_read(&priv->regs->rstat)); +#endif } if (events & IEVENT_BABR) { priv->stats.rx_errors++; priv->extra_stats.rx_babr++; - if (netif_msg_rx_err(priv)) - printk(KERN_DEBUG "%s: babbling error\n", dev->name); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: babbling error\n", dev->name); +#endif } if (events & IEVENT_EBERR) { priv->extra_stats.eberr++; - if (netif_msg_rx_err(priv)) - printk(KERN_DEBUG "%s: EBERR\n", dev->name); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: EBERR\n", dev->name); +#endif } - if ((events & IEVENT_RXC) && netif_msg_rx_status(priv)) - if (netif_msg_rx_status(priv)) - printk(KERN_DEBUG "%s: control frame\n", dev->name); + if (events & IEVENT_RXC) +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: control frame\n", dev->name); +#endif if (events & IEVENT_BABT) { priv->extra_stats.tx_babt++; - if (netif_msg_tx_err(priv)) - printk(KERN_DEBUG "%s: babt error\n", dev->name); +#ifdef VERBOSE_GFAR_ERRORS + printk(KERN_DEBUG "%s: babt error\n", dev->name); +#endif } return IRQ_HANDLED; } diff --git a/trunk/drivers/net/gianfar.h b/trunk/drivers/net/gianfar.h index 28af087d9fbb..c2f783a6a9fa 100644 --- a/trunk/drivers/net/gianfar.h +++ b/trunk/drivers/net/gianfar.h @@ -1,4 +1,4 @@ -/* +/* * drivers/net/gianfar.h * * Gianfar Ethernet Driver @@ -53,12 +53,6 @@ /* The maximum number of packets to be handled in one call of gfar_poll */ #define GFAR_DEV_WEIGHT 64 -/* Length for FCB */ -#define GMAC_FCB_LEN 8 - -/* Default padding amount */ -#define DEFAULT_PADDING 2 - /* Number of bytes to align the rx bufs to */ #define RXBUF_ALIGNMENT 64 @@ -97,7 +91,7 @@ extern const char gfar_driver_version[]; #define JUMBO_FRAME_SIZE 9600 /* Latency of interface clock in nanoseconds */ -/* Interface clock latency , in this case, means the +/* Interface clock latency , in this case, means the * time described by a value of 1 in the interrupt * coalescing registers' time fields. Since those fields * refer to the time it takes for 64 clocks to pass, the @@ -172,28 +166,9 @@ extern const char gfar_driver_version[]; mk_ic_icft(count) | \ mk_ic_ictt(time)) -#define RCTRL_PAL_MASK 0x001f0000 -#define RCTRL_VLEX 0x00002000 -#define RCTRL_FILREN 0x00001000 -#define RCTRL_GHTX 0x00000400 -#define RCTRL_IPCSEN 0x00000200 -#define RCTRL_TUCSEN 0x00000100 -#define RCTRL_PRSDEP_MASK 0x000000c0 -#define RCTRL_PRSDEP_INIT 0x000000c0 #define RCTRL_PROM 0x00000008 -#define RCTRL_CHECKSUMMING (RCTRL_IPCSEN \ - | RCTRL_TUCSEN | RCTRL_PRSDEP_INIT) -#define RCTRL_EXTHASH (RCTRL_GHTX) -#define RCTRL_VLAN (RCTRL_PRSDEP_INIT) - - #define RSTAT_CLEAR_RHALT 0x00800000 -#define TCTRL_IPCSEN 0x00004000 -#define TCTRL_TUCSEN 0x00002000 -#define TCTRL_VLINS 0x00001000 -#define TCTRL_INIT_CSUM (TCTRL_TUCSEN | TCTRL_IPCSEN) - #define IEVENT_INIT_CLEAR 0xffffffff #define IEVENT_BABR 0x80000000 #define IEVENT_RXC 0x40000000 @@ -212,16 +187,12 @@ extern const char gfar_driver_version[]; #define IEVENT_RXB0 0x00008000 #define IEVENT_GRSC 0x00000100 #define IEVENT_RXF0 0x00000080 -#define IEVENT_FIR 0x00000008 -#define IEVENT_FIQ 0x00000004 -#define IEVENT_DPE 0x00000002 -#define IEVENT_PERR 0x00000001 #define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0) #define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF) #define IEVENT_ERR_MASK \ (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \ IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \ - | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR) + | IEVENT_CRL | IEVENT_XFUN) #define IMASK_INIT_CLEAR 0x00000000 #define IMASK_BABR 0x80000000 @@ -241,15 +212,10 @@ extern const char gfar_driver_version[]; #define IMASK_RXB0 0x00008000 #define IMASK_GTSC 0x00000100 #define IMASK_RXFEN0 0x00000080 -#define IMASK_FIR 0x00000008 -#define IMASK_FIQ 0x00000004 -#define IMASK_DPE 0x00000002 -#define IMASK_PERR 0x00000001 #define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY) #define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \ IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \ - IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \ - | IMASK_PERR) + IMASK_XFUN | IMASK_RXC | IMASK_BABT) /* Attribute fields */ @@ -288,18 +254,6 @@ extern const char gfar_driver_version[]; #define TXBD_RETRYLIMIT 0x0040 #define TXBD_RETRYCOUNTMASK 0x003c #define TXBD_UNDERRUN 0x0002 -#define TXBD_TOE 0x0002 - -/* Tx FCB param bits */ -#define TXFCB_VLN 0x80 -#define TXFCB_IP 0x40 -#define TXFCB_IP6 0x20 -#define TXFCB_TUP 0x10 -#define TXFCB_UDP 0x08 -#define TXFCB_CIP 0x04 -#define TXFCB_CTU 0x02 -#define TXFCB_NPH 0x01 -#define TXFCB_DEFAULT (TXFCB_IP|TXFCB_TUP|TXFCB_CTU|TXFCB_NPH) /* RxBD status field bits */ #define RXBD_EMPTY 0x8000 @@ -319,18 +273,6 @@ extern const char gfar_driver_version[]; #define RXBD_TRUNCATED 0x0001 #define RXBD_STATS 0x01ff -/* Rx FCB status field bits */ -#define RXFCB_VLN 0x8000 -#define RXFCB_IP 0x4000 -#define RXFCB_IP6 0x2000 -#define RXFCB_TUP 0x1000 -#define RXFCB_CIP 0x0800 -#define RXFCB_CTU 0x0400 -#define RXFCB_EIP 0x0200 -#define RXFCB_ETU 0x0100 -#define RXFCB_PERR_MASK 0x000c -#define RXFCB_PERR_BADL3 0x0008 - struct txbd8 { u16 status; /* Status Fields */ @@ -338,22 +280,6 @@ struct txbd8 u32 bufPtr; /* Buffer Pointer */ }; -struct txfcb { - u8 vln:1, - ip:1, - ip6:1, - tup:1, - udp:1, - cip:1, - ctu:1, - nph:1; - u8 reserved; - u8 l4os; /* Level 4 Header Offset */ - u8 l3os; /* Level 3 Header Offset */ - u16 phcs; /* Pseudo-header Checksum */ - u16 vlctl; /* VLAN control word */ -}; - struct rxbd8 { u16 status; /* Status Fields */ @@ -361,21 +287,6 @@ struct rxbd8 u32 bufPtr; /* Buffer Pointer */ }; -struct rxfcb { - u16 vln:1, - ip:1, - ip6:1, - tup:1, - cip:1, - ctu:1, - eip:1, - etu:1; - u8 rq; /* Receive Queue index */ - u8 pro; /* Layer 4 Protocol */ - u16 reserved; - u16 vlctl; /* VLAN control word */ -}; - struct rmon_mib { u32 tr64; /* 0x.680 - Transmit and Receive 64-byte Frame Counter */ @@ -460,191 +371,90 @@ struct gfar_stats { struct gfar { - u32 tsec_id; /* 0x.000 - Controller ID register */ - u8 res1[12]; - u32 ievent; /* 0x.010 - Interrupt Event Register */ - u32 imask; /* 0x.014 - Interrupt Mask Register */ - u32 edis; /* 0x.018 - Error Disabled Register */ + u8 res1[16]; + u32 ievent; /* 0x.010 - Interrupt Event Register */ + u32 imask; /* 0x.014 - Interrupt Mask Register */ + u32 edis; /* 0x.018 - Error Disabled Register */ u8 res2[4]; - u32 ecntrl; /* 0x.020 - Ethernet Control Register */ - u32 minflr; /* 0x.024 - Minimum Frame Length Register */ - u32 ptv; /* 0x.028 - Pause Time Value Register */ - u32 dmactrl; /* 0x.02c - DMA Control Register */ - u32 tbipa; /* 0x.030 - TBI PHY Address Register */ + u32 ecntrl; /* 0x.020 - Ethernet Control Register */ + u32 minflr; /* 0x.024 - Minimum Frame Length Register */ + u32 ptv; /* 0x.028 - Pause Time Value Register */ + u32 dmactrl; /* 0x.02c - DMA Control Register */ + u32 tbipa; /* 0x.030 - TBI PHY Address Register */ u8 res3[88]; - u32 fifo_tx_thr; /* 0x.08c - FIFO transmit threshold register */ + u32 fifo_tx_thr; /* 0x.08c - FIFO transmit threshold register */ u8 res4[8]; - u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */ + u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */ u32 fifo_tx_starve_shutoff; /* 0x.09c - FIFO transmit starve shutoff register */ - u8 res5[4]; - u32 fifo_rx_pause; /* 0x.0a4 - FIFO receive pause threshold register */ - u32 fifo_rx_alarm; /* 0x.0a8 - FIFO receive alarm threshold register */ - u8 res6[84]; - u32 tctrl; /* 0x.100 - Transmit Control Register */ - u32 tstat; /* 0x.104 - Transmit Status Register */ - u32 dfvlan; /* 0x.108 - Default VLAN Control word */ - u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */ - u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */ - u32 tqueue; /* 0x.114 - Transmit queue control register */ - u8 res7[40]; - u32 tr03wt; /* 0x.140 - TxBD Rings 0-3 round-robin weightings */ - u32 tr47wt; /* 0x.144 - TxBD Rings 4-7 round-robin weightings */ - u8 res8[52]; - u32 tbdbph; /* 0x.17c - Tx data buffer pointer high */ - u8 res9a[4]; - u32 tbptr0; /* 0x.184 - TxBD Pointer for ring 0 */ - u8 res9b[4]; - u32 tbptr1; /* 0x.18c - TxBD Pointer for ring 1 */ - u8 res9c[4]; - u32 tbptr2; /* 0x.194 - TxBD Pointer for ring 2 */ - u8 res9d[4]; - u32 tbptr3; /* 0x.19c - TxBD Pointer for ring 3 */ - u8 res9e[4]; - u32 tbptr4; /* 0x.1a4 - TxBD Pointer for ring 4 */ - u8 res9f[4]; - u32 tbptr5; /* 0x.1ac - TxBD Pointer for ring 5 */ - u8 res9g[4]; - u32 tbptr6; /* 0x.1b4 - TxBD Pointer for ring 6 */ - u8 res9h[4]; - u32 tbptr7; /* 0x.1bc - TxBD Pointer for ring 7 */ - u8 res9[64]; - u32 tbaseh; /* 0x.200 - TxBD base address high */ - u32 tbase0; /* 0x.204 - TxBD Base Address of ring 0 */ - u8 res10a[4]; - u32 tbase1; /* 0x.20c - TxBD Base Address of ring 1 */ - u8 res10b[4]; - u32 tbase2; /* 0x.214 - TxBD Base Address of ring 2 */ - u8 res10c[4]; - u32 tbase3; /* 0x.21c - TxBD Base Address of ring 3 */ - u8 res10d[4]; - u32 tbase4; /* 0x.224 - TxBD Base Address of ring 4 */ - u8 res10e[4]; - u32 tbase5; /* 0x.22c - TxBD Base Address of ring 5 */ - u8 res10f[4]; - u32 tbase6; /* 0x.234 - TxBD Base Address of ring 6 */ - u8 res10g[4]; - u32 tbase7; /* 0x.23c - TxBD Base Address of ring 7 */ - u8 res10[192]; - u32 rctrl; /* 0x.300 - Receive Control Register */ - u32 rstat; /* 0x.304 - Receive Status Register */ - u8 res12[8]; - u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */ - u32 rqueue; /* 0x.314 - Receive queue control register */ - u8 res13[24]; - u32 rbifx; /* 0x.330 - Receive bit field extract control register */ - u32 rqfar; /* 0x.334 - Receive queue filing table address register */ - u32 rqfcr; /* 0x.338 - Receive queue filing table control register */ - u32 rqfpr; /* 0x.33c - Receive queue filing table property register */ - u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */ - u8 res14[56]; - u32 rbdbph; /* 0x.37c - Rx data buffer pointer high */ - u8 res15a[4]; - u32 rbptr0; /* 0x.384 - RxBD pointer for ring 0 */ - u8 res15b[4]; - u32 rbptr1; /* 0x.38c - RxBD pointer for ring 1 */ - u8 res15c[4]; - u32 rbptr2; /* 0x.394 - RxBD pointer for ring 2 */ - u8 res15d[4]; - u32 rbptr3; /* 0x.39c - RxBD pointer for ring 3 */ - u8 res15e[4]; - u32 rbptr4; /* 0x.3a4 - RxBD pointer for ring 4 */ - u8 res15f[4]; - u32 rbptr5; /* 0x.3ac - RxBD pointer for ring 5 */ - u8 res15g[4]; - u32 rbptr6; /* 0x.3b4 - RxBD pointer for ring 6 */ - u8 res15h[4]; - u32 rbptr7; /* 0x.3bc - RxBD pointer for ring 7 */ - u8 res16[64]; - u32 rbaseh; /* 0x.400 - RxBD base address high */ - u32 rbase0; /* 0x.404 - RxBD base address of ring 0 */ - u8 res17a[4]; - u32 rbase1; /* 0x.40c - RxBD base address of ring 1 */ - u8 res17b[4]; - u32 rbase2; /* 0x.414 - RxBD base address of ring 2 */ - u8 res17c[4]; - u32 rbase3; /* 0x.41c - RxBD base address of ring 3 */ - u8 res17d[4]; - u32 rbase4; /* 0x.424 - RxBD base address of ring 4 */ - u8 res17e[4]; - u32 rbase5; /* 0x.42c - RxBD base address of ring 5 */ - u8 res17f[4]; - u32 rbase6; /* 0x.434 - RxBD base address of ring 6 */ - u8 res17g[4]; - u32 rbase7; /* 0x.43c - RxBD base address of ring 7 */ - u8 res17[192]; - u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */ - u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */ - u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */ - u32 hafdup; /* 0x.50c - Half Duplex Register */ - u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */ + u8 res5[96]; + u32 tctrl; /* 0x.100 - Transmit Control Register */ + u32 tstat; /* 0x.104 - Transmit Status Register */ + u8 res6[4]; + u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */ + u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */ + u8 res7[16]; + u32 ctbptr; /* 0x.124 - Current Transmit Buffer Descriptor Pointer Register */ + u8 res8[92]; + u32 tbptr; /* 0x.184 - Transmit Buffer Descriptor Pointer Low Register */ + u8 res9[124]; + u32 tbase; /* 0x.204 - Transmit Descriptor Base Address Register */ + u8 res10[168]; + u32 ostbd; /* 0x.2b0 - Out-of-Sequence Transmit Buffer Descriptor Register */ + u32 ostbdp; /* 0x.2b4 - Out-of-Sequence Transmit Data Buffer Pointer Register */ + u8 res11[72]; + u32 rctrl; /* 0x.300 - Receive Control Register */ + u32 rstat; /* 0x.304 - Receive Status Register */ + u8 res12[4]; + u32 rbdlen; /* 0x.30c - RxBD Data Length Register */ + u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */ + u8 res13[16]; + u32 crbptr; /* 0x.324 - Current Receive Buffer Descriptor Pointer */ + u8 res14[24]; + u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */ + u8 res15[64]; + u32 rbptr; /* 0x.384 - Receive Buffer Descriptor Pointer */ + u8 res16[124]; + u32 rbase; /* 0x.404 - Receive Descriptor Base Address */ + u8 res17[248]; + u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */ + u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */ + u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */ + u32 hafdup; /* 0x.50c - Half Duplex Register */ + u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */ u8 res18[12]; - u32 miimcfg; /* 0x.520 - MII Management Configuration Register */ - u32 miimcom; /* 0x.524 - MII Management Command Register */ - u32 miimadd; /* 0x.528 - MII Management Address Register */ - u32 miimcon; /* 0x.52c - MII Management Control Register */ - u32 miimstat; /* 0x.530 - MII Management Status Register */ - u32 miimind; /* 0x.534 - MII Management Indicator Register */ + u32 miimcfg; /* 0x.520 - MII Management Configuration Register */ + u32 miimcom; /* 0x.524 - MII Management Command Register */ + u32 miimadd; /* 0x.528 - MII Management Address Register */ + u32 miimcon; /* 0x.52c - MII Management Control Register */ + u32 miimstat; /* 0x.530 - MII Management Status Register */ + u32 miimind; /* 0x.534 - MII Management Indicator Register */ u8 res19[4]; - u32 ifstat; /* 0x.53c - Interface Status Register */ - u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ - u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */ - u32 mac01addr1; /* 0x.548 - MAC exact match address 1, part 1 */ - u32 mac01addr2; /* 0x.54c - MAC exact match address 1, part 2 */ - u32 mac02addr1; /* 0x.550 - MAC exact match address 2, part 1 */ - u32 mac02addr2; /* 0x.554 - MAC exact match address 2, part 2 */ - u32 mac03addr1; /* 0x.558 - MAC exact match address 3, part 1 */ - u32 mac03addr2; /* 0x.55c - MAC exact match address 3, part 2 */ - u32 mac04addr1; /* 0x.560 - MAC exact match address 4, part 1 */ - u32 mac04addr2; /* 0x.564 - MAC exact match address 4, part 2 */ - u32 mac05addr1; /* 0x.568 - MAC exact match address 5, part 1 */ - u32 mac05addr2; /* 0x.56c - MAC exact match address 5, part 2 */ - u32 mac06addr1; /* 0x.570 - MAC exact match address 6, part 1 */ - u32 mac06addr2; /* 0x.574 - MAC exact match address 6, part 2 */ - u32 mac07addr1; /* 0x.578 - MAC exact match address 7, part 1 */ - u32 mac07addr2; /* 0x.57c - MAC exact match address 7, part 2 */ - u32 mac08addr1; /* 0x.580 - MAC exact match address 8, part 1 */ - u32 mac08addr2; /* 0x.584 - MAC exact match address 8, part 2 */ - u32 mac09addr1; /* 0x.588 - MAC exact match address 9, part 1 */ - u32 mac09addr2; /* 0x.58c - MAC exact match address 9, part 2 */ - u32 mac10addr1; /* 0x.590 - MAC exact match address 10, part 1*/ - u32 mac10addr2; /* 0x.594 - MAC exact match address 10, part 2*/ - u32 mac11addr1; /* 0x.598 - MAC exact match address 11, part 1*/ - u32 mac11addr2; /* 0x.59c - MAC exact match address 11, part 2*/ - u32 mac12addr1; /* 0x.5a0 - MAC exact match address 12, part 1*/ - u32 mac12addr2; /* 0x.5a4 - MAC exact match address 12, part 2*/ - u32 mac13addr1; /* 0x.5a8 - MAC exact match address 13, part 1*/ - u32 mac13addr2; /* 0x.5ac - MAC exact match address 13, part 2*/ - u32 mac14addr1; /* 0x.5b0 - MAC exact match address 14, part 1*/ - u32 mac14addr2; /* 0x.5b4 - MAC exact match address 14, part 2*/ - u32 mac15addr1; /* 0x.5b8 - MAC exact match address 15, part 1*/ - u32 mac15addr2; /* 0x.5bc - MAC exact match address 15, part 2*/ - u8 res20[192]; - struct rmon_mib rmon; /* 0x.680-0x.73c */ - u32 rrej; /* 0x.740 - Receive filer rejected packet counter */ - u8 res21[188]; - u32 igaddr0; /* 0x.800 - Indivdual/Group address register 0*/ - u32 igaddr1; /* 0x.804 - Indivdual/Group address register 1*/ - u32 igaddr2; /* 0x.808 - Indivdual/Group address register 2*/ - u32 igaddr3; /* 0x.80c - Indivdual/Group address register 3*/ - u32 igaddr4; /* 0x.810 - Indivdual/Group address register 4*/ - u32 igaddr5; /* 0x.814 - Indivdual/Group address register 5*/ - u32 igaddr6; /* 0x.818 - Indivdual/Group address register 6*/ - u32 igaddr7; /* 0x.81c - Indivdual/Group address register 7*/ + u32 ifstat; /* 0x.53c - Interface Status Register */ + u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ + u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */ + u8 res20[312]; + struct rmon_mib rmon; + u8 res21[192]; + u32 iaddr0; /* 0x.800 - Indivdual address register 0 */ + u32 iaddr1; /* 0x.804 - Indivdual address register 1 */ + u32 iaddr2; /* 0x.808 - Indivdual address register 2 */ + u32 iaddr3; /* 0x.80c - Indivdual address register 3 */ + u32 iaddr4; /* 0x.810 - Indivdual address register 4 */ + u32 iaddr5; /* 0x.814 - Indivdual address register 5 */ + u32 iaddr6; /* 0x.818 - Indivdual address register 6 */ + u32 iaddr7; /* 0x.81c - Indivdual address register 7 */ u8 res22[96]; - u32 gaddr0; /* 0x.880 - Group address register 0 */ - u32 gaddr1; /* 0x.884 - Group address register 1 */ - u32 gaddr2; /* 0x.888 - Group address register 2 */ - u32 gaddr3; /* 0x.88c - Group address register 3 */ - u32 gaddr4; /* 0x.890 - Group address register 4 */ - u32 gaddr5; /* 0x.894 - Group address register 5 */ - u32 gaddr6; /* 0x.898 - Group address register 6 */ - u32 gaddr7; /* 0x.89c - Group address register 7 */ - u8 res23a[352]; - u32 fifocfg; /* 0x.a00 - FIFO interface config register */ - u8 res23b[252]; - u8 res23c[248]; - u32 attr; /* 0x.bf8 - Attributes Register */ - u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */ + u32 gaddr0; /* 0x.880 - Global address register 0 */ + u32 gaddr1; /* 0x.884 - Global address register 1 */ + u32 gaddr2; /* 0x.888 - Global address register 2 */ + u32 gaddr3; /* 0x.88c - Global address register 3 */ + u32 gaddr4; /* 0x.890 - Global address register 4 */ + u32 gaddr5; /* 0x.894 - Global address register 5 */ + u32 gaddr6; /* 0x.898 - Global address register 6 */ + u32 gaddr7; /* 0x.89c - Global address register 7 */ + u8 res23[856]; + u32 attr; /* 0x.bf8 - Attributes Register */ + u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */ u8 res24[1024]; }; @@ -686,8 +496,6 @@ struct gfar_private { struct txbd8 *cur_tx; /* Next free ring entry */ struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ - u32 *hash_regs[16]; - int hash_width; struct gfar *phyregs; struct work_struct tq; struct timer_list phy_info_timer; @@ -698,12 +506,9 @@ struct gfar_private { unsigned int rx_stash_size; unsigned int tx_ring_size; unsigned int rx_ring_size; + wait_queue_head_t rxcleanupq; + unsigned int rxclean; - unsigned char vlan_enable:1, - rx_csum_enable:1, - extended_hash:1; - unsigned short padding; - struct vlan_group *vlgrp; /* Info structure initialized by board setup code */ unsigned int interruptTransmit; unsigned int interruptReceive; @@ -714,8 +519,6 @@ struct gfar_private { int oldspeed; int oldduplex; int oldlink; - - uint32_t msg_enable; }; extern inline u32 gfar_read(volatile unsigned *addr) diff --git a/trunk/drivers/net/gianfar_ethtool.c b/trunk/drivers/net/gianfar_ethtool.c index a451de629197..28046e9e88ba 100644 --- a/trunk/drivers/net/gianfar_ethtool.c +++ b/trunk/drivers/net/gianfar_ethtool.c @@ -46,18 +46,16 @@ extern int startup_gfar(struct net_device *dev); extern void stop_gfar(struct net_device *dev); -extern void gfar_halt(struct net_device *dev); -extern void gfar_start(struct net_device *dev); -extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); +extern void gfar_receive(int irq, void *dev_id, struct pt_regs *regs); -static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, +void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf); -static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); -static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); -static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); -static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals); -static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); -static void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); +void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); +int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); +int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); +void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals); +int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); +void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); static char stat_gstrings[][ETH_GSTRING_LEN] = { "rx-dropped-by-kernel", @@ -120,56 +118,57 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = { "tx-fragmented-frames", }; -/* Fill in a buffer with the strings which correspond to the - * stats */ -static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) -{ - struct gfar_private *priv = netdev_priv(dev); - - if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) - memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); - else - memcpy(buf, stat_gstrings, - GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN); -} - /* Fill in an array of 64-bit statistics from various sources. * This array will be appended to the end of the ethtool_stats * structure, and returned to user space */ -static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) +void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) { int i; struct gfar_private *priv = netdev_priv(dev); + u32 *rmon = (u32 *) & priv->regs->rmon; u64 *extra = (u64 *) & priv->extra_stats; + struct gfar_stats *stats = (struct gfar_stats *) buf; - if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { - u32 *rmon = (u32 *) & priv->regs->rmon; - struct gfar_stats *stats = (struct gfar_stats *) buf; - - for (i = 0; i < GFAR_RMON_LEN; i++) - stats->rmon[i] = (u64) (rmon[i]); + for (i = 0; i < GFAR_RMON_LEN; i++) { + stats->rmon[i] = (u64) (rmon[i]); + } - for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) - stats->extra[i] = extra[i]; - } else - for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) - buf[i] = extra[i]; + for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) { + stats->extra[i] = extra[i]; + } } /* Returns the number of stats (and their corresponding strings) */ -static int gfar_stats_count(struct net_device *dev) +int gfar_stats_count(struct net_device *dev) +{ + return GFAR_STATS_LEN; +} + +void gfar_gstrings_normon(struct net_device *dev, u32 stringset, u8 * buf) +{ + memcpy(buf, stat_gstrings, GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN); +} + +void gfar_fill_stats_normon(struct net_device *dev, + struct ethtool_stats *dummy, u64 * buf) { + int i; struct gfar_private *priv = netdev_priv(dev); + u64 *extra = (u64 *) & priv->extra_stats; - if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) - return GFAR_STATS_LEN; - else - return GFAR_EXTRA_STATS_LEN; + for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) { + buf[i] = extra[i]; + } } + +int gfar_stats_count_normon(struct net_device *dev) +{ + return GFAR_EXTRA_STATS_LEN; +} /* Fills in the drvinfo structure with some basic info */ -static void gfar_gdrvinfo(struct net_device *dev, struct +void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN); @@ -183,7 +182,7 @@ static void gfar_gdrvinfo(struct net_device *dev, struct } /* Return the current settings in the ethtool_cmd structure */ -static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) +int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) { struct gfar_private *priv = netdev_priv(dev); uint gigabit_support = @@ -217,13 +216,13 @@ static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) } /* Return the length of the register structure */ -static int gfar_reglen(struct net_device *dev) +int gfar_reglen(struct net_device *dev) { return sizeof (struct gfar); } /* Return a dump of the GFAR register space */ -static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) +void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) { int i; struct gfar_private *priv = netdev_priv(dev); @@ -234,6 +233,13 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi buf[i] = theregs[i]; } +/* Fill in a buffer with the strings which correspond to the + * stats */ +void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) +{ + memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); +} + /* Convert microseconds to ethernet clock ticks, which changes * depending on what speed the controller is running at */ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs) @@ -285,12 +291,9 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic /* Get the coalescing parameters, and put them in the cvals * structure. */ -static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) +int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) { struct gfar_private *priv = netdev_priv(dev); - - if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) - return -EOPNOTSUPP; cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime); cvals->rx_max_coalesced_frames = priv->rxcount; @@ -334,13 +337,10 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals * Both cvals->*_usecs and cvals->*_frames have to be > 0 * in order for coalescing to be active */ -static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) +int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) { struct gfar_private *priv = netdev_priv(dev); - if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) - return -EOPNOTSUPP; - /* Set up rx coalescing */ if ((cvals->rx_coalesce_usecs == 0) || (cvals->rx_max_coalesced_frames == 0)) @@ -379,7 +379,7 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals /* Fills in rvals with the current ring parameters. Currently, * rx, rx_mini, and rx_jumbo rings are the same size, as mini and * jumbo are ignored by the driver */ -static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) +void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) { struct gfar_private *priv = netdev_priv(dev); @@ -401,8 +401,9 @@ static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rv * necessary so that we don't mess things up while we're in * motion. We wait for the ring to be clean before reallocating * the rings. */ -static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) +int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) { + u32 tempval; struct gfar_private *priv = netdev_priv(dev); int err = 0; @@ -424,54 +425,37 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva return -EINVAL; } - if (dev->flags & IFF_UP) { - unsigned long flags; - - /* Halt TX and RX, and process the frames which - * have already been received */ - spin_lock_irqsave(&priv->lock, flags); - gfar_halt(dev); - gfar_clean_rx_ring(dev, priv->rx_ring_size); - spin_unlock_irqrestore(&priv->lock, flags); + /* Stop the controller so we don't rx any more frames */ + /* But first, make sure we clear the bits */ + tempval = gfar_read(&priv->regs->dmactrl); + tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); + gfar_write(&priv->regs->dmactrl, tempval); - /* Now we take down the rings to rebuild them */ - stop_gfar(dev); - } - - /* Change the size */ - priv->rx_ring_size = rvals->rx_pending; - priv->tx_ring_size = rvals->tx_pending; + tempval = gfar_read(&priv->regs->dmactrl); + tempval |= (DMACTRL_GRS | DMACTRL_GTS); + gfar_write(&priv->regs->dmactrl, tempval); - /* Rebuild the rings with the new size */ - if (dev->flags & IFF_UP) - err = startup_gfar(dev); + while (!(gfar_read(&priv->regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))) + cpu_relax(); - return err; -} - -static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) -{ - struct gfar_private *priv = netdev_priv(dev); - int err = 0; - - if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) - return -EOPNOTSUPP; + /* Note that rx is not clean right now */ + priv->rxclean = 0; if (dev->flags & IFF_UP) { - unsigned long flags; + /* Tell the driver to process the rest of the frames */ + gfar_receive(0, (void *) dev, NULL); + + /* Now wait for it to be done */ + wait_event_interruptible(priv->rxcleanupq, priv->rxclean); - /* Halt TX and RX, and process the frames which - * have already been received */ - spin_lock_irqsave(&priv->lock, flags); - gfar_halt(dev); - gfar_clean_rx_ring(dev, priv->rx_ring_size); - spin_unlock_irqrestore(&priv->lock, flags); + /* Ok, all packets have been handled. Now we bring it down, + * change the ring size, and bring it up */ - /* Now we take down the rings to rebuild them */ stop_gfar(dev); } - priv->rx_csum_enable = data; + priv->rx_ring_size = rvals->rx_pending; + priv->tx_ring_size = rvals->tx_pending; if (dev->flags & IFF_UP) err = startup_gfar(dev); @@ -479,61 +463,6 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) return err; } -static uint32_t gfar_get_rx_csum(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - - if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) - return 0; - - return priv->rx_csum_enable; -} - -static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) -{ - unsigned long flags; - struct gfar_private *priv = netdev_priv(dev); - - if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) - return -EOPNOTSUPP; - - spin_lock_irqsave(&priv->lock, flags); - gfar_halt(dev); - - if (data) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features &= ~NETIF_F_IP_CSUM; - - gfar_start(dev); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static uint32_t gfar_get_tx_csum(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - - if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) - return 0; - - return (dev->features & NETIF_F_IP_CSUM) != 0; -} - -static uint32_t gfar_get_msglevel(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - return priv->msg_enable; -} - -static void gfar_set_msglevel(struct net_device *dev, uint32_t data) -{ - struct gfar_private *priv = netdev_priv(dev); - priv->msg_enable = data; -} - - struct ethtool_ops gfar_ethtool_ops = { .get_settings = gfar_gsettings, .get_drvinfo = gfar_gdrvinfo, @@ -547,10 +476,52 @@ struct ethtool_ops gfar_ethtool_ops = { .get_strings = gfar_gstrings, .get_stats_count = gfar_stats_count, .get_ethtool_stats = gfar_fill_stats, - .get_rx_csum = gfar_get_rx_csum, - .get_tx_csum = gfar_get_tx_csum, - .set_rx_csum = gfar_set_rx_csum, - .set_tx_csum = gfar_set_tx_csum, - .get_msglevel = gfar_get_msglevel, - .set_msglevel = gfar_set_msglevel, +}; + +struct ethtool_ops gfar_normon_nocoalesce_ethtool_ops = { + .get_settings = gfar_gsettings, + .get_drvinfo = gfar_gdrvinfo, + .get_regs_len = gfar_reglen, + .get_regs = gfar_get_regs, + .get_link = ethtool_op_get_link, + .get_ringparam = gfar_gringparam, + .set_ringparam = gfar_sringparam, + .get_strings = gfar_gstrings_normon, + .get_stats_count = gfar_stats_count_normon, + .get_ethtool_stats = gfar_fill_stats_normon, +}; + +struct ethtool_ops gfar_nocoalesce_ethtool_ops = { + .get_settings = gfar_gsettings, + .get_drvinfo = gfar_gdrvinfo, + .get_regs_len = gfar_reglen, + .get_regs = gfar_get_regs, + .get_link = ethtool_op_get_link, + .get_ringparam = gfar_gringparam, + .set_ringparam = gfar_sringparam, + .get_strings = gfar_gstrings, + .get_stats_count = gfar_stats_count, + .get_ethtool_stats = gfar_fill_stats, +}; + +struct ethtool_ops gfar_normon_ethtool_ops = { + .get_settings = gfar_gsettings, + .get_drvinfo = gfar_gdrvinfo, + .get_regs_len = gfar_reglen, + .get_regs = gfar_get_regs, + .get_link = ethtool_op_get_link, + .get_coalesce = gfar_gcoalesce, + .set_coalesce = gfar_scoalesce, + .get_ringparam = gfar_gringparam, + .set_ringparam = gfar_sringparam, + .get_strings = gfar_gstrings_normon, + .get_stats_count = gfar_stats_count_normon, + .get_ethtool_stats = gfar_fill_stats_normon, +}; + +struct ethtool_ops *gfar_op_array[] = { + &gfar_ethtool_ops, + &gfar_normon_ethtool_ops, + &gfar_nocoalesce_ethtool_ops, + &gfar_normon_nocoalesce_ethtool_ops }; diff --git a/trunk/drivers/net/pcnet32.c b/trunk/drivers/net/pcnet32.c index 3213f3e50487..13f114876965 100644 --- a/trunk/drivers/net/pcnet32.c +++ b/trunk/drivers/net/pcnet32.c @@ -850,7 +850,7 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))) data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - msleep_interruptible(data * 1000); + schedule_timeout(data * HZ); del_timer_sync(&lp->blink_timer); /* Restore the original value of the bcrs */ diff --git a/trunk/drivers/net/sb1000.c b/trunk/drivers/net/sb1000.c index d6388e1533f0..e15369c8d165 100644 --- a/trunk/drivers/net/sb1000.c +++ b/trunk/drivers/net/sb1000.c @@ -90,6 +90,7 @@ static int sb1000_close(struct net_device *dev); /* SB1000 hardware routines to be used during open/configuration phases */ +static inline void nicedelay(unsigned long usecs); static inline int card_wait_for_busy_clear(const int ioaddr[], const char* name); static inline int card_wait_for_ready(const int ioaddr[], const char* name, @@ -253,6 +254,13 @@ static struct pnp_driver sb1000_driver = { static const int TimeOutJiffies = (875 * HZ) / 100; +static inline void nicedelay(unsigned long usecs) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ); + return; +} + /* Card Wait For Busy Clear (cannot be used during an interrupt) */ static inline int card_wait_for_busy_clear(const int ioaddr[], const char* name) @@ -467,7 +475,7 @@ sb1000_reset(const int ioaddr[], const char* name) udelay(1000); outb(0x0, port); inb(port); - ssleep(1); + nicedelay(60000); outb(0x4, port); inb(port); udelay(1000); @@ -529,7 +537,7 @@ sb1000_activate(const int ioaddr[], const char* name) const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00}; const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00}; - ssleep(1); + nicedelay(50000); if ((status = card_send_command(ioaddr, name, Command0, st))) return status; if ((status = card_send_command(ioaddr, name, Command1, st))) @@ -936,7 +944,7 @@ sb1000_open(struct net_device *dev) /* initialize sb1000 */ if ((status = sb1000_reset(ioaddr, name))) return status; - ssleep(1); + nicedelay(200000); if ((status = sb1000_check_CRC(ioaddr, name))) return status; diff --git a/trunk/drivers/net/skfp/Makefile b/trunk/drivers/net/skfp/Makefile index cb23580fcffa..5f4bb1a67400 100644 --- a/trunk/drivers/net/skfp/Makefile +++ b/trunk/drivers/net/skfp/Makefile @@ -6,8 +6,8 @@ obj-$(CONFIG_SKFP) += skfp.o skfp-objs := skfddi.o hwmtm.o fplustm.o smt.o cfm.o \ ecm.o pcmplc.o pmf.o queue.o rmt.o \ - smtdef.o smtinit.o smttimer.o srf.o hwt.o \ - drvfbi.o ess.o + smtdef.o smtinit.o smttimer.o srf.o smtparse.o\ + hwt.o drvfbi.o ess.o # NOTE: # Compiling this driver produces some warnings (and some more are diff --git a/trunk/drivers/net/skfp/drvfbi.c b/trunk/drivers/net/skfp/drvfbi.c index 5b475833f645..052e841ba187 100644 --- a/trunk/drivers/net/skfp/drvfbi.c +++ b/trunk/drivers/net/skfp/drvfbi.c @@ -105,8 +105,8 @@ extern int AIX_vpdReadByte() ; #endif -/* Prototype of a local function. */ -static void smt_stop_watchdog(struct s_smc *smc); +/* Prototypes of local functions. */ +void smt_stop_watchdog(struct s_smc *smc); #ifdef MCA static int read_card_id() ; @@ -631,7 +631,7 @@ void plc_clear_irq(struct s_smc *smc, int p) * LED_Y_OFF just switch yellow LED off * LED_Y_ON just switch yello LED on */ -static void led_indication(struct s_smc *smc, int led_event) +void led_indication(struct s_smc *smc, int led_event) { /* use smc->hw.mac_ring_is_up == TRUE * as indication for Ring Operational @@ -764,6 +764,122 @@ void llc_recover_tx(struct s_smc *smc) #endif } +/*--------------------------- DMA init ----------------------------*/ +#ifdef ISA + +/* + * init DMA + */ +void init_dma(struct s_smc *smc, int dma) +{ + SK_UNUSED(smc) ; + + /* + * set cascade mode, + * clear mask bit (enable DMA cannal) + */ + if (dma > 3) { + outp(0xd6,(dma & 0x03) | 0xc0) ; + outp(0xd4, dma & 0x03) ; + } + else { + outp(0x0b,(dma & 0x03) | 0xc0) ; + outp(0x0a,dma & 0x03) ; + } +} + +/* + * disable DMA + */ +void dis_dma(struct s_smc *smc, int dma) +{ + SK_UNUSED(smc) ; + + /* + * set mask bit (disable DMA cannal) + */ + if (dma > 3) { + outp(0xd4,(dma & 0x03) | 0x04) ; + } + else { + outp(0x0a,(dma & 0x03) | 0x04) ; + } +} + +#endif /* ISA */ + +#ifdef EISA + +/*arrays with io addresses of dma controller length and address registers*/ +static const int cntr[8] = { 0x001,0x003,0x005,0x007,0,0x0c6,0x0ca,0x0ce } ; +static const int base[8] = { 0x000,0x002,0x004,0x006,0,0x0c4,0x0c8,0x0cc } ; +static const int page[8] = { 0x087,0x083,0x081,0x082,0,0x08b,0x089,0x08a } ; + +void init_dma(struct s_smc *smc, int dma) +{ + /* + * extended mode register + * 32 bit IO + * type c + * TC output + * disable stop + */ + + /* mode read (write) demand */ + smc->hw.dma_rmode = (dma & 3) | 0x08 | 0x0 ; + smc->hw.dma_wmode = (dma & 3) | 0x04 | 0x0 ; + + /* 32 bit IO's, burst DMA mode (type "C") */ + smc->hw.dma_emode = (dma & 3) | 0x08 | 0x30 ; + + outp((dma < 4) ? 0x40b : 0x4d6,smc->hw.dma_emode) ; + + /* disable chaining */ + outp((dma < 4) ? 0x40a : 0x4d4,(dma&3)) ; + + /*load dma controller addresses for fast access during set dma*/ + smc->hw.dma_base_word_count = cntr[smc->hw.dma]; + smc->hw.dma_base_address = base[smc->hw.dma]; + smc->hw.dma_base_address_page = page[smc->hw.dma]; + +} + +void dis_dma(struct s_smc *smc, int dma) +{ + SK_UNUSED(smc) ; + + outp((dma < 4) ? 0x0a : 0xd4,(dma&3)|4) ;/* mask bit */ +} +#endif /* EISA */ + +#ifdef MCA +void init_dma(struct s_smc *smc, int dma) +{ + SK_UNUSED(smc) ; + SK_UNUSED(dma) ; +} + +void dis_dma(struct s_smc *smc, int dma) +{ + SK_UNUSED(smc) ; + SK_UNUSED(dma) ; +} +#endif + +#ifdef PCI +void init_dma(struct s_smc *smc, int dma) +{ + SK_UNUSED(smc) ; + SK_UNUSED(dma) ; +} + +void dis_dma(struct s_smc *smc, int dma) +{ + SK_UNUSED(smc) ; + SK_UNUSED(dma) ; +} +#endif + #ifdef MULT_OEM static int is_equal_num(char comp1[], char comp2[], int num) { @@ -1291,7 +1407,7 @@ void smt_start_watchdog(struct s_smc *smc) #endif /* DEBUG */ } -static void smt_stop_watchdog(struct s_smc *smc) +void smt_stop_watchdog(struct s_smc *smc) { SK_UNUSED(smc) ; /* Make LINT happy. */ #ifndef DEBUG @@ -1306,6 +1422,104 @@ static void smt_stop_watchdog(struct s_smc *smc) } #ifdef PCI +static char get_rom_byte(struct s_smc *smc, u_short addr) +{ + GET_PAGE(addr) ; + return (READ_PROM(ADDR(B2_FDP))) ; +} + +/* + * ROM image defines + */ +#define ROM_SIG_1 0 +#define ROM_SIG_2 1 +#define PCI_DATA_1 0x18 +#define PCI_DATA_2 0x19 + +/* + * PCI data structure defines + */ +#define VPD_DATA_1 0x08 +#define VPD_DATA_2 0x09 +#define IMAGE_LEN_1 0x10 +#define IMAGE_LEN_2 0x11 +#define CODE_TYPE 0x14 +#define INDICATOR 0x15 + +/* + * BEGIN_MANUAL_ENTRY(mac_drv_vpd_read) + * mac_drv_vpd_read(smc,buf,size,image) + * + * function DOWNCALL (FDDIWARE) + * reads the VPD data of the FPROM and writes it into the + * buffer + * + * para buf points to the buffer for the VPD data + * size size of the VPD data buffer + * image boot image; code type of the boot image + * image = 0 Intel x86, PC-AT compatible + * 1 OPENBOOT standard for PCI + * 2-FF reserved + * + * returns len number of VPD data bytes read form the FPROM + * <0 number of read bytes + * >0 error: data invalid + * + * END_MANUAL_ENTRY + */ +int mac_drv_vpd_read(struct s_smc *smc, char *buf, int size, char image) +{ + u_short ibase ; + u_short pci_base ; + u_short vpd ; + int len ; + + len = 0 ; + ibase = 0 ; + /* + * as long images defined + */ + while (get_rom_byte(smc,ibase+ROM_SIG_1) == 0x55 && + (u_char) get_rom_byte(smc,ibase+ROM_SIG_2) == 0xaa) { + /* + * get the pointer to the PCI data structure + */ + pci_base = ibase + get_rom_byte(smc,ibase+PCI_DATA_1) + + (get_rom_byte(smc,ibase+PCI_DATA_2) << 8) ; + + if (image == get_rom_byte(smc,pci_base+CODE_TYPE)) { + /* + * we have the right image, read the VPD data + */ + vpd = ibase + get_rom_byte(smc,pci_base+VPD_DATA_1) + + (get_rom_byte(smc,pci_base+VPD_DATA_2) << 8) ; + if (vpd == ibase) { + break ; /* no VPD data */ + } + for (len = 0; len < size; len++,buf++,vpd++) { + *buf = get_rom_byte(smc,vpd) ; + } + break ; + } + else { + /* + * try the next image + */ + if (get_rom_byte(smc,pci_base+INDICATOR) & 0x80) { + break ; /* this was the last image */ + } + ibase = ibase + get_rom_byte(smc,ibase+IMAGE_LEN_1) + + (get_rom_byte(smc,ibase+IMAGE_LEN_2) << 8) ; + } + } + + return(len) ; +} + +void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value) +{ + smc->hw.pci_fix_value = fix_value ; +} void mac_do_pci_fix(struct s_smc *smc) { diff --git a/trunk/drivers/net/skfp/ess.c b/trunk/drivers/net/skfp/ess.c index 62b01328c496..fd39b4b2ef7d 100644 --- a/trunk/drivers/net/skfp/ess.c +++ b/trunk/drivers/net/skfp/ess.c @@ -102,7 +102,7 @@ void ess_timer_poll(struct s_smc *smc); void ess_para_change(struct s_smc *smc); int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, int fs); -static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead); +int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead); /* @@ -375,7 +375,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, * determines the synchronous bandwidth, set the TSYNC register and the * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG. */ -static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead) +int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead) { /* * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG, diff --git a/trunk/drivers/net/skfp/fplustm.c b/trunk/drivers/net/skfp/fplustm.c index a2ed47f1cc70..76e78442fc24 100644 --- a/trunk/drivers/net/skfp/fplustm.c +++ b/trunk/drivers/net/skfp/fplustm.c @@ -1114,6 +1114,30 @@ void mac_clear_multicast(struct s_smc *smc) } } +/* + BEGIN_MANUAL_ENTRY(if,func;others;2) + + int mac_set_func_addr(smc,f_addr) + struct s_smc *smc ; + u_long f_addr ; + +Function DOWNCALL (SMT, fplustm.c) + Set a Token-Ring functional address, the address will + be activated after calling mac_update_multicast() + +Para f_addr functional bits in non-canonical format + +Returns 0: always success + + END_MANUAL_ENTRY() + */ +int mac_set_func_addr(struct s_smc *smc, u_long f_addr) +{ + smc->hw.fp.func_addr = f_addr ; + return(0) ; +} + + /* BEGIN_MANUAL_ENTRY(if,func;others;2) @@ -1178,6 +1202,52 @@ int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) return(0) ; } +/* + BEGIN_MANUAL_ENTRY(if,func;others;2) + + void mac_del_multicast(smc,addr,can) + struct s_smc *smc ; + struct fddi_addr *addr ; + int can ; + +Function DOWNCALL (SMT, fplustm.c) + Delete an entry from the multicast table + +Para addr pointer to a multicast address + can = 0: the multicast address has the physical format + = 1: the multicast address has the canonical format + | 0x80 permanent + + END_MANUAL_ENTRY() + */ +void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) +{ + SK_LOC_DECL(struct fddi_addr,own) ; + struct s_fpmc *tb ; + + if (!(tb = mac_get_mc_table(smc,addr,&own,1,can & ~0x80))) + return ; + /* + * permanent addresses must be deleted with perm bit + * and vice versa + */ + if (( tb->perm && (can & 0x80)) || + (!tb->perm && !(can & 0x80))) { + /* + * delete it + */ + if (tb->n) { + tb->n-- ; + if (tb->perm) { + smc->hw.fp.smt_slots_used-- ; + } + else { + smc->hw.fp.os_slots_used-- ; + } + } + } +} + /* * mode */ diff --git a/trunk/drivers/net/skfp/h/cmtdef.h b/trunk/drivers/net/skfp/h/cmtdef.h index f2f771d8be76..603982debc71 100644 --- a/trunk/drivers/net/skfp/h/cmtdef.h +++ b/trunk/drivers/net/skfp/h/cmtdef.h @@ -507,6 +507,7 @@ void pcm_status_state(struct s_smc *smc, int np, int *type, int *state, int *remote, int *mac); void plc_config_mux(struct s_smc *smc, int mux); void sm_lem_evaluate(struct s_smc *smc); +void smt_clear_una_dna(struct s_smc *smc); void mac_update_counter(struct s_smc *smc); void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off); void sm_ma_control(struct s_smc *smc, int mode); @@ -540,9 +541,11 @@ void smt_timer_poll(struct s_smc *smc); u_long smt_get_time(void); u_long smt_get_tid(struct s_smc *smc); void smt_timer_done(struct s_smc *smc); +void smt_set_defaults(struct s_smc *smc); void smt_fixup_mib(struct s_smc *smc); void smt_reset_defaults(struct s_smc *smc, int level); void smt_agent_task(struct s_smc *smc); +void smt_please_reconnect(struct s_smc *smc, int reconn_time); int smt_check_para(struct s_smc *smc, struct smt_header *sm, const u_short list[]); void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr); @@ -565,6 +568,7 @@ int pcm_get_s_port(struct s_smc *smc); int pcm_rooted_station(struct s_smc *smc); int cfm_get_mac_input(struct s_smc *smc); int cfm_get_mac_output(struct s_smc *smc); +int port_to_mib(struct s_smc *smc, int p); int cem_build_path(struct s_smc *smc, char *to, int path_index); int sm_mac_get_tx_state(struct s_smc *smc); char *get_pcmstate(struct s_smc *smc, int np); @@ -576,6 +580,8 @@ void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local); void smt_set_timestamp(struct s_smc *smc, u_char *p); void mac_set_rx_mode(struct s_smc *smc, int mode); int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); +int mac_set_func_addr(struct s_smc *smc, u_long f_addr); +void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); void mac_update_multicast(struct s_smc *smc); void mac_clear_multicast(struct s_smc *smc); void set_formac_tsync(struct s_smc *smc, long sync_bw); @@ -593,6 +599,7 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd); int smt_set_mac_opvalues(struct s_smc *smc); #ifdef TAG_MODE +void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value); void mac_do_pci_fix(struct s_smc *smc); void mac_drv_clear_tx_queue(struct s_smc *smc); void mac_drv_repair_descr(struct s_smc *smc); diff --git a/trunk/drivers/net/skfp/h/hwmtm.h b/trunk/drivers/net/skfp/h/hwmtm.h index 1a606d4bfe5e..4e360af07d77 100644 --- a/trunk/drivers/net/skfp/h/hwmtm.h +++ b/trunk/drivers/net/skfp/h/hwmtm.h @@ -261,6 +261,31 @@ struct os_debug { #define HWM_GET_CURR_TXD(smc,queue) (struct s_smt_fp_txd volatile *)\ (smc)->hw.fp.tx_q[queue].tx_curr_put +/* + * BEGIN_MANUAL_ENTRY(HWM_TX_CHECK) + * void HWM_TX_CHECK(smc,frame_status,low_water) + * + * function MACRO (hardware module, hwmtm.h) + * This macro is invoked by the OS-specific before it left it's + * driver_send function. This macro calls mac_drv_clear_txd + * if the free TxDs of the current transmit queue is equal or + * lower than the given low water mark. + * + * para frame_status status of the frame, see design description + * low_water low water mark of free TxD's + * + * END_MANUAL_ENTRY + */ +#ifndef HWM_NO_FLOW_CTL +#define HWM_TX_CHECK(smc,frame_status,low_water) {\ + if ((low_water)>=(smc)->hw.fp.tx_q[(frame_status)&QUEUE_A0].tx_free) {\ + mac_drv_clear_txd(smc) ;\ + }\ +} +#else +#define HWM_TX_CHECK(smc,frame_status,low_water) mac_drv_clear_txd(smc) +#endif + /* * BEGIN_MANUAL_ENTRY(HWM_GET_RX_FRAG_LEN) * int HWM_GET_RX_FRAG_LEN(rxd) diff --git a/trunk/drivers/net/skfp/hwmtm.c b/trunk/drivers/net/skfp/hwmtm.c index 438f424e6361..18d429021edb 100644 --- a/trunk/drivers/net/skfp/hwmtm.c +++ b/trunk/drivers/net/skfp/hwmtm.c @@ -86,7 +86,6 @@ static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue); static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue); static SMbuf* get_llc_rx(struct s_smc *smc); static SMbuf* get_txd_mb(struct s_smc *smc); -static void mac_drv_clear_txd(struct s_smc *smc); /* ------------------------------------------------------------- @@ -147,6 +146,7 @@ extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, */ void process_receive(struct s_smc *smc); void fddi_isr(struct s_smc *smc); +void mac_drv_clear_txd(struct s_smc *smc); void smt_free_mbuf(struct s_smc *smc, SMbuf *mb); void init_driver_fplus(struct s_smc *smc); void mac_drv_rx_mode(struct s_smc *smc, int mode); @@ -158,6 +158,7 @@ void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, int frame_status); +int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len); int mac_drv_init(struct s_smc *smc); int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, int frame_status); @@ -1447,6 +1448,35 @@ void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ; } +#ifndef NDIS_OS2 +/* + * BEGIN_MANUAL_ENTRY(mac_drv_rx_frag) + * int mac_drv_rx_frag(smc,virt,len) + * + * function DOWNCALL (hwmtm.c) + * mac_drv_rx_frag fills the fragment with a part of the frame. + * + * para virt the virtual address of the fragment + * len the length in bytes of the fragment + * + * return 0: success code, no errors possible + * + * END_MANUAL_ENTRY + */ +int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len) +{ + NDD_TRACE("RHSB",virt,len,smc->os.hwm.r.mb_pos) ; + + DB_RX("receive from queue: len/virt: = %d/%x",len,virt,4) ; + memcpy((char far *)virt,smc->os.hwm.r.mb_pos,len) ; + smc->os.hwm.r.mb_pos += len ; + + NDD_TRACE("RHSE",smc->os.hwm.r.mb_pos,0,0) ; + return(0) ; +} +#endif + + /* * BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue) * @@ -1948,7 +1978,7 @@ void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc) * * END_MANUAL_ENTRY */ -static void mac_drv_clear_txd(struct s_smc *smc) +void mac_drv_clear_txd(struct s_smc *smc) { struct s_smt_tx_queue *queue ; struct s_smt_fp_txd volatile *t1 ; diff --git a/trunk/drivers/net/skfp/pcmplc.c b/trunk/drivers/net/skfp/pcmplc.c index cd0aa4c151b0..571f055c096b 100644 --- a/trunk/drivers/net/skfp/pcmplc.c +++ b/trunk/drivers/net/skfp/pcmplc.c @@ -1861,6 +1861,13 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd) #endif } +void pcm_set_lct_short(struct s_smc *smc, int n) +{ + if (n <= 0 || n > 1000) + return ; + smc->s.lct_short = n ; +} + #ifdef DEBUG /* * fill state struct diff --git a/trunk/drivers/net/skfp/pmf.c b/trunk/drivers/net/skfp/pmf.c index efc639c013fd..f2b446d8b0bf 100644 --- a/trunk/drivers/net/skfp/pmf.c +++ b/trunk/drivers/net/skfp/pmf.c @@ -36,13 +36,12 @@ static int smt_authorize(struct s_smc *smc, struct smt_header *sm); static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm); static const struct s_p_tab* smt_get_ptab(u_short para); static int smt_mib_phys(struct s_smc *smc); -static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, - int local, int set); +int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, + int set); void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, int index, int local); static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req, int set, int local); -static int port_to_mib(struct s_smc *smc, int p); #define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e)) #define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e)) @@ -1079,8 +1078,8 @@ void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, /* * set parameter */ -static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, - int local, int set) +int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, + int set) { #define IFSET(x) if (set) (x) @@ -1550,7 +1549,7 @@ static int smt_mib_phys(struct s_smc *smc) #endif } -static int port_to_mib(struct s_smc *smc, int p) +int port_to_mib(struct s_smc *smc, int p) { #ifdef CONCENTRATOR SK_UNUSED(smc) ; diff --git a/trunk/drivers/net/skfp/skfddi.c b/trunk/drivers/net/skfp/skfddi.c index 4b5ed2c63177..c88aad6edd74 100644 --- a/trunk/drivers/net/skfp/skfddi.c +++ b/trunk/drivers/net/skfp/skfddi.c @@ -149,6 +149,7 @@ extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys, extern void mac_drv_rx_mode(struct s_smc *smc, int mode); extern void mac_drv_clear_rx_queue(struct s_smc *smc); extern void enable_tx_irq(struct s_smc *smc, u_short queue); +extern void mac_drv_clear_txd(struct s_smc *smc); static struct pci_device_id skfddi_pci_tbl[] = { { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, }, diff --git a/trunk/drivers/net/skfp/smt.c b/trunk/drivers/net/skfp/smt.c index f17c05cbe44b..c3a0d2f10b2b 100644 --- a/trunk/drivers/net/skfp/smt.c +++ b/trunk/drivers/net/skfp/smt.c @@ -110,7 +110,7 @@ static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, int len); -static void smt_clear_una_dna(struct s_smc *smc); +void smt_clear_una_dna(struct s_smc *smc); static void smt_clear_old_una_dna(struct s_smc *smc); #ifdef CONCENTRATOR static int entity_to_index(void); @@ -118,7 +118,7 @@ static int entity_to_index(void); static void update_dac(struct s_smc *smc, int report); static int div_ratio(u_long upper, u_long lower); #ifdef USE_CAN_ADDR -static void hwm_conv_can(struct s_smc *smc, char *data, int len); +void hwm_conv_can(struct s_smc *smc, char *data, int len); #else #define hwm_conv_can(smc,data,len) #endif @@ -216,6 +216,24 @@ void smt_agent_task(struct s_smc *smc) DB_SMT("SMT agent task\n",0,0) ; } +void smt_please_reconnect(struct s_smc *smc, int reconn_time) +/* struct s_smc *smc; Pointer to SMT context */ +/* int reconn_time; Wait for reconnect time in seconds */ +{ + /* + * The please reconnect variable is used as a timer. + * It is decremented each time smt_event is called. + * This happens every second or when smt_force_irq is called. + * Note: smt_force_irq () is called on some packet receives and + * when a multicast address is changed. Since nothing + * is received during the disconnect and the multicast + * address changes can be viewed as not very often and + * the timer runs out close to its given value + * (reconn_time). + */ + smc->sm.please_reconnect = reconn_time ; +} + #ifndef SMT_REAL_TOKEN_CT void smt_emulate_token_ct(struct s_smc *smc, int mac_index) { @@ -1556,7 +1574,7 @@ static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long see * clear DNA and UNA * called from CFM if configuration changes */ -static void smt_clear_una_dna(struct s_smc *smc) +void smt_clear_una_dna(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; @@ -2039,11 +2057,31 @@ int smt_action(struct s_smc *smc, int class, int code, int index) return(0) ; } +/* + * change tneg + * set T_Req in MIB (Path Attribute) + * calculate new values for MAC + * if change required + * disconnect + * set reconnect + * end + */ +void smt_change_t_neg(struct s_smc *smc, u_long tneg) +{ + smc->mib.a[PATH0].fddiPATHMaxT_Req = tneg ; + + if (smt_set_mac_opvalues(smc)) { + RS_SET(smc,RS_EVENT) ; + smc->sm.please_reconnect = 1 ; + queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; + } +} + /* * canonical conversion of bytes beginning form *data */ #ifdef USE_CAN_ADDR -static void hwm_conv_can(struct s_smc *smc, char *data, int len) +void hwm_conv_can(struct s_smc *smc, char *data, int len) { int i ; diff --git a/trunk/drivers/net/skfp/smtdef.c b/trunk/drivers/net/skfp/smtdef.c index 4e07ff7073f1..5a0c8db816d8 100644 --- a/trunk/drivers/net/skfp/smtdef.c +++ b/trunk/drivers/net/skfp/smtdef.c @@ -76,6 +76,11 @@ void smt_reset_defaults(struct s_smc *smc, int level); static void smt_init_mib(struct s_smc *smc, int level); static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper); +void smt_set_defaults(struct s_smc *smc) +{ + smt_reset_defaults(smc,0) ; +} + #define MS2BCLK(x) ((x)*12500L) #define US2BCLK(x) ((x)*1250L) diff --git a/trunk/drivers/net/skfp/smtparse.c b/trunk/drivers/net/skfp/smtparse.c new file mode 100644 index 000000000000..d5779e414dbe --- /dev/null +++ b/trunk/drivers/net/skfp/smtparse.c @@ -0,0 +1,467 @@ +/****************************************************************************** + * + * (C)Copyright 1998,1999 SysKonnect, + * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * + * See the file "skfddi.c" for further information. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + + +/* + parser for SMT parameters +*/ + +#include "h/types.h" +#include "h/fddi.h" +#include "h/smc.h" +#include "h/smt_p.h" + +#define KERNEL +#include "h/smtstate.h" + +#ifndef lint +static const char ID_sccs[] = "@(#)smtparse.c 1.12 98/10/06 (C) SK " ; +#endif + +#ifdef sun +#define _far +#endif + +/* + * convert to BCLK units + */ +#define MS2BCLK(x) ((x)*12500L) +#define US2BCLK(x) ((x/10)*125L) + +/* + * parameter table + */ +static struct s_ptab { + char *pt_name ; + u_short pt_num ; + u_short pt_type ; + u_long pt_min ; + u_long pt_max ; +} ptab[] = { + { "PMFPASSWD",0, 0 } , + { "USERDATA",1, 0 } , + { "LERCUTOFFA",2, 1, 4, 15 } , + { "LERCUTOFFB",3, 1, 4, 15 } , + { "LERALARMA",4, 1, 4, 15 } , + { "LERALARMB",5, 1, 4, 15 } , + { "TMAX",6, 1, 5, 165 } , + { "TMIN",7, 1, 5, 165 } , + { "TREQ",8, 1, 5, 165 } , + { "TVX",9, 1, 2500, 10000 } , +#ifdef ESS + { "SBAPAYLOAD",10, 1, 0, 1562 } , + { "SBAOVERHEAD",11, 1, 50, 5000 } , + { "MAXTNEG",12, 1, 5, 165 } , + { "MINSEGMENTSIZE",13, 1, 0, 4478 } , + { "SBACATEGORY",14, 1, 0, 0xffff } , + { "SYNCHTXMODE",15, 0 } , +#endif +#ifdef SBA + { "SBACOMMAND",16, 0 } , + { "SBAAVAILABLE",17, 1, 0, 100 } , +#endif + { NULL } +} ; + +/* Define maximum string size for values and keybuffer */ +#define MAX_VAL 40 + +/* + * local function declarations + */ +static u_long parse_num(int type, char _far *value, char *v, u_long mn, + u_long mx, int scale); +static int parse_word(char *buf, char _far *text); + +#ifdef SIM +#define DB_MAIN(a,b,c) printf(a,b,c) +#else +#define DB_MAIN(a,b,c) +#endif + +/* + * BEGIN_MANUAL_ENTRY() + * + * int smt_parse_arg(struct s_smc *,char _far *keyword,int type, + char _far *value) + * + * parse SMT parameter + * *keyword + * pointer to keyword, must be \0, \n or \r terminated + * *value pointer to value, either char * or u_long * + * if char * + * pointer to value, must be \0, \n or \r terminated + * if u_long * + * contains binary value + * + * type 0: integer + * 1: string + * return + * 0 parameter parsed ok + * != 0 error + * NOTE: + * function can be called with DS != SS + * + * + * END_MANUAL_ENTRY() + */ +int smt_parse_arg(struct s_smc *smc, char _far *keyword, int type, + char _far *value) +{ + char keybuf[MAX_VAL+1]; + char valbuf[MAX_VAL+1]; + char c ; + char *p ; + char *v ; + char *d ; + u_long val = 0 ; + struct s_ptab *pt ; + int st ; + int i ; + + /* + * parse keyword + */ + if ((st = parse_word(keybuf,keyword))) + return(st) ; + /* + * parse value if given as string + */ + if (type == 1) { + if ((st = parse_word(valbuf,value))) + return(st) ; + } + /* + * search in table + */ + st = 0 ; + for (pt = ptab ; (v = pt->pt_name) ; pt++) { + for (p = keybuf ; (c = *p) ; p++,v++) { + if (c != *v) + break ; + } + if (!c && !*v) + break ; + } + if (!v) + return(-1) ; +#if 0 + printf("=>%s<==>%s<=\n",pt->pt_name,valbuf) ; +#endif + /* + * set value in MIB + */ + if (pt->pt_type) + val = parse_num(type,value,valbuf,pt->pt_min,pt->pt_max,1) ; + switch (pt->pt_num) { + case 0 : + v = valbuf ; + d = (char *) smc->mib.fddiPRPMFPasswd ; + for (i = 0 ; i < (signed)sizeof(smc->mib.fddiPRPMFPasswd) ; i++) + *d++ = *v++ ; + DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiPRPMFPasswd) ; + break ; + case 1 : + v = valbuf ; + d = (char *) smc->mib.fddiSMTUserData ; + for (i = 0 ; i < (signed)sizeof(smc->mib.fddiSMTUserData) ; i++) + *d++ = *v++ ; + DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiSMTUserData) ; + break ; + case 2 : + smc->mib.p[PA].fddiPORTLer_Cutoff = (u_char) val ; + DB_MAIN("SET %s = %d\n", + pt->pt_name,smc->mib.p[PA].fddiPORTLer_Cutoff) ; + break ; + case 3 : + smc->mib.p[PB].fddiPORTLer_Cutoff = (u_char) val ; + DB_MAIN("SET %s = %d\n", + pt->pt_name,smc->mib.p[PB].fddiPORTLer_Cutoff) ; + break ; + case 4 : + smc->mib.p[PA].fddiPORTLer_Alarm = (u_char) val ; + DB_MAIN("SET %s = %d\n", + pt->pt_name,smc->mib.p[PA].fddiPORTLer_Alarm) ; + break ; + case 5 : + smc->mib.p[PB].fddiPORTLer_Alarm = (u_char) val ; + DB_MAIN("SET %s = %d\n", + pt->pt_name,smc->mib.p[PB].fddiPORTLer_Alarm) ; + break ; + case 6 : /* TMAX */ + DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; + smc->mib.a[PATH0].fddiPATHT_MaxLowerBound = + (u_long) -MS2BCLK((long)val) ; + break ; + case 7 : /* TMIN */ + DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; + smc->mib.m[MAC0].fddiMACT_Min = + (u_long) -MS2BCLK((long)val) ; + break ; + case 8 : /* TREQ */ + DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; + smc->mib.a[PATH0].fddiPATHMaxT_Req = + (u_long) -MS2BCLK((long)val) ; + break ; + case 9 : /* TVX */ + DB_MAIN("SET %s = %d \n",pt->pt_name,val) ; + smc->mib.a[PATH0].fddiPATHTVXLowerBound = + (u_long) -US2BCLK((long)val) ; + break ; +#ifdef ESS + case 10 : /* SBAPAYLOAD */ + DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; + if (smc->mib.fddiESSPayload != val) { + smc->ess.raf_act_timer_poll = TRUE ; + smc->mib.fddiESSPayload = val ; + } + break ; + case 11 : /* SBAOVERHEAD */ + DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; + smc->mib.fddiESSOverhead = val ; + break ; + case 12 : /* MAXTNEG */ + DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; + smc->mib.fddiESSMaxTNeg = (u_long) -MS2BCLK((long)val) ; + break ; + case 13 : /* MINSEGMENTSIZE */ + DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; + smc->mib.fddiESSMinSegmentSize = val ; + break ; + case 14 : /* SBACATEGORY */ + DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; + smc->mib.fddiESSCategory = + (smc->mib.fddiESSCategory & 0xffff) | + ((u_long)(val << 16)) ; + break ; + case 15 : /* SYNCHTXMODE */ + /* do not use memcmp(valbuf,"ALL",3) because DS != SS */ + if (valbuf[0] == 'A' && valbuf[1] == 'L' && valbuf[2] == 'L') { + smc->mib.fddiESSSynchTxMode = TRUE ; + DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; + } + /* if (!memcmp(valbuf,"SPLIT",5)) { */ + if (valbuf[0] == 'S' && valbuf[1] == 'P' && valbuf[2] == 'L' && + valbuf[3] == 'I' && valbuf[4] == 'T') { + DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; + smc->mib.fddiESSSynchTxMode = FALSE ; + } + break ; +#endif +#ifdef SBA + case 16 : /* SBACOMMAND */ + /* if (!memcmp(valbuf,"START",5)) { */ + if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'A' && + valbuf[3] == 'R' && valbuf[4] == 'T') { + DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; + smc->mib.fddiSBACommand = SB_START ; + } + /* if (!memcmp(valbuf,"STOP",4)) { */ + if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'O' && + valbuf[3] == 'P') { + DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; + smc->mib.fddiSBACommand = SB_STOP ; + } + break ; + case 17 : /* SBAAVAILABLE */ + DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; + smc->mib.fddiSBAAvailable = (u_char) val ; + break ; +#endif + } + return(0) ; +} + +static int parse_word(char *buf, char _far *text) +{ + char c ; + char *p ; + int p_len ; + int quote ; + int i ; + int ok ; + + /* + * skip leading white space + */ + p = buf ; + for (i = 0 ; i < MAX_VAL ; i++) + *p++ = 0 ; + p = buf ; + p_len = 0 ; + ok = 0 ; + while ( (c = *text++) && (c != '\n') && (c != '\r')) { + if ((c != ' ') && (c != '\t')) { + ok = 1 ; + break ; + } + } + if (!ok) + return(-1) ; + if (c == '"') { + quote = 1 ; + } + else { + quote = 0 ; + text-- ; + } + /* + * parse valbuf + */ + ok = 0 ; + while (!ok && p_len < MAX_VAL-1 && (c = *text++) && (c != '\n') + && (c != '\r')) { + switch (quote) { + case 0 : + if ((c == ' ') || (c == '\t') || (c == '=')) { + ok = 1 ; + break ; + } + *p++ = c ; + p_len++ ; + break ; + case 2 : + *p++ = c ; + p_len++ ; + quote = 1 ; + break ; + case 1 : + switch (c) { + case '"' : + ok = 1 ; + break ; + case '\\' : + quote = 2 ; + break ; + default : + *p++ = c ; + p_len++ ; + } + } + } + *p++ = 0 ; + for (p = buf ; (c = *p) ; p++) { + if (c >= 'a' && c <= 'z') + *p = c + 'A' - 'a' ; + } + return(0) ; +} + +static u_long parse_num(int type, char _far *value, char *v, u_long mn, + u_long mx, int scale) +{ + u_long x = 0 ; + char c ; + + if (type == 0) { /* integer */ + u_long _far *l ; + u_long u1 ; + + l = (u_long _far *) value ; + u1 = *l ; + /* + * if the value is negative take the lower limit + */ + if ((long)u1 < 0) { + if (- ((long)u1) > (long) mx) { + u1 = 0 ; + } + else { + u1 = (u_long) - ((long)u1) ; + } + } + x = u1 ; + } + else { /* string */ + int sign = 0 ; + + if (*v == '-') { + sign = 1 ; + } + while ((c = *v++) && (c >= '0') && (c <= '9')) { + x = x * 10 + c - '0' ; + } + if (scale == 10) { + x *= 10 ; + if (c == '.') { + if ((c = *v++) && (c >= '0') && (c <= '9')) { + x += c - '0' ; + } + } + } + if (sign) + x = (u_long) - ((long)x) ; + } + /* + * if the value is negative + * and the absolute value is outside the limits + * take the lower limit + * else + * take the absoute value + */ + if ((long)x < 0) { + if (- ((long)x) > (long) mx) { + x = 0 ; + } + else { + x = (u_long) - ((long)x) ; + } + } + if (x < mn) + return(mn) ; + else if (x > mx) + return(mx) ; + return(x) ; +} + +#if 0 +struct s_smc SMC ; +main() +{ + char *p ; + char *v ; + char buf[100] ; + int toggle = 0 ; + + while (gets(buf)) { + p = buf ; + while (*p && ((*p == ' ') || (*p == '\t'))) + p++ ; + + while (*p && ((*p != ' ') && (*p != '\t'))) + p++ ; + + v = p ; + while (*v && ((*v == ' ') || (*v == '\t'))) + v++ ; + if ((*v >= '0') && (*v <= '9')) { + toggle = !toggle ; + if (toggle) { + u_long l ; + l = atol(v) ; + smt_parse_arg(&SMC,buf,0,(char _far *)&l) ; + } + else + smt_parse_arg(&SMC,buf,1,(char _far *)p) ; + } + else { + smt_parse_arg(&SMC,buf,1,(char _far *)p) ; + } + } + exit(0) ; +} +#endif + diff --git a/trunk/drivers/net/smc91x.c b/trunk/drivers/net/smc91x.c index cfb9d3cdb04a..fd80048f7f7a 100644 --- a/trunk/drivers/net/smc91x.c +++ b/trunk/drivers/net/smc91x.c @@ -315,25 +315,15 @@ static void smc_reset(struct net_device *dev) struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int ctl, cfg; - struct sk_buff *pending_skb; DBG(2, "%s: %s\n", dev->name, __FUNCTION__); - /* Disable all interrupts, block TX tasklet */ + /* Disable all interrupts */ spin_lock(&lp->lock); SMC_SELECT_BANK(2); SMC_SET_INT_MASK(0); - pending_skb = lp->pending_tx_skb; - lp->pending_tx_skb = NULL; spin_unlock(&lp->lock); - /* free any pending tx skb */ - if (pending_skb) { - dev_kfree_skb(pending_skb); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - } - /* * This resets the registers mostly to defaults, but doesn't * affect EEPROM. That seems unnecessary @@ -399,6 +389,14 @@ static void smc_reset(struct net_device *dev) SMC_SELECT_BANK(2); SMC_SET_MMU_CMD(MC_RESET); SMC_WAIT_MMU_BUSY(); + + /* clear anything saved */ + if (lp->pending_tx_skb != NULL) { + dev_kfree_skb (lp->pending_tx_skb); + lp->pending_tx_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + } } /* @@ -442,7 +440,6 @@ static void smc_shutdown(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; - struct sk_buff *pending_skb; DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); @@ -450,11 +447,7 @@ static void smc_shutdown(struct net_device *dev) spin_lock(&lp->lock); SMC_SELECT_BANK(2); SMC_SET_INT_MASK(0); - pending_skb = lp->pending_tx_skb; - lp->pending_tx_skb = NULL; spin_unlock(&lp->lock); - if (pending_skb) - dev_kfree_skb(pending_skb); /* and tell the card to stay away from that nasty outside world */ SMC_SELECT_BANK(0); @@ -634,12 +627,7 @@ static void smc_hardware_send_pkt(unsigned long data) } skb = lp->pending_tx_skb; - if (unlikely(!skb)) { - smc_special_unlock(&lp->lock); - return; - } lp->pending_tx_skb = NULL; - packet_no = SMC_GET_AR(); if (unlikely(packet_no & AR_FAILED)) { printk("%s: Memory allocation failed.\n", dev->name); @@ -714,6 +702,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) DBG(3, "%s: %s\n", dev->name, __FUNCTION__); BUG_ON(lp->pending_tx_skb != NULL); + lp->pending_tx_skb = skb; /* * The MMU wants the number of pages to be the number of 256 bytes @@ -729,6 +718,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) numPages = ((skb->len & ~1) + (6 - 1)) >> 8; if (unlikely(numPages > 7)) { printk("%s: Far too big packet error.\n", dev->name); + lp->pending_tx_skb = NULL; lp->stats.tx_errors++; lp->stats.tx_dropped++; dev_kfree_skb(skb); @@ -755,7 +745,6 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) smc_special_unlock(&lp->lock); - lp->pending_tx_skb = skb; if (!poll_count) { /* oh well, wait until the chip finds memory later */ netif_stop_queue(dev); @@ -1073,7 +1062,7 @@ static void smc_phy_powerdown(struct net_device *dev) above). linkwatch_event() also wants the netlink semaphore. */ while(lp->work_pending) - yield(); + schedule(); bmcr = smc_phy_read(dev, phy, MII_BMCR); smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); @@ -1617,8 +1606,14 @@ static int smc_close(struct net_device *dev) /* clear everything */ smc_shutdown(dev); - tasklet_kill(&lp->tx_task); + smc_phy_powerdown(dev); + + if (lp->pending_tx_skb) { + dev_kfree_skb(lp->pending_tx_skb); + lp->pending_tx_skb = NULL; + } + return 0; } diff --git a/trunk/drivers/net/tokenring/lanstreamer.c b/trunk/drivers/net/tokenring/lanstreamer.c index 97712c3c4e07..6e5ade99a38f 100644 --- a/trunk/drivers/net/tokenring/lanstreamer.c +++ b/trunk/drivers/net/tokenring/lanstreamer.c @@ -455,7 +455,8 @@ static int streamer_reset(struct net_device *dev) writew(readw(streamer_mmio + BCTL) | BCTL_SOFTRESET, streamer_mmio + BCTL); t = jiffies; /* Hold soft reset bit for a while */ - ssleep(1); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ); writew(readw(streamer_mmio + BCTL) & ~BCTL_SOFTRESET, streamer_mmio + BCTL); @@ -511,7 +512,8 @@ static int streamer_reset(struct net_device *dev) writew(SISR_MI, streamer_mmio + SISR_MASK_SUM); while (!((readw(streamer_mmio + SISR)) & SISR_SRB_REPLY)) { - msleep_interruptible(100); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/10); if (jiffies - t > 40 * HZ) { printk(KERN_ERR "IBM PCI tokenring card not responding\n"); diff --git a/trunk/drivers/net/tulip/tulip_core.c b/trunk/drivers/net/tulip/tulip_core.c index 08e0f80f89d5..cfc346e72d62 100644 --- a/trunk/drivers/net/tulip/tulip_core.c +++ b/trunk/drivers/net/tulip/tulip_core.c @@ -242,7 +242,6 @@ static struct pci_device_id tulip_pci_tbl[] = { { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */ { 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */ { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ - { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */ { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); @@ -1757,19 +1756,11 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); - if (!dev) - return -EINVAL; - - if (netif_running(dev)) - tulip_down(dev); - - netif_device_detach(dev); - free_irq(dev->irq, dev); - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - + if (dev && netif_running (dev) && netif_device_present (dev)) { + netif_device_detach (dev); + tulip_down (dev); + /* pci_power_off(pdev, -1); */ + } return 0; } @@ -1777,26 +1768,15 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) static int tulip_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - int retval; - - if (!dev) - return -EINVAL; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_device(pdev); - - if ((retval = request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))) { - printk (KERN_ERR "tulip: request_irq failed in resume\n"); - return retval; + if (dev && netif_running (dev) && !netif_device_present (dev)) { +#if 1 + pci_enable_device (pdev); +#endif + /* pci_power_on(pdev); */ + tulip_up (dev); + netif_device_attach (dev); } - - netif_device_attach(dev); - - if (netif_running(dev)) - tulip_up(dev); - return 0; } diff --git a/trunk/drivers/net/via-rhine.c b/trunk/drivers/net/via-rhine.c index be1c1047b9ba..6200cfc4244e 100644 --- a/trunk/drivers/net/via-rhine.c +++ b/trunk/drivers/net/via-rhine.c @@ -1398,7 +1398,7 @@ static void rhine_tx(struct net_device *dev) while (rp->dirty_tx != rp->cur_tx) { txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status); if (debug > 6) - printk(KERN_DEBUG "Tx scavenge %d status %8.8x.\n", + printk(KERN_DEBUG " Tx scavenge %d status %8.8x.\n", entry, txstatus); if (txstatus & DescOwn) break; @@ -1469,7 +1469,7 @@ static void rhine_rx(struct net_device *dev) int data_size = desc_status >> 16; if (debug > 4) - printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n", + printk(KERN_DEBUG " rhine_rx() status is %8.8x.\n", desc_status); if (--boguscnt < 0) break; @@ -1487,7 +1487,7 @@ static void rhine_rx(struct net_device *dev) } else if (desc_status & RxErr) { /* There was a error. */ if (debug > 2) - printk(KERN_DEBUG "rhine_rx() Rx " + printk(KERN_DEBUG " rhine_rx() Rx " "error was %8.8x.\n", desc_status); rp->stats.rx_errors++; diff --git a/trunk/drivers/net/wan/farsync.c b/trunk/drivers/net/wan/farsync.c index 7217d44e8854..7575b799ce53 100644 --- a/trunk/drivers/net/wan/farsync.c +++ b/trunk/drivers/net/wan/farsync.c @@ -981,7 +981,6 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd) /* Wait for any previous command to complete */ while (mbval > NAK) { spin_unlock_irqrestore(&card->card_lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); spin_lock_irqsave(&card->card_lock, flags); diff --git a/trunk/drivers/net/wireless/airo.c b/trunk/drivers/net/wireless/airo.c index c12648d8192b..180968899cad 100644 --- a/trunk/drivers/net/wireless/airo.c +++ b/trunk/drivers/net/wireless/airo.c @@ -900,7 +900,7 @@ typedef struct aironet_ioctl { unsigned char __user *data; // d-data } aironet_ioctl; -static char swversion[] = "2.1"; +static char *swversion = "2.1"; #endif /* CISCO_EXT */ #define NUM_MODULES 2 diff --git a/trunk/drivers/net/wireless/orinoco.c b/trunk/drivers/net/wireless/orinoco.c index aabcdc2be05e..b1078baa1d5e 100644 --- a/trunk/drivers/net/wireless/orinoco.c +++ b/trunk/drivers/net/wireless/orinoco.c @@ -46,9 +46,382 @@ * under either the MPL or the GPL. */ /* + * v0.01 -> v0.02 - 21/3/2001 - Jean II + * o Allow to use regular ethX device name instead of dldwdX + * o Warning on IBSS with ESSID=any for firmware 6.06 + * o Put proper range.throughput values (optimistic) + * o IWSPY support (IOCTL and stat gather in Rx path) + * o Allow setting frequency in Ad-Hoc mode + * o Disable WEP setting if !has_wep to work on old firmware + * o Fix txpower range + * o Start adding support for Samsung/Compaq firmware + * + * v0.02 -> v0.03 - 23/3/2001 - Jean II + * o Start adding Symbol support - need to check all that + * o Fix Prism2/Symbol WEP to accept 128 bits keys + * o Add Symbol WEP (add authentication type) + * o Add Prism2/Symbol rate + * o Add PM timeout (holdover duration) + * o Enable "iwconfig eth0 key off" and friends (toggle flags) + * o Enable "iwconfig eth0 power unicast/all" (toggle flags) + * o Try with an Intel card. It report firmware 1.01, behave like + * an antiquated firmware, however on windows it says 2.00. Yuck ! + * o Workaround firmware bug in allocate buffer (Intel 1.01) + * o Finish external renaming to orinoco... + * o Testing with various Wavelan firmwares + * + * v0.03 -> v0.04 - 30/3/2001 - Jean II + * o Update to Wireless 11 -> add retry limit/lifetime support + * o Tested with a D-Link DWL 650 card, fill in firmware support + * o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot) + * o Fixed the Prism2 WEP bugs that I introduced in v0.03 :-( + * It works on D-Link *only* after a tcpdump. Weird... + * And still doesn't work on Intel card. Grrrr... + * o Update the mode after a setport3 + * o Add preamble setting for Symbol cards (not yet enabled) + * o Don't complain as much about Symbol cards... + * + * v0.04 -> v0.04b - 22/4/2001 - David Gibson + * o Removed the 'eth' parameter - always use ethXX as the + * interface name instead of dldwdXX. The other was racy + * anyway. + * o Clean up RID definitions in hermes.h, other cleanups + * + * v0.04b -> v0.04c - 24/4/2001 - Jean II + * o Tim Hurley reported a D-Link card + * with vendor 02 and firmware 0.08. Added in the capabilities... + * o Tested Lucent firmware 7.28, everything works... + * + * v0.04c -> v0.05 - 3/5/2001 - Benjamin Herrenschmidt + * o Spin-off Pcmcia code. This file is renamed orinoco.c, + * and orinoco_cs.c now contains only the Pcmcia specific stuff + * o Add Airport driver support on top of orinoco.c (see airport.c) + * + * v0.05 -> v0.05a - 4/5/2001 - Jean II + * o Revert to old Pcmcia code to fix breakage of Ben's changes... + * + * v0.05a -> v0.05b - 4/5/2001 - Jean II + * o add module parameter 'ignore_cis_vcc' for D-Link @ 5V + * o D-Link firmware doesn't support multicast. We just print a few + * error messages, but otherwise everything works... + * o For David : set/getport3 works fine, just upgrade iwpriv... + * + * v0.05b -> v0.05c - 5/5/2001 - Benjamin Herrenschmidt + * o Adapt airport.c to latest changes in orinoco.c + * o Remove deferred power enabling code + * + * v0.05c -> v0.05d - 5/5/2001 - Jean II + * o Workaround to SNAP decapsulate frame from Linksys AP + * original patch from : Dong Liu + * (note : the memcmp bug was mine - fixed) + * o Remove set_retry stuff, no firmware support it (bloat--). + * + * v0.05d -> v0.06 - 25/5/2001 - Jean II + * Original patch from "Hong Lin" , + * "Ian Kinner" + * and "David Smith" + * o Init of priv->tx_rate_ctrl in firmware specific section. + * o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh ! + * o Spectrum card always need cor_reset (for every reset) + * o Fix cor_reset to not lose bit 7 in the register + * o flush_stale_links to remove zombie Pcmcia instances + * o Ack previous hermes event before reset + * Me (with my little hands) + * o Allow orinoco.c to call cor_reset via priv->card_reset_handler + * o Add priv->need_card_reset to toggle this feature + * o Fix various buglets when setting WEP in Symbol firmware + * Now, encryption is fully functional on Symbol cards. Youpi ! + * + * v0.06 -> v0.06b - 25/5/2001 - Jean II + * o IBSS on Symbol use port_mode = 4. Please don't ask... + * + * v0.06b -> v0.06c - 29/5/2001 - Jean II + * o Show first spy address in /proc/net/wireless for IBSS mode as well + * + * v0.06c -> v0.06d - 6/7/2001 - David Gibson + * o Change a bunch of KERN_INFO messages to KERN_DEBUG, as per Linus' + * wishes to reduce the number of unnecessary messages. + * o Removed bogus message on CRC error. + * o Merged fixes for v0.08 Prism 2 firmware from William Waghorn + * + * o Slight cleanup/re-arrangement of firmware detection code. + * + * v0.06d -> v0.06e - 1/8/2001 - David Gibson + * o Removed some redundant global initializers (orinoco_cs.c). + * o Added some module metadata + * + * v0.06e -> v0.06f - 14/8/2001 - David Gibson + * o Wording fix to license + * o Added a 'use_alternate_encaps' module parameter for APs which need an + * oui of 00:00:00. We really need a better way of handling this, but + * the module flag is better than nothing for now. + * + * v0.06f -> v0.07 - 20/8/2001 - David Gibson + * o Removed BAP error retries from hermes_bap_seek(). For Tx we now + * let the upper layers handle the retry, we retry explicitly in the + * Rx path, but don't make as much noise about it. + * o Firmware detection cleanups. + * + * v0.07 -> v0.07a - 1/10/3001 - Jean II + * o Add code to read Symbol firmware revision, inspired by latest code + * in Spectrum24 by Lee John Keyser-Allen - Thanks Lee ! + * o Thanks to Jared Valentine for "providing" me + * a 3Com card with a recent firmware, fill out Symbol firmware + * capabilities of latest rev (2.20), as well as older Symbol cards. + * o Disable Power Management in newer Symbol firmware, the API + * has changed (documentation needed). + * + * v0.07a -> v0.08 - 3/10/2001 - David Gibson + * o Fixed a possible buffer overrun found by the Stanford checker (in + * dldwd_ioctl_setiwencode()). Can only be called by root anyway, so not + * a big problem. + * o Turned has_big_wep on for Intersil cards. That's not true for all of + * them but we should at least let the capable ones try. + * o Wait for BUSY to clear at the beginning of hermes_bap_seek(). I + * realized that my assumption that the driver's serialization + * would prevent the BAP being busy on entry was possibly false, because + * things other than seeks may make the BAP busy. + * o Use "alternate" (oui 00:00:00) encapsulation by default. + * Setting use_old_encaps will mimic the old behaviour, but I think we + * will be able to eliminate this. + * o Don't try to make __initdata const (the version string). This can't + * work because of the way the __initdata sectioning works. + * o Added MODULE_LICENSE tags. + * o Support for PLX (transparent PCMCIA->PCI bridge) cards. + * o Changed to using the new type-fascist min/max. + * + * v0.08 -> v0.08a - 9/10/2001 - David Gibson + * o Inserted some missing acknowledgements/info into the Changelog. + * o Fixed some bugs in the normalization of signal level reporting. + * o Fixed bad bug in WEP key handling on Intersil and Symbol firmware, + * which led to an instant crash on big-endian machines. + * + * v0.08a -> v0.08b - 20/11/2001 - David Gibson + * o Lots of cleanup and bugfixes in orinoco_plx.c + * o Cleanup to handling of Tx rate setting. + * o Removed support for old encapsulation method. + * o Removed old "dldwd" names. + * o Split RID constants into a new file hermes_rid.h + * o Renamed RID constants to match linux-wlan-ng and prism2.o + * o Bugfixes in hermes.c + * o Poke the PLX's INTCSR register, so it actually starts + * generating interrupts. These cards might actually work now. + * o Update to wireless extensions v12 (Jean II) + * o Support for tallies and inquire command (Jean II) + * o Airport updates for newer PPC kernels (BenH) + * + * v0.08b -> v0.09 - 21/12/2001 - David Gibson + * o Some new PCI IDs for PLX cards. + * o Removed broken attempt to do ALLMULTI reception. Just use + * promiscuous mode instead + * o Preliminary work for list-AP (Jean II) + * o Airport updates from (BenH) + * o Eliminated racy hw_ready stuff + * o Fixed generation of fake events in irq handler. This should + * finally kill the EIO problems (Jean II & dgibson) + * o Fixed breakage of bitrate set/get on Agere firmware (Jean II) + * + * v0.09 -> v0.09a - 2/1/2002 - David Gibson + * o Fixed stupid mistake in multicast list handling, triggering + * a BUG() + * + * v0.09a -> v0.09b - 16/1/2002 - David Gibson + * o Fixed even stupider mistake in new interrupt handling, which + * seriously broke things on big-endian machines. + * o Removed a bunch of redundant includes and exports. + * o Removed a redundant MOD_{INC,DEC}_USE_COUNT pair in airport.c + * o Don't attempt to do hardware level multicast reception on + * Intersil firmware, just go promisc instead. + * o Typo fixed in hermes_issue_cmd() + * o Eliminated WIRELESS_SPY #ifdefs + * o Status code reported on Tx exceptions + * o Moved netif_wake_queue() from ALLOC interrupts to TX and TXEXC + * interrupts, which should fix the timeouts we're seeing. + * + * v0.09b -> v0.10 - 25 Feb 2002 - David Gibson + * o Removed nested structures used for header parsing, so the + * driver should now work without hackery on ARM + * o Fix for WEP handling on Intersil (Hawk Newton) + * o Eliminated the /proc/hermes/ethXX/regs debugging file. It + * was never very useful. + * o Make Rx errors less noisy. + * + * v0.10 -> v0.11 - 5 Apr 2002 - David Gibson + * o Laid the groundwork in hermes.[ch] for devices which map + * into PCI memory space rather than IO space. + * o Fixed bug in multicast handling (cleared multicast list when + * leaving promiscuous mode). + * o Relegated Tx error messages to debug. + * o Cleaned up / corrected handling of allocation lengths. + * o Set OWNSSID in IBSS mode for WinXP interoperability (jimc). + * o Change to using alloc_etherdev() for structure allocations. + * o Check for and drop undersized packets. + * o Fixed a race in stopping/waking the queue. This should fix + * the timeout problems (Pavel Roskin) + * o Reverted to netif_wake_queue() on the ALLOC event. + * o Fixes for recent Symbol firmwares which lack AP density + * (Pavel Roskin). + * + * v0.11 -> v0.11a - 29 Apr 2002 - David Gibson + * o Handle different register spacing, necessary for Prism 2.5 + * PCI adaptors (Steve Hill). + * o Cleaned up initialization of card structures in orinoco_cs + * and airport. Removed card->priv field. + * o Make response structure optional for hermes_docmd_wait() + * Pavel Roskin) + * o Added PCI id for Nortel emobility to orinoco_plx.c. + * o Cleanup to handling of Symbol's allocation bug. (Pavel Roskin) + * o Cleanups to firmware capability detection. + * o Arrange for orinoco_pci.c to override firmware detection. + * We should be able to support the PCI Intersil cards now. + * o Cleanup handling of reset_cor and hard_reset (Pavel Roskin). + * o Remove erroneous use of USER_BAP in the TxExc handler (Jouni + * Malinen). + * o Makefile changes for better integration into David Hinds + * pcmcia-cs package. + * + * v0.11a -> v0.11b - 1 May 2002 - David Gibson + * o Better error reporting in orinoco_plx_init_one() + * o Fixed multiple bad kfree() bugs introduced by the + * alloc_orinocodev() changes. + * + * v0.11b -> v0.12 - 19 Jun 2002 - David Gibson + * o Support changing the MAC address. + * o Correct display of Intersil firmware revision numbers. + * o Entirely revised locking scheme. Should be both simpler and + * better. + * o Merged some common code in orinoco_plx, orinoco_pci and + * airport by creating orinoco_default_{open,stop,reset}() + * which are used as the dev->open, dev->stop, priv->reset + * callbacks if none are specified when alloc_orinocodev() is + * called. + * o Removed orinoco_plx_interrupt() and orinoco_pci_interrupt(). + * They didn't do anything. + * + * v0.12 -> v0.12a - 4 Jul 2002 - David Gibson + * o Some rearrangement of code. + * o Numerous fixups to locking and rest handling, particularly + * for PCMCIA. + * o This allows open and stop net_device methods to be in + * orinoco.c now, rather than in the init modules. + * o In orinoco_cs.c link->priv now points to the struct + * net_device not to the struct orinoco_private. + * o Added a check for undersized SNAP frames, which could cause + * crashes. + * + * v0.12a -> v0.12b - 11 Jul 2002 - David Gibson + * o Fix hw->num_init testing code, so num_init is actually + * incremented. + * o Fix very stupid bug in orinoco_cs which broke compile with + * CONFIG_SMP. + * o Squashed a warning. + * + * v0.12b -> v0.12c - 26 Jul 2002 - David Gibson + * o Change to C9X style designated initializers. + * o Add support for 3Com AirConnect PCI. + * o No longer ignore the hard_reset argument to + * alloc_orinocodev(). Oops. + * + * v0.12c -> v0.13beta1 - 13 Sep 2002 - David Gibson + * o Revert the broken 0.12* locking scheme and go to a new yet + * simpler scheme. + * o Do firmware resets only in orinoco_init() and when waking + * the card from hard sleep. + * + * v0.13beta1 -> v0.13 - 27 Sep 2002 - David Gibson + * o Re-introduced full resets (via schedule_task()) on Tx + * timeout. + * + * v0.13 -> v0.13a - 30 Sep 2002 - David Gibson + * o Minor cleanups to info frame handling. Add basic support + * for linkstatus info frames. + * o Include required kernel headers in orinoco.h, to avoid + * compile problems. + * + * v0.13a -> v0.13b - 10 Feb 2003 - David Gibson + * o Implemented hard reset for Airport cards + * o Experimental suspend/resume implementation for orinoco_pci + * o Abolished /proc debugging support, replaced with a debugging + * iwpriv. Now it's ugly and simple instead of ugly and complex. + * o Bugfix in hermes.c if the firmware returned a record length + * of 0, we could go clobbering memory. + * o Bugfix in orinoco_stop() - it used to fail if hw_unavailable + * was set, which was usually true on PCMCIA hot removes. + * o Track LINKSTATUS messages, silently drop Tx packets before + * we are connected (avoids confusing the firmware), and only + * give LINKSTATUS printk()s if the status has changed. + * + * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson + * o Cleanup: use dev instead of priv in various places. + * o Bug fix: Don't ReleaseConfiguration on RESET_PHYSICAL event + * if we're in the middle of a (driver initiated) hard reset. + * o Bug fix: ETH_ZLEN is supposed to include the header + * (Dionysus Blazakis & Manish Karir) + * o Convert to using workqueues instead of taskqueues (and + * backwards compatibility macros for pre 2.5.41 kernels). + * o Drop redundant (I think...) MOD_{INC,DEC}_USE_COUNT in + * airport.c + * o New orinoco_tmd.c init module from Joerg Dorchain for + * TMD7160 based PCI to PCMCIA bridges (similar to + * orinoco_plx.c). + * + * v0.13c -> v0.13d - 22 Apr 2003 - David Gibson + * o Make hw_unavailable a counter, rather than just a flag, this + * is necessary to avoid some races (such as a card being + * removed in the middle of orinoco_reset(). + * o Restore Release/RequestConfiguration in the PCMCIA event handler + * when dealing with a driver initiated hard reset. This is + * necessary to prevent hangs due to a spurious interrupt while + * the reset is in progress. + * o Clear the 802.11 header when transmitting, even though we + * don't use it. This fixes a long standing bug on some + * firmwares, which seem to get confused if that isn't done. + * o Be less eager to de-encapsulate SNAP frames, only do so if + * the OUI is 00:00:00 or 00:00:f8, leave others alone. The old + * behaviour broke CDP (Cisco Discovery Protocol). + * o Use dev instead of priv for free_irq() as well as + * request_irq() (oops). + * o Attempt to reset rather than giving up if we get too many + * IRQs. + * o Changed semantics of __orinoco_down() so it can be called + * safely with hw_unavailable set. It also now clears the + * linkstatus (since we're going to have to reassociate). + * + * v0.13d -> v0.13e - 12 May 2003 - David Gibson + * o Support for post-2.5.68 return values from irq handler. + * o Fixed bug where underlength packets would be double counted + * in the rx_dropped statistics. + * o Provided a module parameter to suppress linkstatus messages. + * + * v0.13e -> v0.14alpha1 - 30 Sep 2003 - David Gibson + * o Replaced priv->connected logic with netif_carrier_on/off() + * calls. + * o Remove has_ibss_any and never set the CREATEIBSS RID when + * the ESSID is empty. Too many firmwares break if we do. + * o 2.6 merges: Replace pdev->slot_name with pci_name(), remove + * __devinitdata from PCI ID tables, use free_netdev(). + * o Enabled shared-key authentication for Agere firmware (from + * Robert J. Moore + * o Move netif_wake_queue() (back) to the Tx completion from the + * ALLOC event. This seems to prevent/mitigate the rolling + * error -110 problems at least on some Intersil firmwares. + * Theoretically reduces performance, but I can't measure it. + * Patch from Andrew Tridgell + * + * v0.14alpha1 -> v0.14alpha2 - 20 Oct 2003 - David Gibson + * o Correctly turn off shared-key authentication when requested + * (bugfix from Robert J. Moore). + * o Correct airport sleep interfaces for current 2.6 kernels. + * o Add code for key change without disabling/enabling the MAC + * port. This is supposed to allow 802.1x to work sanely, but + * doesn't seem to yet. + * * TODO + * o New wireless extensions API (patch from Moustafa + * Youssef, updated by Jim Carter and Pavel Roskin). * o Handle de-encapsulation within network layer, provide 802.11 * headers (patch from Thomas 'Dent' Mirlacher) + * o RF monitor mode support * o Fix possible races in SPY handling. * o Disconnect wireless extensions from fundamental configuration. * o (maybe) Software WEP support (patch from Stano Meduna). @@ -89,10 +462,7 @@ #include #include #include -#include #include -#include -#include #include #include @@ -126,10 +496,6 @@ static int ignore_disconnect; /* = 0 */ module_param(ignore_disconnect, int, 0644); MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer"); -static int force_monitor; /* = 0 */ -module_param(force_monitor, int, 0644); -MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); - /********************************************************************/ /* Compile time configuration and compatibility stuff */ /********************************************************************/ @@ -145,10 +511,6 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); /* Internal constants */ /********************************************************************/ -/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ -static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; -#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) - #define ORINOCO_MIN_MTU 256 #define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD) @@ -175,11 +537,6 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | HERMES_EV_WTERR | HERMES_EV_INFO \ | HERMES_EV_INFDROP ) -#define MAX_RID_LEN 1024 - -static const struct iw_handler_def orinoco_handler_def; -static struct ethtool_ops orinoco_ethtool_ops; - /********************************************************************/ /* Data tables */ /********************************************************************/ @@ -214,45 +571,26 @@ static struct { /* Data types */ /********************************************************************/ -/* Used in Event handling. - * We avoid nested structres as they break on ARM -- Moustafa */ -struct hermes_tx_descriptor_802_11 { - /* hermes_tx_descriptor */ - u16 status; - u16 reserved1; - u16 reserved2; - u32 sw_support; - u8 retry_count; - u8 tx_rate; - u16 tx_control; - - /* ieee802_11_hdr */ - u16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; - u16 data_len; - - /* ethhdr */ - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_proto; /* packet type ID field */ - - /* p8022_hdr */ +struct header_struct { + /* 802.3 */ + u8 dest[ETH_ALEN]; + u8 src[ETH_ALEN]; + u16 len; + /* 802.2 */ u8 dsap; u8 ssap; u8 ctrl; + /* SNAP */ u8 oui[3]; - u16 ethertype; } __attribute__ ((packed)); -/* Rx frame header except compatibility 802.3 header */ +/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ +u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; + +#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) + struct hermes_rx_descriptor { - /* Control */ u16 status; u32 time; u8 silence; @@ -260,24 +598,13 @@ struct hermes_rx_descriptor { u8 rate; u8 rxflow; u32 reserved; - - /* 802.11 header */ - u16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; - - /* Data length */ - u16 data_len; } __attribute__ ((packed)); /********************************************************************/ /* Function prototypes */ /********************************************************************/ +static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int __orinoco_program_rids(struct net_device *dev); static void __orinoco_set_multicast_list(struct net_device *dev); @@ -301,10 +628,6 @@ static inline void set_port_type(struct orinoco_private *priv) priv->createibss = 1; } break; - case IW_MODE_MONITOR: - priv->port_type = 3; - priv->createibss = 0; - break; default: printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", priv->ndev->name); @@ -491,7 +814,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) return 1; } - if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) { + if (! netif_carrier_ok(dev)) { /* Oops, the firmware hasn't established a connection, silently drop the packet (this seems to be the safest approach). */ @@ -628,55 +951,26 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) struct orinoco_private *priv = netdev_priv(dev); struct net_device_stats *stats = &priv->stats; u16 fid = hermes_read_regn(hw, TXCOMPLFID); - struct hermes_tx_descriptor_802_11 hdr; + struct hermes_tx_descriptor desc; int err = 0; if (fid == DUMMY_FID) return; /* Nothing's really happened */ - /* Read the frame header */ - err = hermes_bap_pread(hw, IRQ_BAP, &hdr, - sizeof(struct hermes_tx_descriptor) + - sizeof(struct ieee80211_hdr), - fid, 0); - - hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); - stats->tx_errors++; - + err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0); if (err) { printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " "(FID=%04X error %d)\n", dev->name, fid, err); - return; + } else { + DEBUG(1, "%s: Tx error, status %d\n", + dev->name, le16_to_cpu(desc.status)); } - DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name, - err, fid); - - /* We produce a TXDROP event only for retry or lifetime - * exceeded, because that's the only status that really mean - * that this particular node went away. - * Other errors means that *we* screwed up. - Jean II */ - hdr.status = le16_to_cpu(hdr.status); - if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { - union iwreq_data wrqu; - - /* Copy 802.11 dest address. - * We use the 802.11 header because the frame may - * not be 802.3 or may be mangled... - * In Ad-Hoc mode, it will be the node address. - * In managed mode, it will be most likely the AP addr - * User space will figure out how to convert it to - * whatever it needs (IP address or else). - * - Jean II */ - memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - - /* Send event to user space */ - wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL); - } + stats->tx_errors++; netif_wake_queue(dev); + hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); } static void orinoco_tx_timeout(struct net_device *dev) @@ -753,127 +1047,18 @@ static void orinoco_stat_gather(struct net_device *dev, } } -/* - * orinoco_rx_monitor - handle received monitor frames. - * - * Arguments: - * dev network device - * rxfid received FID - * desc rx descriptor of the frame - * - * Call context: interrupt - */ -static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, - struct hermes_rx_descriptor *desc) -{ - u32 hdrlen = 30; /* return full header by default */ - u32 datalen = 0; - u16 fc; - int err; - int len; - struct sk_buff *skb; - struct orinoco_private *priv = netdev_priv(dev); - struct net_device_stats *stats = &priv->stats; - hermes_t *hw = &priv->hw; - - len = le16_to_cpu(desc->data_len); - - /* Determine the size of the header and the data */ - fc = le16_to_cpu(desc->frame_ctl); - switch (fc & IEEE80211_FCTL_FTYPE) { - case IEEE80211_FTYPE_DATA: - if ((fc & IEEE80211_FCTL_TODS) - && (fc & IEEE80211_FCTL_FROMDS)) - hdrlen = 30; - else - hdrlen = 24; - datalen = len; - break; - case IEEE80211_FTYPE_MGMT: - hdrlen = 24; - datalen = len; - break; - case IEEE80211_FTYPE_CTL: - switch (fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_PSPOLL: - case IEEE80211_STYPE_RTS: - case IEEE80211_STYPE_CFEND: - case IEEE80211_STYPE_CFENDACK: - hdrlen = 16; - break; - case IEEE80211_STYPE_CTS: - case IEEE80211_STYPE_ACK: - hdrlen = 10; - break; - } - break; - default: - /* Unknown frame type */ - break; - } - - /* sanity check the length */ - if (datalen > IEEE80211_DATA_LEN + 12) { - printk(KERN_DEBUG "%s: oversized monitor frame, " - "data length = %d\n", dev->name, datalen); - err = -EIO; - stats->rx_length_errors++; - goto update_stats; - } - - skb = dev_alloc_skb(hdrlen + datalen); - if (!skb) { - printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n", - dev->name); - err = -ENOMEM; - goto drop; - } - - /* Copy the 802.11 header to the skb */ - memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen); - skb->mac.raw = skb->data; - - /* If any, copy the data from the card to the skb */ - if (datalen > 0) { - err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), - ALIGN(datalen, 2), rxfid, - HERMES_802_2_OFFSET); - if (err) { - printk(KERN_ERR "%s: error %d reading monitor frame\n", - dev->name, err); - goto drop; - } - } - - skb->dev = dev; - skb->ip_summed = CHECKSUM_NONE; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_802_2); - - dev->last_rx = jiffies; - stats->rx_packets++; - stats->rx_bytes += skb->len; - - netif_rx(skb); - return; - - drop: - dev_kfree_skb_irq(skb); - update_stats: - stats->rx_errors++; - stats->rx_dropped++; -} - static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) { struct orinoco_private *priv = netdev_priv(dev); struct net_device_stats *stats = &priv->stats; struct iw_statistics *wstats = &priv->wstats; struct sk_buff *skb = NULL; - u16 rxfid, status, fc; - int length; + u16 rxfid, status; + int length, data_len, data_off; + char *p; struct hermes_rx_descriptor desc; - struct ethhdr *hdr; + struct header_struct hdr; + struct ethhdr *eh; int err; rxfid = hermes_read_regn(hw, RXFID); @@ -883,46 +1068,53 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) if (err) { printk(KERN_ERR "%s: error %d reading Rx descriptor. " "Frame dropped.\n", dev->name, err); - goto update_stats; + stats->rx_errors++; + goto drop; } status = le16_to_cpu(desc.status); - if (status & HERMES_RXSTAT_BADCRC) { - DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", - dev->name); - stats->rx_crc_errors++; - goto update_stats; + if (status & HERMES_RXSTAT_ERR) { + if (status & HERMES_RXSTAT_UNDECRYPTABLE) { + wstats->discard.code++; + DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", + dev->name); + } else { + stats->rx_crc_errors++; + DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); + } + stats->rx_errors++; + goto drop; } - /* Handle frames in monitor mode */ - if (priv->iw_mode == IW_MODE_MONITOR) { - orinoco_rx_monitor(dev, rxfid, &desc); - return; - } + /* For now we ignore the 802.11 header completely, assuming + that the card's firmware has handled anything vital */ - if (status & HERMES_RXSTAT_UNDECRYPTABLE) { - DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", - dev->name); - wstats->discard.code++; - goto update_stats; + err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), + rxfid, HERMES_802_3_OFFSET); + if (err) { + printk(KERN_ERR "%s: error %d reading frame header. " + "Frame dropped.\n", dev->name, err); + stats->rx_errors++; + goto drop; } - length = le16_to_cpu(desc.data_len); - fc = le16_to_cpu(desc.frame_ctl); - + length = ntohs(hdr.len); + /* Sanity checks */ if (length < 3) { /* No for even an 802.2 LLC header */ /* At least on Symbol firmware with PCF we get quite a lot of these legitimately - Poll frames with no data. */ - return; + stats->rx_dropped++; + goto drop; } if (length > IEEE802_11_DATA_LEN) { printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", dev->name, length); stats->rx_length_errors++; - goto update_stats; + stats->rx_errors++; + goto drop; } /* We need space for the packet data itself, plus an ethernet @@ -934,53 +1126,60 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) if (!skb) { printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", dev->name); - goto update_stats; - } - - /* We'll prepend the header, so reserve space for it. The worst - case is no decapsulation, when 802.3 header is prepended and - nothing is removed. 2 is for aligning the IP header. */ - skb_reserve(skb, ETH_HLEN + 2); - - err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length), - ALIGN(length, 2), rxfid, - HERMES_802_2_OFFSET); - if (err) { - printk(KERN_ERR "%s: error %d reading frame. " - "Frame dropped.\n", dev->name, err); goto drop; } + skb_reserve(skb, 2); /* This way the IP header is aligned */ + /* Handle decapsulation * In most cases, the firmware tell us about SNAP frames. * For some reason, the SNAP frames sent by LinkSys APs * are not properly recognised by most firmwares. * So, check ourselves */ - if (length >= ENCAPS_OVERHEAD && - (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || - ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || - is_ethersnap(skb->data))) { + if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || + ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || + is_ethersnap(&hdr)) { /* These indicate a SNAP within 802.2 LLC within 802.11 frame which we'll need to de-encapsulate to the original EthernetII frame. */ - hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD); + + if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */ + stats->rx_length_errors++; + goto drop; + } + + /* Remove SNAP header, reconstruct EthernetII frame */ + data_len = length - ENCAPS_OVERHEAD; + data_off = HERMES_802_3_OFFSET + sizeof(hdr); + + eh = (struct ethhdr *)skb_put(skb, ETH_HLEN); + + memcpy(eh, &hdr, 2 * ETH_ALEN); + eh->h_proto = hdr.ethertype; } else { - /* 802.3 frame - prepend 802.3 header as is */ - hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN); - hdr->h_proto = htons(length); + /* All other cases indicate a genuine 802.3 frame. No + decapsulation needed. We just throw the whole + thing in, and hope the protocol layer can deal with + it as 802.3 */ + data_len = length; + data_off = HERMES_802_3_OFFSET; + /* FIXME: we re-read from the card data we already read here */ + } + + p = skb_put(skb, data_len); + err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2), + rxfid, data_off); + if (err) { + printk(KERN_ERR "%s: error %d reading frame. " + "Frame dropped.\n", dev->name, err); + stats->rx_errors++; + goto drop; } - memcpy(hdr->h_dest, desc.addr1, ETH_ALEN); - if (fc & IEEE80211_FCTL_FROMDS) - memcpy(hdr->h_source, desc.addr3, ETH_ALEN); - else - memcpy(hdr->h_source, desc.addr2, ETH_ALEN); dev->last_rx = jiffies; skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_NONE; - if (fc & IEEE80211_FCTL_TODS) - skb->pkt_type = PACKET_OTHERHOST; /* Process the wireless stats if needed */ orinoco_stat_gather(dev, skb, &desc); @@ -993,10 +1192,11 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) return; drop: - dev_kfree_skb_irq(skb); - update_stats: - stats->rx_errors++; stats->rx_dropped++; + + if (skb) + dev_kfree_skb_irq(skb); + return; } /********************************************************************/ @@ -1040,99 +1240,6 @@ static void print_linkstatus(struct net_device *dev, u16 status) dev->name, s, status); } -/* Search scan results for requested BSSID, join it if found */ -static void orinoco_join_ap(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - int err; - unsigned long flags; - struct join_req { - u8 bssid[ETH_ALEN]; - u16 channel; - } __attribute__ ((packed)) req; - const int atom_len = offsetof(struct prism2_scan_apinfo, atim); - struct prism2_scan_apinfo *atom; - int offset = 4; - u8 *buf; - u16 len; - - /* Allocate buffer for scan results */ - buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL); - if (! buf) - return; - - if (orinoco_lock(priv, &flags) != 0) - goto out; - - /* Sanity checks in case user changed something in the meantime */ - if (! priv->bssid_fixed) - goto out; - - if (strlen(priv->desired_essid) == 0) - goto out; - - /* Read scan results from the firmware */ - err = hermes_read_ltv(hw, USER_BAP, - HERMES_RID_SCANRESULTSTABLE, - MAX_SCAN_LEN, &len, buf); - if (err) { - printk(KERN_ERR "%s: Cannot read scan results\n", - dev->name); - goto out; - } - - len = HERMES_RECLEN_TO_BYTES(len); - - /* Go through the scan results looking for the channel of the AP - * we were requested to join */ - for (; offset + atom_len <= len; offset += atom_len) { - atom = (struct prism2_scan_apinfo *) (buf + offset); - if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) - goto found; - } - - DEBUG(1, "%s: Requested AP not found in scan results\n", - dev->name); - goto out; - - found: - memcpy(req.bssid, priv->desired_bssid, ETH_ALEN); - req.channel = atom->channel; /* both are little-endian */ - err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST, - &req); - if (err) - printk(KERN_ERR "%s: Error issuing join request\n", dev->name); - - out: - kfree(buf); - orinoco_unlock(priv, &flags); -} - -/* Send new BSSID to userspace */ -static void orinoco_send_wevents(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - union iwreq_data wrqu; - int err; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return; - - err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID, - ETH_ALEN, NULL, wrqu.ap_addr.sa_data); - if (err != 0) - return; - - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - - /* Send event to user space */ - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); - orinoco_unlock(priv, &flags); -} - static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) { struct orinoco_private *priv = netdev_priv(dev); @@ -1200,9 +1307,6 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) u16 newstatus; int connected; - if (priv->iw_mode == IW_MODE_MONITOR) - break; - if (len != sizeof(linkstatus)) { printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", dev->name, len); @@ -1215,15 +1319,6 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) break; newstatus = le16_to_cpu(linkstatus.linkstatus); - /* Symbol firmware uses "out of range" to signal that - * the hostscan frame can be requested. */ - if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE && - priv->firmware_type == FIRMWARE_TYPE_SYMBOL && - priv->has_hostscan && priv->scan_inprogress) { - hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL); - break; - } - connected = (newstatus == HERMES_LINKSTATUS_CONNECTED) || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE); @@ -1233,89 +1328,12 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) else if (!ignore_disconnect) netif_carrier_off(dev); - if (newstatus != priv->last_linkstatus) { - priv->last_linkstatus = newstatus; + if (newstatus != priv->last_linkstatus) print_linkstatus(dev, newstatus); - /* The info frame contains only one word which is the - * status (see hermes.h). The status is pretty boring - * in itself, that's why we export the new BSSID... - * Jean II */ - schedule_work(&priv->wevent_work); - } - } - break; - case HERMES_INQ_SCAN: - if (!priv->scan_inprogress && priv->bssid_fixed && - priv->firmware_type == FIRMWARE_TYPE_INTERSIL) { - schedule_work(&priv->join_work); - break; - } - /* fall through */ - case HERMES_INQ_HOSTSCAN: - case HERMES_INQ_HOSTSCAN_SYMBOL: { - /* Result of a scanning. Contains information about - * cells in the vicinity - Jean II */ - union iwreq_data wrqu; - unsigned char *buf; - - /* Sanity check */ - if (len > 4096) { - printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n", - dev->name, len); - break; - } - - /* We are a strict producer. If the previous scan results - * have not been consumed, we just have to drop this - * frame. We can't remove the previous results ourselves, - * that would be *very* racy... Jean II */ - if (priv->scan_result != NULL) { - printk(KERN_WARNING "%s: Previous scan results not consumed, dropping info frame.\n", dev->name); - break; - } - - /* Allocate buffer for results */ - buf = kmalloc(len, GFP_ATOMIC); - if (buf == NULL) - /* No memory, so can't printk()... */ - break; - /* Read scan data */ - err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, - infofid, sizeof(info)); - if (err) - break; - -#ifdef ORINOCO_DEBUG - { - int i; - printk(KERN_DEBUG "Scan result [%02X", buf[0]); - for(i = 1; i < (len * 2); i++) - printk(":%02X", buf[i]); - printk("]\n"); - } -#endif /* ORINOCO_DEBUG */ - - /* Allow the clients to access the results */ - priv->scan_len = len; - priv->scan_result = buf; - - /* Send an empty event to user space. - * We don't send the received data on the event because - * it would require us to do complex transcoding, and - * we want to minimise the work done in the irq handler - * Use a request to extract the data - Jean II */ - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); + priv->last_linkstatus = newstatus; } break; - case HERMES_INQ_SEC_STAT_AGERE: - /* Security status (Agere specific) */ - /* Ignore this frame for now */ - if (priv->firmware_type == FIRMWARE_TYPE_AGERE) - break; - /* fall through */ default: printk(KERN_DEBUG "%s: Unknown information frame received: " "type 0x%04x, length %d\n", dev->name, type, len); @@ -1452,36 +1470,6 @@ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) return err; } -/* Set fixed AP address */ -static int __orinoco_hw_set_wap(struct orinoco_private *priv) -{ - int roaming_flag; - int err = 0; - hermes_t *hw = &priv->hw; - - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: - /* not supported */ - break; - case FIRMWARE_TYPE_INTERSIL: - if (priv->bssid_fixed) - roaming_flag = 2; - else - roaming_flag = 1; - - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFROAMINGMODE, - roaming_flag); - break; - case FIRMWARE_TYPE_SYMBOL: - err = HERMES_WRITE_RECORD(hw, USER_BAP, - HERMES_RID_CNFMANDATORYBSSID_SYMBOL, - &priv->desired_bssid); - break; - } - return err; -} - /* Change the WEP keys and/or the current keys. Can be called * either from __orinoco_hw_setup_wep() or directly from * orinoco_ioctl_setiwencode(). In the later case the association @@ -1667,13 +1655,6 @@ static int __orinoco_program_rids(struct net_device *dev) } } - /* Set the desired BSSID */ - err = __orinoco_hw_set_wap(priv); - if (err) { - printk(KERN_ERR "%s: Error %d setting AP address\n", - dev->name, err); - return err; - } /* Set the desired ESSID */ idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); @@ -1812,20 +1793,6 @@ static int __orinoco_program_rids(struct net_device *dev) } } - if (priv->iw_mode == IW_MODE_MONITOR) { - /* Enable monitor mode */ - dev->type = ARPHRD_IEEE80211; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | - HERMES_TEST_MONITOR, 0, NULL); - } else { - /* Disable monitor mode */ - dev->type = ARPHRD_ETHER; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | - HERMES_TEST_STOP, 0, NULL); - } - if (err) - return err; - /* Set promiscuity / multicast*/ priv->promiscuous = 0; priv->mc_count = 0; @@ -1902,6 +1869,55 @@ __orinoco_set_multicast_list(struct net_device *dev) dev->flags &= ~IFF_PROMISC; } +static int orinoco_reconfigure(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct hermes *hw = &priv->hw; + unsigned long flags; + int err = 0; + + if (priv->broken_disableport) { + schedule_work(&priv->reset_work); + return 0; + } + + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + + err = hermes_disable_port(hw, 0); + if (err) { + printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n", + dev->name); + priv->broken_disableport = 1; + goto out; + } + + err = __orinoco_program_rids(dev); + if (err) { + printk(KERN_WARNING "%s: Unable to reconfigure card\n", + dev->name); + goto out; + } + + err = hermes_enable_port(hw, 0); + if (err) { + printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", + dev->name); + goto out; + } + + out: + if (err) { + printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); + schedule_work(&priv->reset_work); + err = 0; + } + + orinoco_unlock(priv, &flags); + return err; + +} + /* This must be called from user context, without locks held - use * schedule_work() */ static void orinoco_reset(struct net_device *dev) @@ -1930,11 +1946,6 @@ static void orinoco_reset(struct net_device *dev) orinoco_unlock(priv, &flags); - /* Scanning support: Cleanup of driver struct */ - kfree(priv->scan_result); - priv->scan_result = NULL; - priv->scan_inprogress = 0; - if (priv->hard_reset) { err = (*priv->hard_reset)(priv); if (err) { @@ -2173,8 +2184,6 @@ static int determine_firmware(struct net_device *dev) priv->has_mwo = (firmver >= 0x60000); priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ priv->ibss_port = 1; - priv->has_hostscan = (firmver >= 0x8000a); - priv->broken_monitor = (firmver >= 0x80000); /* Tested with Agere firmware : * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II @@ -2220,8 +2229,6 @@ static int determine_firmware(struct net_device *dev) priv->ibss_port = 4; priv->broken_disableport = (firmver == 0x25013) || (firmver >= 0x30000 && firmver <= 0x31000); - priv->has_hostscan = (firmver >= 0x31001) || - (firmver >= 0x29057 && firmver < 0x30000); /* Tested with Intel firmware : 0x20015 => Jean II */ /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */ break; @@ -2241,7 +2248,6 @@ static int determine_firmware(struct net_device *dev) priv->has_ibss = (firmver >= 0x000700); /* FIXME */ priv->has_big_wep = priv->has_wep = (firmver >= 0x000800); priv->has_pm = (firmver >= 0x000700); - priv->has_hostscan = (firmver >= 0x010301); if (firmver >= 0x000800) priv->ibss_port = 0; @@ -2450,9 +2456,8 @@ struct net_device *alloc_orinocodev(int sizeof_card, dev->tx_timeout = orinoco_tx_timeout; dev->watchdog_timeo = HZ; /* 1 second timeout */ dev->get_stats = orinoco_get_stats; - dev->ethtool_ops = &orinoco_ethtool_ops; dev->get_wireless_stats = orinoco_get_wireless_stats; - dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; + dev->do_ioctl = orinoco_ioctl; dev->change_mtu = orinoco_change_mtu; dev->set_multicast_list = orinoco_set_multicast_list; /* we use the default eth_mac_addr for setting the MAC addr */ @@ -2468,8 +2473,6 @@ struct net_device *alloc_orinocodev(int sizeof_card, * before anything else touches the * hardware */ INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); - INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev); - INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev); netif_carrier_off(dev); priv->last_linkstatus = 0xffff; @@ -2480,9 +2483,6 @@ struct net_device *alloc_orinocodev(int sizeof_card, void free_orinocodev(struct net_device *dev) { - struct orinoco_private *priv = netdev_priv(dev); - - kfree(priv->scan_result); free_netdev(dev); } @@ -2490,6 +2490,24 @@ void free_orinocodev(struct net_device *dev) /* Wireless extensions */ /********************************************************************/ +static int orinoco_hw_get_bssid(struct orinoco_private *priv, + char buf[ETH_ALEN]) +{ + hermes_t *hw = &priv->hw; + int err = 0; + unsigned long flags; + + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + + err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, + ETH_ALEN, NULL, buf); + + orinoco_unlock(priv, &flags); + + return err; +} + static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, char buf[IW_ESSID_MAX_SIZE+1]) { @@ -2615,271 +2633,140 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, return 0; } -static int orinoco_ioctl_getname(struct net_device *dev, - struct iw_request_info *info, - char *name, - char *extra) +static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq) { struct orinoco_private *priv = netdev_priv(dev); + int err = 0; + int mode; + struct iw_range range; int numrates; - int err; - - err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0); - - if (!err && (numrates > 2)) - strcpy(name, "IEEE 802.11b"); - else - strcpy(name, "IEEE 802.11-DS"); - - return 0; -} - -static int orinoco_ioctl_setwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ + int i, k; unsigned long flags; - static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* Enable automatic roaming - no sanity checks are needed */ - if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 || - memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) { - priv->bssid_fixed = 0; - memset(priv->desired_bssid, 0, ETH_ALEN); - - /* "off" means keep existing connection */ - if (ap_addr->sa_data[0] == 0) { - __orinoco_hw_set_wap(priv); - err = 0; - } - goto out; - } - - if (priv->firmware_type == FIRMWARE_TYPE_AGERE) { - printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't " - "support manual roaming\n", - dev->name); - err = -EOPNOTSUPP; - goto out; - } - if (priv->iw_mode != IW_MODE_INFRA) { - printk(KERN_WARNING "%s: Manual roaming supported only in " - "managed mode\n", dev->name); - err = -EOPNOTSUPP; - goto out; - } - - /* Intersil firmware hangs without Desired ESSID */ - if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL && - strlen(priv->desired_essid) == 0) { - printk(KERN_WARNING "%s: Desired ESSID must be set for " - "manual roaming\n", dev->name); - err = -EOPNOTSUPP; - goto out; - } - - /* Finally, enable manual roaming */ - priv->bssid_fixed = 1; - memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN); + TRACE_ENTER(dev->name); - out: - orinoco_unlock(priv, &flags); - return err; -} + if (!access_ok(VERIFY_WRITE, rrq->pointer, sizeof(range))) + return -EFAULT; -static int orinoco_ioctl_getwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - - hermes_t *hw = &priv->hw; - int err = 0; - unsigned long flags; + rrq->length = sizeof(range); if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - ap_addr->sa_family = ARPHRD_ETHER; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, - ETH_ALEN, NULL, ap_addr->sa_data); - + mode = priv->iw_mode; orinoco_unlock(priv, &flags); - return err; -} + memset(&range, 0, sizeof(range)); -static int orinoco_ioctl_setmode(struct net_device *dev, - struct iw_request_info *info, - u32 *mode, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; + /* Much of this shamelessly taken from wvlan_cs.c. No idea + * what it all means -dgibson */ + range.we_version_compiled = WIRELESS_EXT; + range.we_version_source = 11; - if (priv->iw_mode == *mode) - return 0; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - switch (*mode) { - case IW_MODE_ADHOC: - if (!priv->has_ibss && !priv->has_port3) - err = -EOPNOTSUPP; - break; - - case IW_MODE_INFRA: - break; - - case IW_MODE_MONITOR: - if (priv->broken_monitor && !force_monitor) { - printk(KERN_WARNING "%s: Monitor mode support is " - "buggy in this firmware, not enabling\n", - dev->name); - err = -EOPNOTSUPP; - } - break; - - default: - err = -EOPNOTSUPP; - break; - } - - if (err == -EINPROGRESS) { - priv->iw_mode = *mode; - set_port_type(priv); - } - - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getmode(struct net_device *dev, - struct iw_request_info *info, - u32 *mode, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - - *mode = priv->iw_mode; - return 0; -} - -static int orinoco_ioctl_getiwrange(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *rrq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int err = 0; - struct iw_range *range = (struct iw_range *) extra; - int numrates; - int i, k; - - TRACE_ENTER(dev->name); - - rrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 14; + range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ /* Set available channels/frequencies */ - range->num_channels = NUM_CHANNELS; + range.num_channels = NUM_CHANNELS; k = 0; for (i = 0; i < NUM_CHANNELS; i++) { if (priv->channel_mask & (1 << i)) { - range->freq[k].i = i + 1; - range->freq[k].m = channel_frequency[i] * 100000; - range->freq[k].e = 1; + range.freq[k].i = i + 1; + range.freq[k].m = channel_frequency[i] * 100000; + range.freq[k].e = 1; k++; } if (k >= IW_MAX_FREQUENCIES) break; } - range->num_frequency = k; - range->sensitivity = 3; - - if (priv->has_wep) { - range->max_encoding_tokens = ORINOCO_MAX_KEYS; - range->encoding_size[0] = SMALL_KEY_SIZE; - range->num_encoding_sizes = 1; + range.num_frequency = k; - if (priv->has_big_wep) { - range->encoding_size[1] = LARGE_KEY_SIZE; - range->num_encoding_sizes = 2; - } - } + range.sensitivity = 3; - if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ + if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ /* Quality stats meaningless in ad-hoc mode */ + range.max_qual.qual = 0; + range.max_qual.level = 0; + range.max_qual.noise = 0; + range.avg_qual.qual = 0; + range.avg_qual.level = 0; + range.avg_qual.noise = 0; } else { - range->max_qual.qual = 0x8b - 0x2f; - range->max_qual.level = 0x2f - 0x95 - 1; - range->max_qual.noise = 0x2f - 0x95 - 1; + range.max_qual.qual = 0x8b - 0x2f; + range.max_qual.level = 0x2f - 0x95 - 1; + range.max_qual.noise = 0x2f - 0x95 - 1; /* Need to get better values */ - range->avg_qual.qual = 0x24; - range->avg_qual.level = 0xC2; - range->avg_qual.noise = 0x9E; + range.avg_qual.qual = 0x24; + range.avg_qual.level = 0xC2; + range.avg_qual.noise = 0x9E; } err = orinoco_hw_get_bitratelist(priv, &numrates, - range->bitrate, IW_MAX_BITRATES); + range.bitrate, IW_MAX_BITRATES); if (err) return err; - range->num_bitrates = numrates; - + range.num_bitrates = numrates; + /* Set an indication of the max TCP throughput in bit/s that we can * expect using this interface. May be use for QoS stuff... * Jean II */ - if (numrates > 2) - range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ + if(numrates > 2) + range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ else - range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - range->min_pmp = 0; - range->max_pmp = 65535000; - range->min_pmt = 0; - range->max_pmt = 65535 * 1000; /* ??? */ - range->pmp_flags = IW_POWER_PERIOD; - range->pmt_flags = IW_POWER_TIMEOUT; - range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; - - range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; - range->retry_flags = IW_RETRY_LIMIT; - range->r_time_flags = IW_RETRY_LIFETIME; - range->min_retry = 0; - range->max_retry = 65535; /* ??? */ - range->min_r_time = 0; - range->max_r_time = 65535 * 1000; /* ??? */ + range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ + + range.min_rts = 0; + range.max_rts = 2347; + range.min_frag = 256; + range.max_frag = 2346; + + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + if (priv->has_wep) { + range.max_encoding_tokens = ORINOCO_MAX_KEYS; + + range.encoding_size[0] = SMALL_KEY_SIZE; + range.num_encoding_sizes = 1; + + if (priv->has_big_wep) { + range.encoding_size[1] = LARGE_KEY_SIZE; + range.num_encoding_sizes = 2; + } + } else { + range.num_encoding_sizes = 0; + range.max_encoding_tokens = 0; + } + orinoco_unlock(priv, &flags); + + range.min_pmp = 0; + range.max_pmp = 65535000; + range.min_pmt = 0; + range.max_pmt = 65535 * 1000; /* ??? */ + range.pmp_flags = IW_POWER_PERIOD; + range.pmt_flags = IW_POWER_TIMEOUT; + range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; + + range.num_txpower = 1; + range.txpower[0] = 15; /* 15dBm */ + range.txpower_capa = IW_TXPOW_DBM; + + range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; + range.retry_flags = IW_RETRY_LIMIT; + range.r_time_flags = IW_RETRY_LIFETIME; + range.min_retry = 0; + range.max_retry = 65535; /* ??? */ + range.min_r_time = 0; + range.max_r_time = 65535 * 1000; /* ??? */ + + if (copy_to_user(rrq->pointer, &range, sizeof(range))) + return -EFAULT; TRACE_EXIT(dev->name); return 0; } -static int orinoco_ioctl_setiwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *keybuf) +static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq) { struct orinoco_private *priv = netdev_priv(dev); int index = (erq->flags & IW_ENCODE_INDEX) - 1; @@ -2887,7 +2774,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, int enable = priv->wep_on; int restricted = priv->wep_restrict; u16 xlen = 0; - int err = -EINPROGRESS; /* Call commit handler */ + int err = 0; + char keybuf[ORINOCO_MAX_KEY_SIZE]; unsigned long flags; if (! priv->has_wep) @@ -2900,6 +2788,9 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) return -E2BIG; + + if (copy_from_user(keybuf, erq->pointer, erq->length)) + return -EFAULT; } if (orinoco_lock(priv, &flags) != 0) @@ -2973,14 +2864,12 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, return err; } -static int orinoco_ioctl_getiwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *keybuf) +static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq) { struct orinoco_private *priv = netdev_priv(dev); int index = (erq->flags & IW_ENCODE_INDEX) - 1; u16 xlen = 0; + char keybuf[ORINOCO_MAX_KEY_SIZE]; unsigned long flags; if (! priv->has_wep) @@ -3009,47 +2898,51 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); orinoco_unlock(priv, &flags); + + if (erq->pointer) { + if (copy_to_user(erq->pointer, keybuf, xlen)) + return -EFAULT; + } + return 0; } -static int orinoco_ioctl_setessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *essidbuf) +static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq) { struct orinoco_private *priv = netdev_priv(dev); + char essidbuf[IW_ESSID_MAX_SIZE+1]; unsigned long flags; /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it * anyway... - Jean II */ - /* Hum... Should not use Wireless Extension constant (may change), - * should use our own... - Jean II */ - if (erq->length > IW_ESSID_MAX_SIZE) - return -E2BIG; + memset(&essidbuf, 0, sizeof(essidbuf)); + + if (erq->flags) { + /* iwconfig includes the NUL in the specified length */ + if (erq->length > IW_ESSID_MAX_SIZE+1) + return -E2BIG; + + if (copy_from_user(&essidbuf, erq->pointer, erq->length)) + return -EFAULT; + + essidbuf[IW_ESSID_MAX_SIZE] = '\0'; + } if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */ - memset(priv->desired_essid, 0, sizeof(priv->desired_essid)); - - /* If not ANY, get the new ESSID */ - if (erq->flags) { - memcpy(priv->desired_essid, essidbuf, erq->length); - } + memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid)); orinoco_unlock(priv, &flags); - return -EINPROGRESS; /* Call commit handler */ + return 0; } -static int orinoco_ioctl_getessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *essidbuf) +static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) { struct orinoco_private *priv = netdev_priv(dev); + char essidbuf[IW_ESSID_MAX_SIZE+1]; int active; int err = 0; unsigned long flags; @@ -3063,46 +2956,51 @@ static int orinoco_ioctl_getessid(struct net_device *dev, } else { if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1); + memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf)); orinoco_unlock(priv, &flags); } erq->flags = 1; erq->length = strlen(essidbuf) + 1; + if (erq->pointer) + if (copy_to_user(erq->pointer, essidbuf, erq->length)) + return -EFAULT; TRACE_EXIT(dev->name); return 0; } -static int orinoco_ioctl_setnick(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *nrq, - char *nickbuf) +static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq) { struct orinoco_private *priv = netdev_priv(dev); + char nickbuf[IW_ESSID_MAX_SIZE+1]; unsigned long flags; if (nrq->length > IW_ESSID_MAX_SIZE) return -E2BIG; + memset(nickbuf, 0, sizeof(nickbuf)); + + if (copy_from_user(nickbuf, nrq->pointer, nrq->length)) + return -EFAULT; + + nickbuf[nrq->length] = '\0'; + if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - memset(priv->nick, 0, sizeof(priv->nick)); - memcpy(priv->nick, nickbuf, nrq->length); + memcpy(priv->nick, nickbuf, sizeof(priv->nick)); orinoco_unlock(priv, &flags); - return -EINPROGRESS; /* Call commit handler */ + return 0; } -static int orinoco_ioctl_getnick(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *nrq, - char *nickbuf) +static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) { struct orinoco_private *priv = netdev_priv(dev); + char nickbuf[IW_ESSID_MAX_SIZE+1]; unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -3113,22 +3011,23 @@ static int orinoco_ioctl_getnick(struct net_device *dev, nrq->length = strlen(nickbuf)+1; + if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf))) + return -EFAULT; + return 0; } -static int orinoco_ioctl_setfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *frq, - char *extra) +static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) { struct orinoco_private *priv = netdev_priv(dev); int chan = -1; unsigned long flags; - int err = -EINPROGRESS; /* Call commit handler */ - /* In infrastructure mode the AP sets the channel */ - if (priv->iw_mode == IW_MODE_INFRA) - return -EBUSY; + /* We can only use this in Ad-Hoc demo mode to set the operating + * frequency, or in IBSS mode to set the frequency where the IBSS + * will be created - Jean II */ + if (priv->iw_mode != IW_MODE_ADHOC) + return -EOPNOTSUPP; if ( (frq->e == 0) && (frq->m <= 1000) ) { /* Setting by channel number */ @@ -3152,44 +3051,13 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - priv->channel = chan; - if (priv->iw_mode == IW_MODE_MONITOR) { - /* Fast channel change - no commit if successful */ - hermes_t *hw = &priv->hw; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | - HERMES_TEST_SET_CHANNEL, - chan, NULL); - } orinoco_unlock(priv, &flags); - return err; -} - -static int orinoco_ioctl_getfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *frq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int tmp; - - /* Locking done in there */ - tmp = orinoco_hw_get_freq(priv); - if (tmp < 0) { - return tmp; - } - - frq->m = tmp; - frq->e = 1; - return 0; } -static int orinoco_ioctl_getsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *srq, - char *extra) +static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -3215,10 +3083,7 @@ static int orinoco_ioctl_getsens(struct net_device *dev, return 0; } -static int orinoco_ioctl_setsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *srq, - char *extra) +static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) { struct orinoco_private *priv = netdev_priv(dev); int val = srq->value; @@ -3235,13 +3100,10 @@ static int orinoco_ioctl_setsens(struct net_device *dev, priv->ap_density = val; orinoco_unlock(priv, &flags); - return -EINPROGRESS; /* Call commit handler */ + return 0; } -static int orinoco_ioctl_setrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) +static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) { struct orinoco_private *priv = netdev_priv(dev); int val = rrq->value; @@ -3259,30 +3121,13 @@ static int orinoco_ioctl_setrts(struct net_device *dev, priv->rts_thresh = val; orinoco_unlock(priv, &flags); - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_getrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - - rrq->value = priv->rts_thresh; - rrq->disabled = (rrq->value == 2347); - rrq->fixed = 1; - return 0; } -static int orinoco_ioctl_setfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, - char *extra) +static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) { struct orinoco_private *priv = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ + int err = 0; unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -3314,14 +3159,11 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, return err; } -static int orinoco_ioctl_getfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, - char *extra) +static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; - int err; + int err = 0; u16 val; unsigned long flags; @@ -3354,12 +3196,10 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, return err; } -static int orinoco_ioctl_setrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) +static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) { struct orinoco_private *priv = netdev_priv(dev); + int err = 0; int ratemode = -1; int bitrate; /* 100s of kilobits */ int i; @@ -3395,13 +3235,10 @@ static int orinoco_ioctl_setrate(struct net_device *dev, priv->bitratemode = ratemode; orinoco_unlock(priv, &flags); - return -EINPROGRESS; + return err; } -static int orinoco_ioctl_getrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) +static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -3466,13 +3303,10 @@ static int orinoco_ioctl_getrate(struct net_device *dev, return err; } -static int orinoco_ioctl_setpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *prq, - char *extra) +static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) { struct orinoco_private *priv = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ + int err = 0; unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -3521,10 +3355,7 @@ static int orinoco_ioctl_setpower(struct net_device *dev, return err; } -static int orinoco_ioctl_getpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *prq, - char *extra) +static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -3572,10 +3403,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev, return err; } -static int orinoco_ioctl_getretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) +static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -3626,38 +3454,10 @@ static int orinoco_ioctl_getretry(struct net_device *dev, return err; } -static int orinoco_ioctl_reset(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - - if (! capable(CAP_NET_ADMIN)) - return -EPERM; - - if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) { - printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); - - /* Firmware reset */ - orinoco_reset(dev); - } else { - printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); - - schedule_work(&priv->reset_work); - } - - return 0; -} - -static int orinoco_ioctl_setibssport(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) - +static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) { struct orinoco_private *priv = netdev_priv(dev); - int val = *( (int *) extra ); + int val = *( (int *) wrq->u.name ); unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -3669,28 +3469,28 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, set_port_type(priv); orinoco_unlock(priv, &flags); - return -EINPROGRESS; /* Call commit handler */ + return 0; } -static int orinoco_ioctl_getibssport(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) +static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq) { struct orinoco_private *priv = netdev_priv(dev); - int *val = (int *) extra; + int *val = (int *)wrq->u.name; + unsigned long flags; + + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; *val = priv->ibss_port; + orinoco_unlock(priv, &flags); + return 0; } -static int orinoco_ioctl_setport3(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) +static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) { struct orinoco_private *priv = netdev_priv(dev); - int val = *( (int *) extra ); + int val = *( (int *) wrq->u.name ); int err = 0; unsigned long flags; @@ -3719,131 +3519,51 @@ static int orinoco_ioctl_setport3(struct net_device *dev, err = -EINVAL; } - if (! err) { + if (! err) /* Actually update the mode we are using */ set_port_type(priv); - err = -EINPROGRESS; - } orinoco_unlock(priv, &flags); return err; } -static int orinoco_ioctl_getport3(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int *val = (int *) extra; - - *val = priv->prefer_port3; - return 0; -} - -static int orinoco_ioctl_setpreamble(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) +static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq) { struct orinoco_private *priv = netdev_priv(dev); + int *val = (int *)wrq->u.name; unsigned long flags; - int val; - - if (! priv->has_preamble) - return -EOPNOTSUPP; - - /* 802.11b has recently defined some short preamble. - * Basically, the Phy header has been reduced in size. - * This increase performance, especially at high rates - * (the preamble is transmitted at 1Mb/s), unfortunately - * this give compatibility troubles... - Jean II */ - val = *( (int *) extra ); if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - if (val) - priv->preamble = 1; - else - priv->preamble = 0; - + *val = priv->prefer_port3; orinoco_unlock(priv, &flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_getpreamble(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int *val = (int *) extra; - - if (! priv->has_preamble) - return -EOPNOTSUPP; - - *val = priv->preamble; return 0; } -/* ioctl interface to hermes_read_ltv() - * To use with iwpriv, pass the RID as the token argument, e.g. - * iwpriv get_rid [0xfc00] - * At least Wireless Tools 25 is required to use iwpriv. - * For Wireless Tools 25 and 26 append "dummy" are the end. */ -static int orinoco_ioctl_getrid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - hermes_t *hw = &priv->hw; - int rid = data->flags; - u16 length; - int err; - unsigned long flags; - - /* It's a "get" function, but we don't want users to access the - * WEP key and other raw firmware data */ - if (! capable(CAP_NET_ADMIN)) - return -EPERM; - - if (rid < 0xfc00 || rid > 0xffff) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, - extra); - if (err) - goto out; - - data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length), - MAX_RID_LEN); - - out: - orinoco_unlock(priv, &flags); - return err; -} - /* Spy is used for link quality/strength measurements in Ad-Hoc mode * Jean II */ -static int orinoco_ioctl_setspy(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *srq, - char *extra) - +static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) { struct orinoco_private *priv = netdev_priv(dev); - struct sockaddr *address = (struct sockaddr *) extra; + struct sockaddr address[IW_MAX_SPY]; int number = srq->length; int i; + int err = 0; unsigned long flags; + /* Check the number of addresses */ + if (number > IW_MAX_SPY) + return -E2BIG; + + /* Get the data in the driver */ + if (srq->pointer) { + if (copy_from_user(address, srq->pointer, + sizeof(struct sockaddr) * number)) + return -EFAULT; + } + /* Make sure nobody mess with the structure while we do */ if (orinoco_lock(priv, &flags) != 0) return -EBUSY; @@ -3867,17 +3587,14 @@ static int orinoco_ioctl_setspy(struct net_device *dev, /* Now, let the others play */ orinoco_unlock(priv, &flags); - /* Do NOT call commit handler */ - return 0; + return err; } -static int orinoco_ioctl_getspy(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *srq, - char *extra) +static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) { struct orinoco_private *priv = netdev_priv(dev); - struct sockaddr *address = (struct sockaddr *) extra; + struct sockaddr address[IW_MAX_SPY]; + struct iw_quality spy_stat[IW_MAX_SPY]; int number; int i; unsigned long flags; @@ -3886,12 +3603,7 @@ static int orinoco_ioctl_getspy(struct net_device *dev, return -EBUSY; number = priv->spy_number; - /* Create address struct */ - for (i = 0; i < number; i++) { - memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN); - address[i].sa_family = AF_UNIX; - } - if (number > 0) { + if ((number > 0) && (srq->pointer)) { /* Create address struct */ for (i = 0; i < number; i++) { memcpy(address[i].sa_data, priv->spy_address[i], @@ -3902,503 +3614,344 @@ static int orinoco_ioctl_getspy(struct net_device *dev, /* In theory, we should disable irqs while copying the stats * because the rx path might update it in the middle... * Bah, who care ? - Jean II */ - memcpy(extra + (sizeof(struct sockaddr) * number), - priv->spy_stat, sizeof(struct iw_quality) * number); + memcpy(&spy_stat, priv->spy_stat, + sizeof(struct iw_quality) * IW_MAX_SPY); + for (i=0; i < number; i++) + priv->spy_stat[i].updated = 0; } - /* Reset updated flags. */ - for (i = 0; i < number; i++) - priv->spy_stat[i].updated = 0; orinoco_unlock(priv, &flags); + /* Push stuff to user space */ srq->length = number; + if(copy_to_user(srq->pointer, address, + sizeof(struct sockaddr) * number)) + return -EFAULT; + if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number), + &spy_stat, sizeof(struct iw_quality) * number)) + return -EFAULT; return 0; } -/* Trigger a scan (look for other cells in the vicinity */ -static int orinoco_ioctl_setscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *srq, - char *extra) +static int +orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct orinoco_private *priv = netdev_priv(dev); - hermes_t *hw = &priv->hw; + struct iwreq *wrq = (struct iwreq *)rq; int err = 0; + int tmp; + int changed = 0; unsigned long flags; - /* Note : you may have realised that, as this is a SET operation, - * this is priviledged and therefore a normal user can't - * perform scanning. - * This is not an error, while the device perform scanning, - * traffic doesn't flow, so it's a perfect DoS... - * Jean II */ - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* Scanning with port 0 disabled would fail */ - if (!netif_running(dev)) { - err = -ENETDOWN; - goto out; - } + TRACE_ENTER(dev->name); - /* In monitor mode, the scan results are always empty. - * Probe responses are passed to the driver as received - * frames and could be processed in software. */ - if (priv->iw_mode == IW_MODE_MONITOR) { - err = -EOPNOTSUPP; - goto out; - } + /* In theory, we could allow most of the the SET stuff to be + * done. In practice, the lapse of time at startup when the + * card is not ready is very short, so why bother... Note + * that netif_device_present is different from up/down + * (ifconfig), when the device is not yet up, it is usually + * already ready... Jean II */ + if (! netif_device_present(dev)) + return -ENODEV; - /* Note : because we don't lock out the irq handler, the way - * we access scan variables in priv is critical. - * o scan_inprogress : not touched by irq handler - * o scan_mode : not touched by irq handler - * o scan_result : irq is strict producer, non-irq is strict - * consumer. - * o scan_len : synchronised with scan_result - * Before modifying anything on those variables, please think hard ! - * Jean II */ + switch (cmd) { + case SIOCGIWNAME: + strcpy(wrq->u.name, "IEEE 802.11-DS"); + break; + + case SIOCGIWAP: + wrq->u.ap_addr.sa_family = ARPHRD_ETHER; + err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data); + break; - /* If there is still some left-over scan results, get rid of it */ - if (priv->scan_result != NULL) { - /* What's likely is that a client did crash or was killed - * between triggering the scan request and reading the - * results, so we need to reset everything. - * Some clients that are too slow may suffer from that... - * Jean II */ - kfree(priv->scan_result); - priv->scan_result = NULL; - } + case SIOCGIWRANGE: + err = orinoco_ioctl_getiwrange(dev, &wrq->u.data); + break; - /* Save flags */ - priv->scan_mode = srq->flags; + case SIOCSIWMODE: + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + switch (wrq->u.mode) { + case IW_MODE_ADHOC: + if (! (priv->has_ibss || priv->has_port3) ) + err = -EINVAL; + else { + priv->iw_mode = IW_MODE_ADHOC; + changed = 1; + } + break; - /* Always trigger scanning, even if it's in progress. - * This way, if the info frame get lost, we will recover somewhat - * gracefully - Jean II */ + case IW_MODE_INFRA: + priv->iw_mode = IW_MODE_INFRA; + changed = 1; + break; - if (priv->has_hostscan) { - switch (priv->firmware_type) { - case FIRMWARE_TYPE_SYMBOL: - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFHOSTSCAN_SYMBOL, - HERMES_HOSTSCAN_SYMBOL_ONCE | - HERMES_HOSTSCAN_SYMBOL_BCAST); + default: + err = -EINVAL; break; - case FIRMWARE_TYPE_INTERSIL: { - u16 req[3]; - - req[0] = cpu_to_le16(0x3fff); /* All channels */ - req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ - req[2] = 0; /* Any ESSID */ - err = HERMES_WRITE_RECORD(hw, USER_BAP, - HERMES_RID_CNFHOSTSCAN, &req); } + set_port_type(priv); + orinoco_unlock(priv, &flags); + break; + + case SIOCGIWMODE: + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + wrq->u.mode = priv->iw_mode; + orinoco_unlock(priv, &flags); + break; + + case SIOCSIWENCODE: + err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding); + if (! err) + changed = 1; break; - case FIRMWARE_TYPE_AGERE: - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFSCANSSID_AGERE, - 0); /* Any ESSID */ - if (err) - break; - err = hermes_inquire(hw, HERMES_INQ_SCAN); + case SIOCGIWENCODE: + if (! capable(CAP_NET_ADMIN)) { + err = -EPERM; break; } - } else - err = hermes_inquire(hw, HERMES_INQ_SCAN); - /* One more client */ - if (! err) - priv->scan_inprogress = 1; + err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding); + break; - out: - orinoco_unlock(priv, &flags); - return err; -} + case SIOCSIWESSID: + err = orinoco_ioctl_setessid(dev, &wrq->u.essid); + if (! err) + changed = 1; + break; -/* Translate scan data returned from the card to a card independant - * format that the Wireless Tools will understand - Jean II */ -static inline int orinoco_translate_scan(struct net_device *dev, - char *buffer, - char *scan, - int scan_len) -{ - struct orinoco_private *priv = netdev_priv(dev); - int offset; /* In the scan data */ - union hermes_scan_info *atom; - int atom_len; - u16 capabilities; - u16 channel; - struct iw_event iwe; /* Temporary buffer */ - char * current_ev = buffer; - char * end_buf = buffer + IW_SCAN_MAX_DATA; + case SIOCGIWESSID: + err = orinoco_ioctl_getessid(dev, &wrq->u.essid); + break; - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: - atom_len = sizeof(struct agere_scan_apinfo); - offset = 0; + case SIOCSIWNICKN: + err = orinoco_ioctl_setnick(dev, &wrq->u.data); + if (! err) + changed = 1; break; - case FIRMWARE_TYPE_SYMBOL: - /* Lack of documentation necessitates this hack. - * Different firmwares have 68 or 76 byte long atoms. - * We try modulo first. If the length divides by both, - * we check what would be the channel in the second - * frame for a 68-byte atom. 76-byte atoms have 0 there. - * Valid channel cannot be 0. */ - if (scan_len % 76) - atom_len = 68; - else if (scan_len % 68) - atom_len = 76; - else if (scan_len >= 1292 && scan[68] == 0) - atom_len = 76; - else - atom_len = 68; - offset = 0; + + case SIOCGIWNICKN: + err = orinoco_ioctl_getnick(dev, &wrq->u.data); break; - case FIRMWARE_TYPE_INTERSIL: - offset = 4; - if (priv->has_hostscan) - atom_len = scan[0] + (scan[1] << 8); - else - atom_len = offsetof(struct prism2_scan_apinfo, atim); + + case SIOCGIWFREQ: + tmp = orinoco_hw_get_freq(priv); + if (tmp < 0) { + err = tmp; + } else { + wrq->u.freq.m = tmp; + wrq->u.freq.e = 1; + } break; - default: - return 0; - } - /* Check that we got an whole number of atoms */ - if ((scan_len - offset) % atom_len) { - printk(KERN_ERR "%s: Unexpected scan data length %d, " - "atom_len %d, offset %d\n", dev->name, scan_len, - atom_len, offset); - return 0; - } + case SIOCSIWFREQ: + err = orinoco_ioctl_setfreq(dev, &wrq->u.freq); + if (! err) + changed = 1; + break; - /* Read the entries one by one */ - for (; offset + atom_len <= scan_len; offset += atom_len) { - /* Get next atom */ - atom = (union hermes_scan_info *) (scan + offset); - - /* First entry *MUST* be the AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); - - /* Other entries will be displayed in the order we give them */ - - /* Add the ESSID */ - iwe.u.data.length = le16_to_cpu(atom->a.essid_len); - if (iwe.u.data.length > 32) - iwe.u.data.length = 32; - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid); - - /* Add mode */ - iwe.cmd = SIOCGIWMODE; - capabilities = le16_to_cpu(atom->a.capabilities); - if (capabilities & 0x3) { - if (capabilities & 0x1) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); - } + case SIOCGIWSENS: + err = orinoco_ioctl_getsens(dev, &wrq->u.sens); + break; - channel = atom->s.channel; - if ( (channel >= 1) && (channel <= NUM_CHANNELS) ) { - /* Add frequency */ - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = channel_frequency[channel-1] * 100000; - iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(current_ev, end_buf, - &iwe, IW_EV_FREQ_LEN); - } + case SIOCSIWSENS: + err = orinoco_ioctl_setsens(dev, &wrq->u.sens); + if (! err) + changed = 1; + break; - /* Add quality statistics */ - iwe.cmd = IWEVQUAL; - iwe.u.qual.updated = 0x10; /* no link quality */ - iwe.u.qual.level = (__u8) le16_to_cpu(atom->a.level) - 0x95; - iwe.u.qual.noise = (__u8) le16_to_cpu(atom->a.noise) - 0x95; - /* Wireless tools prior to 27.pre22 will show link quality - * anyway, so we provide a reasonable value. */ - if (iwe.u.qual.level > iwe.u.qual.noise) - iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; - else - iwe.u.qual.qual = 0; - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + case SIOCGIWRTS: + wrq->u.rts.value = priv->rts_thresh; + wrq->u.rts.disabled = (wrq->u.rts.value == 2347); + wrq->u.rts.fixed = 1; + break; - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (capabilities & 0x10) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid); - - /* Bit rate is not available in Lucent/Agere firmwares */ - if (priv->firmware_type != FIRMWARE_TYPE_AGERE) { - char * current_val = current_ev + IW_EV_LCP_LEN; - int i; - int step; - - if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) - step = 2; - else - step = 1; - - iwe.cmd = SIOCGIWRATE; - /* Those two flags are ignored... */ - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - /* Max 10 values */ - for (i = 0; i < 10; i += step) { - /* NULL terminated */ - if (atom->p.rates[i] == 0x0) - break; - /* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000); - current_val = iwe_stream_add_value(current_ev, current_val, - end_buf, &iwe, - IW_EV_PARAM_LEN); - } - /* Check if we added any event */ - if ((current_val - current_ev) > IW_EV_LCP_LEN) - current_ev = current_val; - } + case SIOCSIWRTS: + err = orinoco_ioctl_setrts(dev, &wrq->u.rts); + if (! err) + changed = 1; + break; - /* The other data in the scan result are not really - * interesting, so for now drop it - Jean II */ - } - return current_ev - buffer; -} + case SIOCSIWFRAG: + err = orinoco_ioctl_setfrag(dev, &wrq->u.frag); + if (! err) + changed = 1; + break; -/* Return results of a scan */ -static int orinoco_ioctl_getscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *srq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int err = 0; - unsigned long flags; + case SIOCGIWFRAG: + err = orinoco_ioctl_getfrag(dev, &wrq->u.frag); + break; - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; + case SIOCSIWRATE: + err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate); + if (! err) + changed = 1; + break; - /* If no results yet, ask to try again later */ - if (priv->scan_result == NULL) { - if (priv->scan_inprogress) - /* Important note : we don't want to block the caller - * until results are ready for various reasons. - * First, managing wait queues is complex and racy. - * Second, we grab some rtnetlink lock before comming - * here (in dev_ioctl()). - * Third, we generate an Wireless Event, so the - * caller can wait itself on that - Jean II */ - err = -EAGAIN; - else - /* Client error, no scan results... - * The caller need to restart the scan. */ - err = -ENODATA; - } else { - /* We have some results to push back to user space */ - - /* Translate to WE format */ - srq->length = orinoco_translate_scan(dev, extra, - priv->scan_result, - priv->scan_len); - - /* Return flags */ - srq->flags = (__u16) priv->scan_mode; - - /* Results are here, so scan no longer in progress */ - priv->scan_inprogress = 0; - - /* In any case, Scan results will be cleaned up in the - * reset function and when exiting the driver. - * The person triggering the scanning may never come to - * pick the results, so we need to do it in those places. - * Jean II */ - -#ifdef SCAN_SINGLE_READ - /* If you enable this option, only one client (the first - * one) will be able to read the result (and only one - * time). If there is multiple concurent clients that - * want to read scan results, this behavior is not - * advisable - Jean II */ - kfree(priv->scan_result); - priv->scan_result = NULL; -#endif /* SCAN_SINGLE_READ */ - /* Here, if too much time has elapsed since last scan, - * we may want to clean up scan results... - Jean II */ - } - - orinoco_unlock(priv, &flags); - return err; -} + case SIOCGIWRATE: + err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate); + break; -/* Commit handler, called after set operations */ -static int orinoco_ioctl_commit(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - unsigned long flags; - int err = 0; + case SIOCSIWPOWER: + err = orinoco_ioctl_setpower(dev, &wrq->u.power); + if (! err) + changed = 1; + break; - if (!priv->open) - return 0; + case SIOCGIWPOWER: + err = orinoco_ioctl_getpower(dev, &wrq->u.power); + break; - if (priv->broken_disableport) { - orinoco_reset(dev); - return 0; - } + case SIOCGIWTXPOW: + /* The card only supports one tx power, so this is easy */ + wrq->u.txpower.value = 15; /* dBm */ + wrq->u.txpower.fixed = 1; + wrq->u.txpower.disabled = 0; + wrq->u.txpower.flags = IW_TXPOW_DBM; + break; - if (orinoco_lock(priv, &flags) != 0) - return err; + case SIOCSIWRETRY: + err = -EOPNOTSUPP; + break; - err = hermes_disable_port(hw, 0); - if (err) { - printk(KERN_WARNING "%s: Unable to disable port " - "while reconfiguring card\n", dev->name); - priv->broken_disableport = 1; - goto out; - } + case SIOCGIWRETRY: + err = orinoco_ioctl_getretry(dev, &wrq->u.retry); + break; - err = __orinoco_program_rids(dev); - if (err) { - printk(KERN_WARNING "%s: Unable to reconfigure card\n", - dev->name); - goto out; - } + case SIOCSIWSPY: + err = orinoco_ioctl_setspy(dev, &wrq->u.data); + break; - err = hermes_enable_port(hw, 0); - if (err) { - printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", - dev->name); - goto out; - } + case SIOCGIWSPY: + err = orinoco_ioctl_getspy(dev, &wrq->u.data); + break; + + case SIOCGIWPRIV: + if (wrq->u.data.pointer) { + struct iw_priv_args privtab[] = { + { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, + { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, + { SIOCIWFIRSTPRIV + 0x2, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_port3" }, + { SIOCIWFIRSTPRIV + 0x3, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_port3" }, + { SIOCIWFIRSTPRIV + 0x4, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_preamble" }, + { SIOCIWFIRSTPRIV + 0x5, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_preamble" }, + { SIOCIWFIRSTPRIV + 0x6, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_ibssport" }, + { SIOCIWFIRSTPRIV + 0x7, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_ibssport" }, + }; + + wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); + if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab))) + err = -EFAULT; + } + break; + + case SIOCIWFIRSTPRIV + 0x0: /* force_reset */ + case SIOCIWFIRSTPRIV + 0x1: /* card_reset */ + if (! capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } + + printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); - out: - if (err) { - printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); schedule_work(&priv->reset_work); - err = 0; - } + break; - orinoco_unlock(priv, &flags); - return err; -} + case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */ + if (! capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } -static const struct iw_priv_args orinoco_privtab[] = { - { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, - { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, - { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_port3" }, - { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_port3" }, - { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_preamble" }, - { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_preamble" }, - { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_ibssport" }, - { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_ibssport" }, - { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN, - "get_rid" }, -}; + err = orinoco_ioctl_setport3(dev, wrq); + if (! err) + changed = 1; + break; + case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */ + err = orinoco_ioctl_getport3(dev, wrq); + break; -/* - * Structures to export the Wireless Handlers - */ + case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */ + if (! capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } -static const iw_handler orinoco_handler[] = { - [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit, - [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname, - [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq, - [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq, - [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode, - [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode, - [SIOCSIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens, - [SIOCGIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens, - [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange, - [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy, - [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy, - [SIOCSIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setwap, - [SIOCGIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap, - [SIOCSIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setscan, - [SIOCGIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getscan, - [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid, - [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid, - [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick, - [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick, - [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate, - [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate, - [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts, - [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts, - [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag, - [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag, - [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry, - [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode, - [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode, - [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower, - [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower, -}; + /* 802.11b has recently defined some short preamble. + * Basically, the Phy header has been reduced in size. + * This increase performance, especially at high rates + * (the preamble is transmitted at 1Mb/s), unfortunately + * this give compatibility troubles... - Jean II */ + if(priv->has_preamble) { + int val = *( (int *) wrq->u.name ); + + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + if (val) + priv->preamble = 1; + else + priv->preamble = 0; + orinoco_unlock(priv, &flags); + changed = 1; + } else + err = -EOPNOTSUPP; + break; + case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */ + if(priv->has_preamble) { + int *val = (int *)wrq->u.name; -/* - Added typecasting since we no longer use iwreq_data -- Moustafa - */ -static const iw_handler orinoco_private_handler[] = { - [0] (iw_handler) orinoco_ioctl_reset, - [1] (iw_handler) orinoco_ioctl_reset, - [2] (iw_handler) orinoco_ioctl_setport3, - [3] (iw_handler) orinoco_ioctl_getport3, - [4] (iw_handler) orinoco_ioctl_setpreamble, - [5] (iw_handler) orinoco_ioctl_getpreamble, - [6] (iw_handler) orinoco_ioctl_setibssport, - [7] (iw_handler) orinoco_ioctl_getibssport, - [9] (iw_handler) orinoco_ioctl_getrid, -}; + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + *val = priv->preamble; + orinoco_unlock(priv, &flags); + } else + err = -EOPNOTSUPP; + break; + case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */ + if (! capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } -static const struct iw_handler_def orinoco_handler_def = { - .num_standard = ARRAY_SIZE(orinoco_handler), - .num_private = ARRAY_SIZE(orinoco_private_handler), - .num_private_args = ARRAY_SIZE(orinoco_privtab), - .standard = orinoco_handler, - .private = orinoco_private_handler, - .private_args = orinoco_privtab, -}; + err = orinoco_ioctl_setibssport(dev, wrq); + if (! err) + changed = 1; + break; -static void orinoco_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct orinoco_private *priv = netdev_priv(dev); + case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */ + err = orinoco_ioctl_getibssport(dev, wrq); + break; - strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1); - strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1); - strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1); - if (dev->class_dev.dev) - strncpy(info->bus_info, dev->class_dev.dev->bus_id, - sizeof(info->bus_info) - 1); - else - snprintf(info->bus_info, sizeof(info->bus_info) - 1, - "PCMCIA %p", priv->hw.iobase); + default: + err = -EOPNOTSUPP; + } + + if (! err && changed && netif_running(dev)) { + err = orinoco_reconfigure(dev); + } + + TRACE_EXIT(dev->name); + + return err; } -static struct ethtool_ops orinoco_ethtool_ops = { - .get_drvinfo = orinoco_get_drvinfo, - .get_link = ethtool_op_get_link, -}; /********************************************************************/ /* Debugging */ diff --git a/trunk/drivers/net/wireless/orinoco.h b/trunk/drivers/net/wireless/orinoco.h index 2f213a7103fe..f749b50d1088 100644 --- a/trunk/drivers/net/wireless/orinoco.h +++ b/trunk/drivers/net/wireless/orinoco.h @@ -7,7 +7,7 @@ #ifndef _ORINOCO_H #define _ORINOCO_H -#define DRIVER_VERSION "0.15rc2" +#define DRIVER_VERSION "0.14alpha2" #include #include @@ -22,8 +22,6 @@ #define WIRELESS_SPY // enable iwspy support -#define MAX_SCAN_LEN 4096 - #define ORINOCO_MAX_KEY_SIZE 14 #define ORINOCO_MAX_KEYS 4 @@ -32,20 +30,6 @@ struct orinoco_key { char data[ORINOCO_MAX_KEY_SIZE]; } __attribute__ ((packed)); -struct header_struct { - /* 802.3 */ - u8 dest[ETH_ALEN]; - u8 src[ETH_ALEN]; - u16 len; - /* 802.2 */ - u8 dsap; - u8 ssap; - u8 ctrl; - /* SNAP */ - u8 oui[3]; - u16 ethertype; -} __attribute__ ((packed)); - typedef enum { FIRMWARE_TYPE_AGERE, FIRMWARE_TYPE_INTERSIL, @@ -64,8 +48,6 @@ struct orinoco_private { /* driver state */ int open; u16 last_linkstatus; - struct work_struct join_work; - struct work_struct wevent_work; /* Net device stuff */ struct net_device *ndev; @@ -92,9 +74,7 @@ struct orinoco_private { unsigned int has_pm:1; unsigned int has_preamble:1; unsigned int has_sensitivity:1; - unsigned int has_hostscan:1; unsigned int broken_disableport:1; - unsigned int broken_monitor:1; /* Configuration paramaters */ u32 iw_mode; @@ -104,8 +84,6 @@ struct orinoco_private { int bitratemode; char nick[IW_ESSID_MAX_SIZE+1]; char desired_essid[IW_ESSID_MAX_SIZE+1]; - char desired_bssid[ETH_ALEN]; - int bssid_fixed; u16 frag_thresh, mwo_robust; u16 channel; u16 ap_density, rts_thresh; @@ -120,12 +98,6 @@ struct orinoco_private { /* Configuration dependent variables */ int port_type, createibss; int promiscuous, mc_count; - - /* Scanning support */ - int scan_inprogress; /* Scan pending... */ - u32 scan_mode; /* Type of scan done */ - char * scan_result; /* Result of previous scan */ - int scan_len; /* Lenght of result */ }; #ifdef ORINOCO_DEBUG diff --git a/trunk/drivers/net/wireless/prism54/isl_38xx.c b/trunk/drivers/net/wireless/prism54/isl_38xx.c index adc7499136dc..4481ec18c5a0 100644 --- a/trunk/drivers/net/wireless/prism54/isl_38xx.c +++ b/trunk/drivers/net/wireless/prism54/isl_38xx.c @@ -112,10 +112,10 @@ isl38xx_handle_wakeup(isl38xx_control_block *control_block, void isl38xx_trigger_device(int asleep, void __iomem *device_base) { + struct timeval current_time; u32 reg, counter = 0; #if VERBOSE > SHOW_ERROR_MESSAGES - struct timeval current_time; DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n"); #endif @@ -126,11 +126,11 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) do_gettimeofday(¤t_time); DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n", current_time.tv_sec, (long)current_time.tv_usec); +#endif DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", current_time.tv_sec, (long)current_time.tv_usec, readl(device_base + ISL38XX_CTRL_STAT_REG)); -#endif udelay(ISL38XX_WRITEIO_DELAY); reg = readl(device_base + ISL38XX_INT_IDENT_REG); @@ -148,12 +148,10 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) counter++; } -#if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", current_time.tv_sec, (long)current_time.tv_usec, readl(device_base + ISL38XX_CTRL_STAT_REG)); -#endif udelay(ISL38XX_WRITEIO_DELAY); #if VERBOSE > SHOW_ERROR_MESSAGES diff --git a/trunk/drivers/scsi/libata-scsi.c b/trunk/drivers/scsi/libata-scsi.c index 794fb559efb0..7a4adc4c8f09 100644 --- a/trunk/drivers/scsi/libata-scsi.c +++ b/trunk/drivers/scsi/libata-scsi.c @@ -1176,12 +1176,8 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, n_sectors = ata_id_u32(args->id, 60); n_sectors--; /* ATA TotalUserSectors - 1 */ + tmp = n_sectors; /* note: truncates, if lba48 */ if (args->cmd->cmnd[0] == READ_CAPACITY) { - if( n_sectors >= 0xffffffffULL ) - tmp = 0xffffffff ; /* Return max count on overflow */ - else - tmp = n_sectors ; - /* sector count, 32-bit */ rbuf[0] = tmp >> (8 * 3); rbuf[1] = tmp >> (8 * 2); @@ -1195,12 +1191,10 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, } else { /* sector count, 64-bit */ - tmp = n_sectors >> (8 * 4); - rbuf[2] = tmp >> (8 * 3); - rbuf[3] = tmp >> (8 * 2); - rbuf[4] = tmp >> (8 * 1); - rbuf[5] = tmp; - tmp = n_sectors; + rbuf[2] = n_sectors >> (8 * 7); + rbuf[3] = n_sectors >> (8 * 6); + rbuf[4] = n_sectors >> (8 * 5); + rbuf[5] = n_sectors >> (8 * 4); rbuf[6] = tmp >> (8 * 3); rbuf[7] = tmp >> (8 * 2); rbuf[8] = tmp >> (8 * 1); diff --git a/trunk/drivers/usb/Makefile b/trunk/drivers/usb/Makefile index a708a1dbb530..a61d4433a989 100644 --- a/trunk/drivers/usb/Makefile +++ b/trunk/drivers/usb/Makefile @@ -31,7 +31,6 @@ obj-$(CONFIG_USB_MOUSE) += input/ obj-$(CONFIG_USB_MTOUCH) += input/ obj-$(CONFIG_USB_POWERMATE) += input/ obj-$(CONFIG_USB_WACOM) += input/ -obj-$(CONFIG_USB_ACECAD) += input/ obj-$(CONFIG_USB_XPAD) += input/ obj-$(CONFIG_USB_DABUSB) += media/ diff --git a/trunk/drivers/usb/input/Kconfig b/trunk/drivers/usb/input/Kconfig index fd59f6bdd67f..d28e7eab6f98 100644 --- a/trunk/drivers/usb/input/Kconfig +++ b/trunk/drivers/usb/input/Kconfig @@ -151,18 +151,6 @@ config USB_WACOM To compile this driver as a module, choose M here: the module will be called wacom. -config USB_ACECAD - tristate "Acecad Flair tablet support" - depends on USB && INPUT - help - Say Y here if you want to use the USB version of the Acecad Flair - tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - To compile this driver as a module, choose M here: the - module will be called acecad. - config USB_KBTAB tristate "KB Gear JamStudio tablet support" depends on USB && INPUT @@ -202,18 +190,6 @@ config USB_MTOUCH To compile this driver as a module, choose M here: the module will be called mtouchusb. -config USB_ITMTOUCH - tristate "ITM Touch USB Touchscreen Driver" - depends on USB && INPUT - ---help--- - Say Y here if you want to use a ITM Touch USB - Touchscreen controller. - - This touchscreen is used in LG 1510SF monitors. - - To compile this driver as a module, choose M here: the - module will be called itmtouch. - config USB_EGALAX tristate "eGalax TouchKit USB Touchscreen Driver" depends on USB && INPUT diff --git a/trunk/drivers/usb/input/Makefile b/trunk/drivers/usb/input/Makefile index 831b2b0f1f05..6bcedd16b0a1 100644 --- a/trunk/drivers/usb/input/Makefile +++ b/trunk/drivers/usb/input/Makefile @@ -33,9 +33,7 @@ obj-$(CONFIG_USB_KBD) += usbkbd.o obj-$(CONFIG_USB_KBTAB) += kbtab.o obj-$(CONFIG_USB_MOUSE) += usbmouse.o obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o -obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o obj-$(CONFIG_USB_EGALAX) += touchkitusb.o obj-$(CONFIG_USB_POWERMATE) += powermate.o obj-$(CONFIG_USB_WACOM) += wacom.o -obj-$(CONFIG_USB_ACECAD) += acecad.o obj-$(CONFIG_USB_XPAD) += xpad.o diff --git a/trunk/drivers/usb/input/acecad.c b/trunk/drivers/usb/input/acecad.c deleted file mode 100644 index ebcf7c955800..000000000000 --- a/trunk/drivers/usb/input/acecad.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2001-2005 Edouard TISSERANT - * Copyright (c) 2004-2005 Stephane VOLTZ - * - * USB Acecad "Acecad Flair" tablet support - * - * Changelog: - * v3.2 - Added sysfs support - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include - -/* - * Version Information - */ -#define DRIVER_VERSION "v3.2" -#define DRIVER_DESC "USB Acecad Flair tablet driver" -#define DRIVER_LICENSE "GPL" -#define DRIVER_AUTHOR "Edouard TISSERANT " - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - -#define USB_VENDOR_ID_ACECAD 0x0460 -#define USB_DEVICE_ID_FLAIR 0x0004 -#define USB_DEVICE_ID_302 0x0008 - -struct usb_acecad { - char name[128]; - char phys[64]; - struct usb_device *usbdev; - struct input_dev dev; - struct urb *irq; - - signed char *data; - dma_addr_t data_dma; -}; - -static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs) -{ - struct usb_acecad *acecad = urb->context; - unsigned char *data = acecad->data; - struct input_dev *dev = &acecad->dev; - int prox, status; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); - goto resubmit; - } - - prox = (data[0] & 0x04) >> 2; - input_report_key(dev, BTN_TOOL_PEN, prox); - - if (prox) { - int x = data[1] | (data[2] << 8); - int y = data[3] | (data[4] << 8); - /*Pressure should compute the same way for flair and 302*/ - int pressure = data[5] | ((int)data[6] << 8); - int touch = data[0] & 0x01; - int stylus = (data[0] & 0x10) >> 4; - int stylus2 = (data[0] & 0x20) >> 5; - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - input_report_abs(dev, ABS_PRESSURE, pressure); - input_report_key(dev, BTN_TOUCH, touch); - input_report_key(dev, BTN_STYLUS, stylus); - input_report_key(dev, BTN_STYLUS2, stylus2); - } - - /* event termination */ - input_sync(dev); - -resubmit: - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status) - err ("can't resubmit intr, %s-%s/input0, status %d", - acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status); -} - -static int usb_acecad_open(struct input_dev *dev) -{ - struct usb_acecad *acecad = dev->private; - - acecad->irq->dev = acecad->usbdev; - if (usb_submit_urb(acecad->irq, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void usb_acecad_close(struct input_dev *dev) -{ - struct usb_acecad *acecad = dev->private; - - usb_kill_urb(acecad->irq); -} - -static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface = intf->cur_altsetting; - struct usb_endpoint_descriptor *endpoint; - struct usb_acecad *acecad; - int pipe, maxp; - char path[64]; - - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - - if (!(endpoint->bEndpointAddress & 0x80)) - return -ENODEV; - - if ((endpoint->bmAttributes & 3) != 3) - return -ENODEV; - - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - acecad = kcalloc(1, sizeof(struct usb_acecad), GFP_KERNEL); - if (!acecad) - return -ENOMEM; - - acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma); - if (!acecad->data) - goto fail1; - - acecad->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!acecad->irq) - goto fail2; - - if (dev->manufacturer) - strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name)); - - if (dev->product) { - if (dev->manufacturer) - strlcat(acecad->name, " ", sizeof(acecad->name)); - strlcat(acecad->name, dev->product, sizeof(acecad->name)); - } - - usb_make_path(dev, path, sizeof(path)); - snprintf(acecad->phys, sizeof(acecad->phys), "%s/input0", path); - - acecad->usbdev = dev; - - acecad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - acecad->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - acecad->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - acecad->dev.keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2); - - switch (id->driver_info) { - case 0: - acecad->dev.absmax[ABS_X] = 5000; - acecad->dev.absmax[ABS_Y] = 3750; - acecad->dev.absmax[ABS_PRESSURE] = 512; - if (!strlen(acecad->name)) - snprintf(acecad->name, sizeof(acecad->name), - "USB Acecad Flair Tablet %04x:%04x", - dev->descriptor.idVendor, dev->descriptor.idProduct); - break; - case 1: - acecad->dev.absmax[ABS_X] = 3000; - acecad->dev.absmax[ABS_Y] = 2250; - acecad->dev.absmax[ABS_PRESSURE] = 1024; - if (!strlen(acecad->name)) - snprintf(acecad->name, sizeof(acecad->name), - "USB Acecad 302 Tablet %04x:%04x", - dev->descriptor.idVendor, dev->descriptor.idProduct); - break; - } - - acecad->dev.absfuzz[ABS_X] = 4; - acecad->dev.absfuzz[ABS_Y] = 4; - - acecad->dev.private = acecad; - acecad->dev.open = usb_acecad_open; - acecad->dev.close = usb_acecad_close; - - acecad->dev.name = acecad->name; - acecad->dev.phys = acecad->phys; - acecad->dev.id.bustype = BUS_USB; - acecad->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - acecad->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - acecad->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); - acecad->dev.dev = &intf->dev; - - usb_fill_int_urb(acecad->irq, dev, pipe, - acecad->data, maxp > 8 ? 8 : maxp, - usb_acecad_irq, acecad, endpoint->bInterval); - acecad->irq->transfer_dma = acecad->data_dma; - acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - input_register_device(&acecad->dev); - - printk(KERN_INFO "input: %s with packet size %d on %s\n", - acecad->name, maxp, path); - - usb_set_intfdata(intf, acecad); - - return 0; - - fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); - fail1: kfree(acecad); - return -ENOMEM; -} - -static void usb_acecad_disconnect(struct usb_interface *intf) -{ - struct usb_acecad *acecad = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - if (acecad) { - usb_kill_urb(acecad->irq); - input_unregister_device(&acecad->dev); - usb_free_urb(acecad->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); - kfree(acecad); - } -} - -static struct usb_device_id usb_acecad_id_table [] = { - { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 }, - { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302), .driver_info = 1 }, - { } -}; - -MODULE_DEVICE_TABLE(usb, usb_acecad_id_table); - -static struct usb_driver usb_acecad_driver = { - .owner = THIS_MODULE, - .name = "usb_acecad", - .probe = usb_acecad_probe, - .disconnect = usb_acecad_disconnect, - .id_table = usb_acecad_id_table, -}; - -static int __init usb_acecad_init(void) -{ - int result = usb_register(&usb_acecad_driver); - if (result == 0) - info(DRIVER_VERSION ":" DRIVER_DESC); - return result; -} - -static void __exit usb_acecad_exit(void) -{ - usb_deregister(&usb_acecad_driver); -} - -module_init(usb_acecad_init); -module_exit(usb_acecad_exit); diff --git a/trunk/drivers/usb/input/aiptek.c b/trunk/drivers/usb/input/aiptek.c index 6bb0f25e8e93..e991f7ed7330 100644 --- a/trunk/drivers/usb/input/aiptek.c +++ b/trunk/drivers/usb/input/aiptek.c @@ -1,7 +1,7 @@ /* * Native support for the Aiptek HyperPen USB Tablets * (4000U/5000U/6000U/8000U/12000U) - * + * * Copyright (c) 2001 Chris Atenasio * Copyright (c) 2002-2004 Bryan W. Headley * @@ -31,7 +31,7 @@ * - Added support for the sysfs interface, deprecating the * procfs interface for 2.5.x kernel. Also added support for * Wheel command. Bryan W. Headley July-15-2003. - * v1.2 - Reworked jitter timer as a kernel thread. + * v1.2 - Reworked jitter timer as a kernel thread. * Bryan W. Headley November-28-2003/Jan-10-2004. * v1.3 - Repaired issue of kernel thread going nuts on single-processor * machines, introduced programmableDelay as a command line @@ -49,10 +49,10 @@ * NOTE: * This kernel driver is augmented by the "Aiptek" XFree86 input * driver for your X server, as well as the Gaiptek GUI Front-end - * "Tablet Manager". - * These three products are highly interactive with one another, + * "Tablet Manager". + * These three products are highly interactive with one another, * so therefore it's easier to document them all as one subsystem. - * Please visit the project's "home page", located at, + * Please visit the project's "home page", located at, * http://aiptektablet.sourceforge.net. * * This program is free software; you can redistribute it and/or modify @@ -156,7 +156,7 @@ * Command/Data Description Return Bytes Return Value * 0x10/0x00 SwitchToMouse 0 * 0x10/0x01 SwitchToTablet 0 - * 0x18/0x04 SetResolution 0 + * 0x18/0x04 SetResolution 0 * 0x12/0xFF AutoGainOn 0 * 0x17/0x00 FilterOn 0 * 0x01/0x00 GetXExtension 2 MaxX @@ -247,7 +247,7 @@ #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 - /* Time to wait (in ms) to help mask hand jittering + /* Time to wait (in ms) to help mask hand jittering * when pressing the stylus buttons. */ #define AIPTEK_JITTER_DELAY_DEFAULT 50 @@ -324,6 +324,7 @@ struct aiptek { struct aiptek_settings curSetting; /* tablet's current programmable */ struct aiptek_settings newSetting; /* ... and new param settings */ unsigned int ifnum; /* interface number for IO */ + int openCount; /* module use counter */ int diagnostic; /* tablet diagnostic codes */ unsigned long eventCount; /* event count */ int inDelay; /* jitter: in jitter delay? */ @@ -790,7 +791,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs) * specific Aiptek model numbers, because there has been overlaps, * use, and reuse of id's in existing models. Certain models have * been known to use more than one ID, indicative perhaps of - * manufacturing revisions. In any event, we consider these + * manufacturing revisions. In any event, we consider these * IDs to not be model-specific nor unique. */ static const struct usb_device_id aiptek_ids[] = { @@ -813,9 +814,15 @@ static int aiptek_open(struct input_dev *inputdev) { struct aiptek *aiptek = inputdev->private; + if (aiptek->openCount++ > 0) { + return 0; + } + aiptek->urb->dev = aiptek->usbdev; - if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) + if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) { + aiptek->openCount--; return -EIO; + } return 0; } @@ -827,11 +834,13 @@ static void aiptek_close(struct input_dev *inputdev) { struct aiptek *aiptek = inputdev->private; - usb_kill_urb(aiptek->urb); + if (--aiptek->openCount == 0) { + usb_kill_urb(aiptek->urb); + } } /*********************************************************************** - * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, + * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, * where they were known as usb_set_report and usb_get_report. */ static int @@ -2243,6 +2252,7 @@ static void aiptek_disconnect(struct usb_interface *intf) AIPTEK_PACKET_LENGTH, aiptek->data, aiptek->data_dma); kfree(aiptek); + aiptek = NULL; } } diff --git a/trunk/drivers/usb/input/ati_remote.c b/trunk/drivers/usb/input/ati_remote.c index db95c975952b..860df26323b1 100644 --- a/trunk/drivers/usb/input/ati_remote.c +++ b/trunk/drivers/usb/input/ati_remote.c @@ -1,15 +1,15 @@ -/* +/* * USB ATI Remote support * * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev * * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including - * porting to the 2.6 kernel interfaces, along with other modification + * porting to the 2.6 kernel interfaces, along with other modification * to better match the style of the existing usb/input drivers. However, the * protocol and hardware handling is essentially unchanged from 2.1.1. - * - * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by + * + * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by * Vojtech Pavlik. * * Changes: @@ -23,64 +23,64 @@ * Added support for the "Lola" remote contributed by: * Seth Cohn * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Hardware & software notes * - * These remote controls are distributed by ATI as part of their - * "All-In-Wonder" video card packages. The receiver self-identifies as a + * These remote controls are distributed by ATI as part of their + * "All-In-Wonder" video card packages. The receiver self-identifies as a * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". * - * The "Lola" remote is available from X10. See: + * The "Lola" remote is available from X10. See: * http://www.x10.com/products/lola_sg1.htm * The Lola is similar to the ATI remote but has no mouse support, and slightly * different keys. * - * It is possible to use multiple receivers and remotes on multiple computers + * It is possible to use multiple receivers and remotes on multiple computers * simultaneously by configuring them to use specific channels. - * - * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. - * Actually, it may even support more, at least in some revisions of the + * + * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. + * Actually, it may even support more, at least in some revisions of the * hardware. * * Each remote can be configured to transmit on one channel as follows: - * - Press and hold the "hand icon" button. - * - When the red LED starts to blink, let go of the "hand icon" button. - * - When it stops blinking, input the channel code as two digits, from 01 + * - Press and hold the "hand icon" button. + * - When the red LED starts to blink, let go of the "hand icon" button. + * - When it stops blinking, input the channel code as two digits, from 01 * to 16, and press the hand icon again. - * + * * The timing can be a little tricky. Try loading the module with debug=1 * to have the kernel print out messages about the remote control number * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. * * The driver has a "channel_mask" parameter. This bitmask specifies which - * channels will be ignored by the module. To mask out channels, just add + * channels will be ignored by the module. To mask out channels, just add * all the 2^channel_number values together. * * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote - * ignore signals coming from remote controls transmitting on channel 4, but + * ignore signals coming from remote controls transmitting on channel 4, but * accept all other channels. * - * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be + * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be * ignored. * - * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this + * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this * parameter are unused. * */ @@ -99,13 +99,13 @@ /* * Module and Version Information, Module Parameters */ - -#define ATI_REMOTE_VENDOR_ID 0x0bc7 -#define ATI_REMOTE_PRODUCT_ID 0x004 -#define LOLA_REMOTE_PRODUCT_ID 0x002 + +#define ATI_REMOTE_VENDOR_ID 0x0bc7 +#define ATI_REMOTE_PRODUCT_ID 0x004 +#define LOLA_REMOTE_PRODUCT_ID 0x002 #define MEDION_REMOTE_PRODUCT_ID 0x006 -#define DRIVER_VERSION "2.2.1" +#define DRIVER_VERSION "2.2.1" #define DRIVER_AUTHOR "Torrey Hoffman " #define DRIVER_DESC "ATI/X10 RF USB Remote Control" @@ -113,18 +113,18 @@ #define DATA_BUFSIZE 63 /* size of URB data buffers */ #define ATI_INPUTNUM 1 /* Which input device to register as */ -static unsigned long channel_mask; +static unsigned long channel_mask = 0; module_param(channel_mask, ulong, 0444); MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); -static int debug; +static int debug = 0; module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) #undef err #define err(format, arg...) printk(KERN_ERR format , ## arg) - + static struct usb_device_id ati_remote_table[] = { { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, @@ -148,7 +148,7 @@ static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; /* Acceleration curve for directional control pad */ static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; -/* Duplicate event filtering time. +/* Duplicate event filtering time. * Sequential, identical KIND_FILTERED inputs with less than * FILTER_TIME jiffies between them are considered as repeat * events. The hardware generates 5 events for the first keypress @@ -161,10 +161,10 @@ static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; static DECLARE_MUTEX(disconnect_sem); struct ati_remote { - struct input_dev idev; + struct input_dev idev; struct usb_device *udev; struct usb_interface *interface; - + struct urb *irq_urb; struct urb *out_urb; struct usb_endpoint_descriptor *endpoint_in; @@ -174,11 +174,13 @@ struct ati_remote { dma_addr_t inbuf_dma; dma_addr_t outbuf_dma; + int open; /* open counter */ + unsigned char old_data[2]; /* Detect duplicate events */ unsigned long old_jiffies; unsigned long acc_jiffies; /* handle acceleration */ unsigned int repeat_count; - + char name[NAME_BUFSIZE]; char phys[NAME_BUFSIZE]; @@ -204,14 +206,14 @@ static struct int type; unsigned int code; int value; -} ati_remote_tbl[] = +} ati_remote_tbl[] = { /* Directional control pad axes */ {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ - /* Directional control pad diagonals */ + /* Directional control pad diagonals */ {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ @@ -223,7 +225,7 @@ static struct {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ - /* Artificial "doubleclick" events are generated by the hardware. + /* Artificial "doubleclick" events are generated by the hardware. * They are mapped to the "side" and "extra" mouse buttons here. */ {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ @@ -271,15 +273,15 @@ static struct {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ - {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ + {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ - {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ - + {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ + {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} }; @@ -313,7 +315,7 @@ static void ati_remote_dump(unsigned char *data, unsigned int len) if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) warn("Weird byte 0x%02x", data[0]); else if (len == 4) - warn("Weird key %02x %02x %02x %02x", + warn("Weird key %02x %02x %02x %02x", data[0], data[1], data[2], data[3]); else warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", @@ -326,16 +328,25 @@ static void ati_remote_dump(unsigned char *data, unsigned int len) static int ati_remote_open(struct input_dev *inputdev) { struct ati_remote *ati_remote = inputdev->private; + int retval = 0; + + down(&disconnect_sem); + + if (ati_remote->open++) + goto exit; /* On first open, submit the read urb which was set up previously. */ ati_remote->irq_urb->dev = ati_remote->udev; if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { - dev_err(&ati_remote->interface->dev, + dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb failed!\n", __FUNCTION__); - return -EIO; + ati_remote->open--; + retval = -EIO; } - return 0; +exit: + up(&disconnect_sem); + return retval; } /* @@ -344,8 +355,9 @@ static int ati_remote_open(struct input_dev *inputdev) static void ati_remote_close(struct input_dev *inputdev) { struct ati_remote *ati_remote = inputdev->private; - - usb_kill_urb(ati_remote->irq_urb); + + if (!--ati_remote->open) + usb_kill_urb(ati_remote->irq_urb); } /* @@ -354,13 +366,13 @@ static void ati_remote_close(struct input_dev *inputdev) static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) { struct ati_remote *ati_remote = urb->context; - + if (urb->status) { dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", __FUNCTION__, urb->status); return; } - + ati_remote->send_flags |= SEND_FLAG_COMPLETE; wmb(); wake_up(&ati_remote->wait); @@ -368,16 +380,16 @@ static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) /* * ati_remote_sendpacket - * + * * Used to send device initialization strings */ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) { int retval = 0; - + /* Set up out_urb */ memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); - ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); + ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; ati_remote->out_urb->dev = ati_remote->udev; @@ -385,17 +397,17 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); if (retval) { - dev_dbg(&ati_remote->interface->dev, + dev_dbg(&ati_remote->interface->dev, "sendpacket: usb_submit_urb failed: %d\n", retval); return retval; } wait_event_timeout(ati_remote->wait, ((ati_remote->out_urb->status != -EINPROGRESS) || - (ati_remote->send_flags & SEND_FLAG_COMPLETE)), + (ati_remote->send_flags & SEND_FLAG_COMPLETE)), HZ); usb_kill_urb(ati_remote->out_urb); - + return retval; } @@ -407,15 +419,15 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) int i; for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { - /* - * Decide if the table entry matches the remote input. + /* + * Decide if the table entry matches the remote input. */ if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && - ((((ati_remote_tbl[i].data1 >> 4) - - (d1 >> 4) + rem) & 0x0f) == 0x0f) && + ((((ati_remote_tbl[i].data1 >> 4) - + (d1 >> 4) + rem) & 0x0f) == 0x0f) && (ati_remote_tbl[i].data2 == d2)) return i; - + } return -1; } @@ -423,16 +435,16 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) /* * ati_remote_report_input */ -static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) +static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) { struct ati_remote *ati_remote = urb->context; unsigned char *data= ati_remote->inbuf; - struct input_dev *dev = &ati_remote->idev; + struct input_dev *dev = &ati_remote->idev; int index, acc; int remote_num; - + /* Deal with strange looking inputs */ - if ( (urb->actual_length != 4) || (data[0] != 0x14) || + if ( (urb->actual_length != 4) || (data[0] != 0x14) || ((data[3] & 0x0f) != 0x00) ) { ati_remote_dump(data, urb->actual_length); return; @@ -441,7 +453,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) /* Mask unwanted remote channels. */ /* note: remote_num is 0-based, channel 1 on remote == 0 here */ remote_num = (data[3] >> 4) & 0x0f; - if (channel_mask & (1 << (remote_num + 1))) { + if (channel_mask & (1 << (remote_num + 1))) { dbginfo(&ati_remote->interface->dev, "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", remote_num, data[1], data[2], channel_mask); @@ -451,36 +463,37 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) /* Look up event code index in translation table */ index = ati_remote_event_lookup(remote_num, data[1], data[2]); if (index < 0) { - dev_warn(&ati_remote->interface->dev, - "Unknown input from channel 0x%02x: data %02x,%02x\n", + dev_warn(&ati_remote->interface->dev, + "Unknown input from channel 0x%02x: data %02x,%02x\n", remote_num, data[1], data[2]); return; - } - dbginfo(&ati_remote->interface->dev, + } + dbginfo(&ati_remote->interface->dev, "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", remote_num, data[1], data[2], index, ati_remote_tbl[index].code); - + if (ati_remote_tbl[index].kind == KIND_LITERAL) { input_regs(dev, regs); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, ati_remote_tbl[index].value); input_sync(dev); - + ati_remote->old_jiffies = jiffies; return; } - + if (ati_remote_tbl[index].kind == KIND_FILTERED) { /* Filter duplicate events which happen "too close" together. */ - if ((ati_remote->old_data[0] == data[1]) && - (ati_remote->old_data[1] == data[2]) && - ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { + if ((ati_remote->old_data[0] == data[1]) && + (ati_remote->old_data[1] == data[2]) && + ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { ati_remote->repeat_count++; - } else { + } + else { ati_remote->repeat_count = 0; } - + ati_remote->old_data[0] = data[1]; ati_remote->old_data[1] = data[2]; ati_remote->old_jiffies = jiffies; @@ -488,7 +501,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) if ((ati_remote->repeat_count > 0) && (ati_remote->repeat_count < 5)) return; - + input_regs(dev, regs); input_event(dev, ati_remote_tbl[index].type, @@ -498,13 +511,13 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) input_sync(dev); return; - } - - /* + } + + /* * Other event kinds are from the directional control pad, and have an * acceleration factor applied to them. Without this acceleration, the * control pad is mostly unusable. - * + * * If elapsed time since last event is > 1/4 second, user "stopped", * so reset acceleration. Otherwise, user is probably holding the control * pad down, so we increase acceleration, ramping up over two seconds to @@ -546,7 +559,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) input_report_rel(dev, REL_Y, acc); break; default: - dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", + dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", ati_remote_tbl[index].kind); } input_sync(dev); @@ -573,12 +586,12 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) case -ESHUTDOWN: dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", __FUNCTION__); - return; + return; default: /* error */ - dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", + dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", __FUNCTION__, urb->status); } - + retval = usb_submit_urb(urb, SLAB_ATOMIC); if (retval) dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", @@ -590,6 +603,8 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) */ static void ati_remote_delete(struct ati_remote *ati_remote) { + if (!ati_remote) return; + if (ati_remote->irq_urb) usb_kill_urb(ati_remote->irq_urb); @@ -599,16 +614,16 @@ static void ati_remote_delete(struct ati_remote *ati_remote) input_unregister_device(&ati_remote->idev); if (ati_remote->inbuf) - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, ati_remote->inbuf, ati_remote->inbuf_dma); - + if (ati_remote->outbuf) - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, ati_remote->outbuf, ati_remote->outbuf_dma); - + if (ati_remote->irq_urb) usb_free_urb(ati_remote->irq_urb); - + if (ati_remote->out_urb) usb_free_urb(ati_remote->out_urb); @@ -621,21 +636,21 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) int i; idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | + idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) if (ati_remote_tbl[i].type == EV_KEY) set_bit(ati_remote_tbl[i].code, idev->keybit); - + idev->private = ati_remote; idev->open = ati_remote_open; idev->close = ati_remote_close; - + idev->name = ati_remote->name; idev->phys = ati_remote->phys; - - idev->id.bustype = BUS_USB; + + idev->id.bustype = BUS_USB; idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); @@ -645,27 +660,27 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) { struct usb_device *udev = ati_remote->udev; int pipe, maxp; - + init_waitqueue_head(&ati_remote->wait); /* Set up irq_urb */ pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; - - usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, - maxp, ati_remote_irq_in, ati_remote, + + usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, + maxp, ati_remote_irq_in, ati_remote, ati_remote->endpoint_in->bInterval); ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - + /* Set up out_urb */ pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; - usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, - maxp, ati_remote_irq_out, ati_remote, + usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, + maxp, ati_remote_irq_out, ati_remote, ati_remote->endpoint_out->bInterval); ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -673,11 +688,11 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) /* send initialization strings */ if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { - dev_err(&ati_remote->interface->dev, + dev_err(&ati_remote->interface->dev, "Initializing ati_remote hardware failed.\n"); return 1; } - + return 0; } @@ -754,7 +769,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de if (!strlen(ati_remote->name)) sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", - le16_to_cpu(ati_remote->udev->descriptor.idVendor), + le16_to_cpu(ati_remote->udev->descriptor.idVendor), le16_to_cpu(ati_remote->udev->descriptor.idProduct)); /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ @@ -766,11 +781,11 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de ati_remote_input_init(ati_remote); input_register_device(&ati_remote->idev); - dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", + dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", ati_remote->name, path); usb_set_intfdata(interface, ati_remote); - + error: if (retval) ati_remote_delete(ati_remote); @@ -785,14 +800,18 @@ static void ati_remote_disconnect(struct usb_interface *interface) { struct ati_remote *ati_remote; + down(&disconnect_sem); + ati_remote = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); if (!ati_remote) { warn("%s - null device?\n", __FUNCTION__); return; } - + ati_remote_delete(ati_remote); + + up(&disconnect_sem); } /* @@ -801,7 +820,7 @@ static void ati_remote_disconnect(struct usb_interface *interface) static int __init ati_remote_init(void) { int result; - + result = usb_register(&ati_remote_driver); if (result) err("usb_register error #%d\n", result); @@ -819,8 +838,8 @@ static void __exit ati_remote_exit(void) usb_deregister(&ati_remote_driver); } -/* - * module specification +/* + * module specification */ module_init(ati_remote_init); diff --git a/trunk/drivers/usb/input/hid-core.c b/trunk/drivers/usb/input/hid-core.c index 100b49bd1d3e..740dec1f521d 100644 --- a/trunk/drivers/usb/input/hid-core.c +++ b/trunk/drivers/usb/input/hid-core.c @@ -232,7 +232,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign report->size += parser->global.report_size * parser->global.report_count; if (!parser->local.usage_index) /* Ignore padding fields */ - return 0; + return 0; usages = max_t(int, parser->local.usage_index, parser->global.report_count); @@ -765,7 +765,7 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n) static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) { report += (offset >> 5) << 2; offset &= 31; - return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1); + return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1); } static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) @@ -1233,13 +1233,6 @@ int hid_wait_io(struct hid_device *hid) return 0; } -static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, - ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); -} - static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, unsigned char type, void *buf, int size) { @@ -1308,6 +1301,10 @@ void hid_init_reports(struct hid_device *hid) if (err) warn("timeout initializing reports\n"); + + usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0), + HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, + hid->ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); } #define USB_VENDOR_ID_WACOM 0x056a @@ -1321,10 +1318,6 @@ void hid_init_reports(struct hid_device *hid) #define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 #define USB_DEVICE_ID_WACOM_CINTIQ 0x003F -#define USB_VENDOR_ID_ACECAD 0x0460 -#define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 -#define USB_DEVICE_ID_ACECAD_302 0x0008 - #define USB_VENDOR_ID_KBGEAR 0x084e #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 @@ -1509,9 +1502,6 @@ static struct hid_blacklist { { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, @@ -1600,8 +1590,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) return NULL; } - hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); - if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { dbg("reading report descriptor failed"); kfree(rdesc); @@ -1647,7 +1635,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) /* Change the polling interval of mice. */ if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) interval = hid_mousepoll_interval; - + if (endpoint->bEndpointAddress & USB_DIR_IN) { if (hid->urbin) continue; diff --git a/trunk/drivers/usb/input/hid-debug.h b/trunk/drivers/usb/input/hid-debug.h index 52437e5e2e78..2b91705740a7 100644 --- a/trunk/drivers/usb/input/hid-debug.h +++ b/trunk/drivers/usb/input/hid-debug.h @@ -67,7 +67,7 @@ static const struct hid_usage_entry hid_usage_table[] = { {0, 0x44, "Vbry"}, {0, 0x45, "Vbrz"}, {0, 0x46, "Vno"}, - {0, 0x80, "SystemControl"}, + {0, 0x80, "SystemControl"}, {0, 0x81, "SystemPowerDown"}, {0, 0x82, "SystemSleep"}, {0, 0x83, "SystemWakeUp"}, @@ -347,7 +347,7 @@ __inline__ static void tab(int n) { static void hid_dump_field(struct hid_field *field, int n) { int j; - + if (field->physical) { tab(n); printk("Physical("); @@ -408,7 +408,7 @@ static void hid_dump_field(struct hid_field *field, int n) { printk("%s", units[sys][i]); if(nibble != 1) { /* This is a _signed_ nibble(!) */ - + int val = nibble & 0x7; if(nibble & 0x08) val = -((0x7 & ~val) +1); @@ -443,7 +443,7 @@ static void __attribute__((unused)) hid_dump_device(struct hid_device *device) { struct list_head *list; unsigned i,k; static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; - + for (i = 0; i < HID_REPORT_TYPES; i++) { report_enum = device->report_enum + i; list = report_enum->report_list.next; @@ -664,8 +664,8 @@ static char *keys[KEY_MAX + 1] = { static char *relatives[REL_MAX + 1] = { [REL_X] = "X", [REL_Y] = "Y", [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", - [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", - [REL_MISC] = "Misc", + [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", + [REL_MISC] = "Misc", }; static char *absolutes[ABS_MAX + 1] = { @@ -690,9 +690,9 @@ static char *misc[MSC_MAX + 1] = { }; static char *leds[LED_MAX + 1] = { - [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", + [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", - [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", + [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", [LED_MISC] = "Misc", }; diff --git a/trunk/drivers/usb/input/hid-input.c b/trunk/drivers/usb/input/hid-input.c index 9ac1e9095334..5553c3553e9d 100644 --- a/trunk/drivers/usb/input/hid-input.c +++ b/trunk/drivers/usb/input/hid-input.c @@ -164,7 +164,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case HID_GD_X: case HID_GD_Y: case HID_GD_Z: case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: - if (field->flags & HID_MAIN_ITEM_RELATIVE) + if (field->flags & HID_MAIN_ITEM_RELATIVE) map_rel(usage->hid & 0xf); else map_abs(usage->hid & 0xf); @@ -297,7 +297,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case HID_UP_MSVENDOR: goto ignore; - + case HID_UP_PID: set_bit(EV_FF, input->evbit); @@ -349,7 +349,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel goto ignore; if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && - (usage->type == EV_REL) && (usage->code == REL_WHEEL)) + (usage->type == EV_REL) && (usage->code == REL_WHEEL)) set_bit(REL_HWHEEL, bit); 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 a = field->logical_minimum = 0; b = field->logical_maximum = 255; } - + if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); else input_set_abs_params(input, usage->code, a, b, 0, 0); - + } 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 return; } - if (usage->hat_min < usage->hat_max || usage->hat_dir) { + if (usage->hat_min < usage->hat_max || usage->hat_dir) { int hat_dir = usage->hat_dir; if (!hat_dir) 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) for (i = 0; i < hid->maxcollection; i++) if (hid->collection[i].type == HID_COLLECTION_APPLICATION || hid->collection[i].type == HID_COLLECTION_PHYSICAL) - if (IS_INPUT_APPLICATION(hid->collection[i].usage)) + if (IS_INPUT_APPLICATION(hid->collection[i].usage)) break; if (i == hid->maxcollection) @@ -592,7 +592,7 @@ int hidinput_connect(struct hid_device *hid) for (j = 0; j < report->field[i]->maxusage; j++) hidinput_configure_usage(hidinput, report->field[i], report->field[i]->usage + j); - + if (hid->quirks & HID_QUIRK_MULTI_INPUT) { /* This will leave hidinput NULL, so that it * allocates another one if we have more inputs on diff --git a/trunk/drivers/usb/input/hid-lgff.c b/trunk/drivers/usb/input/hid-lgff.c index 0c4c77aa31ea..0d7404bab92f 100644 --- a/trunk/drivers/usb/input/hid-lgff.c +++ b/trunk/drivers/usb/input/hid-lgff.c @@ -94,7 +94,7 @@ struct lgff_device { isn't really necessary */ unsigned long flags[1]; /* Contains various information about the - state of the driver for this device */ + state of the driver for this device */ struct timer_list timer; }; @@ -234,7 +234,7 @@ static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) kfree(ret); return NULL; } - memset(ret->field[0]->value, 0, sizeof(s32[8])); + memset(ret->field[0]->value, 0, sizeof(s32[8])); return ret; } @@ -295,11 +295,11 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, unsigned long flags; if (type != EV_FF) return -EINVAL; - if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; + if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; if (value < 0) return -EINVAL; spin_lock_irqsave(&lgff->lock, flags); - + if (value > 0) { if (test_bit(EFFECT_STARTED, effect->flags)) { spin_unlock_irqrestore(&lgff->lock, flags); @@ -345,7 +345,7 @@ static int hid_lgff_flush(struct input_dev *dev, struct file *file) and perform ioctls on the same fd all at the same time */ if ( current->pid == lgff->effects[i].owner && test_bit(EFFECT_USED, lgff->effects[i].flags)) { - + if (hid_lgff_erase(dev, i)) warn("erase effect %d failed", i); } @@ -378,7 +378,7 @@ static int hid_lgff_upload_effect(struct input_dev* input, struct lgff_effect new; int id; unsigned long flags; - + dbg("ioctl rumble"); if (!test_bit(effect->type, input->ffbit)) return -EINVAL; @@ -441,7 +441,7 @@ static void hid_lgff_timer(unsigned long timer_data) spin_lock_irqsave(&lgff->lock, flags); - for (i=0; ieffects +i; if (test_bit(EFFECT_PLAYING, effect->flags)) { @@ -491,7 +491,7 @@ static void hid_lgff_timer(unsigned long timer_data) set_bit(EFFECT_PLAYING, lgff->effects[i].flags); } } - } + } #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff @@ -524,5 +524,5 @@ static void hid_lgff_timer(unsigned long timer_data) add_timer(&lgff->timer); } - spin_unlock_irqrestore(&lgff->lock, flags); + spin_unlock_irqrestore(&lgff->lock, flags); } diff --git a/trunk/drivers/usb/input/hid.h b/trunk/drivers/usb/input/hid.h index c1b6b69bc4a4..6d9329c698d9 100644 --- a/trunk/drivers/usb/input/hid.h +++ b/trunk/drivers/usb/input/hid.h @@ -118,7 +118,7 @@ struct hid_item { #define HID_MAIN_ITEM_CONSTANT 0x001 #define HID_MAIN_ITEM_VARIABLE 0x002 #define HID_MAIN_ITEM_RELATIVE 0x004 -#define HID_MAIN_ITEM_WRAP 0x008 +#define HID_MAIN_ITEM_WRAP 0x008 #define HID_MAIN_ITEM_NONLINEAR 0x010 #define HID_MAIN_ITEM_NO_PREFERRED 0x020 #define HID_MAIN_ITEM_NULL_STATE 0x040 @@ -172,14 +172,14 @@ struct hid_item { #define HID_USAGE_PAGE 0xffff0000 #define HID_UP_UNDEFINED 0x00000000 -#define HID_UP_GENDESK 0x00010000 -#define HID_UP_KEYBOARD 0x00070000 -#define HID_UP_LED 0x00080000 -#define HID_UP_BUTTON 0x00090000 -#define HID_UP_ORDINAL 0x000a0000 +#define HID_UP_GENDESK 0x00010000 +#define HID_UP_KEYBOARD 0x00070000 +#define HID_UP_LED 0x00080000 +#define HID_UP_BUTTON 0x00090000 +#define HID_UP_ORDINAL 0x000a0000 #define HID_UP_CONSUMER 0x000c0000 -#define HID_UP_DIGITIZER 0x000d0000 -#define HID_UP_PID 0x000f0000 +#define HID_UP_DIGITIZER 0x000d0000 +#define HID_UP_PID 0x000f0000 #define HID_UP_HPVENDOR 0xff7f0000 #define HID_UP_MSVENDOR 0xff000000 @@ -406,7 +406,7 @@ struct hid_device { /* device report descriptor */ dma_addr_t outbuf_dma; /* Output buffer dma */ spinlock_t outlock; /* Output fifo spinlock */ - unsigned claimed; /* Claimed by hidinput, hiddev? */ + unsigned claimed; /* Claimed by hidinput, hiddev? */ unsigned quirks; /* Various quirks the device can pull on us */ struct list_head inputs; /* The list of inputs */ diff --git a/trunk/drivers/usb/input/hiddev.c b/trunk/drivers/usb/input/hiddev.c index 4c13331b5f41..96b7c9067951 100644 --- a/trunk/drivers/usb/input/hiddev.c +++ b/trunk/drivers/usb/input/hiddev.c @@ -95,7 +95,7 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) return NULL; rinfo->report_id = ((struct hid_report *) list)->id; break; - + case HID_REPORT_ID_NEXT: list = (struct list_head *) 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) return NULL; rinfo->report_id = ((struct hid_report *) list)->id; break; - + default: return NULL; } @@ -158,7 +158,7 @@ static void hiddev_send_event(struct hid_device *hid, if (uref->field_index != HID_FIELD_INDEX_NONE || (list->flags & HIDDEV_FLAG_REPORT) != 0) { list->buffer[list->head] = *uref; - list->head = (list->head + 1) & + list->head = (list->head + 1) & (HIDDEV_BUFFER_SIZE - 1); kill_fasync(&list->fasync, SIGIO, POLL_IN); } @@ -179,9 +179,9 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, unsigned type = field->report_type; struct hiddev_usage_ref uref; - uref.report_type = + uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : - ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : + ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); uref.report_id = field->report->id; uref.field_index = field->index; @@ -199,9 +199,9 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) struct hiddev_usage_ref uref; memset(&uref, 0, sizeof(uref)); - uref.report_type = + uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : - ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : + ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); uref.report_id = report->id; uref.field_index = HID_FIELD_INDEX_NONE; @@ -236,7 +236,7 @@ static int hiddev_release(struct inode * inode, struct file * file) *listptr = (*listptr)->next; if (!--list->hiddev->open) { - if (list->hiddev->exist) + if (list->hiddev->exist) hid_close(list->hiddev->hid); else kfree(list->hiddev); @@ -303,7 +303,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun if (list->head == list->tail) { add_wait_queue(&list->hiddev->wait, &wait); set_current_state(TASK_INTERRUPTIBLE); - + while (list->head == list->tail) { if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; @@ -317,7 +317,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun retval = -EIO; break; } - + schedule(); } @@ -329,7 +329,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun return retval; - while (list->head != list->tail && + while (list->head != list->tail && retval + event_size <= count) { if ((list->flags & HIDDEV_FLAG_UREF) == 0) { if (list->buffer[list->tail].field_index != @@ -405,10 +405,10 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd return -EINVAL; for (i = 0; i < hid->maxcollection; i++) - if (hid->collection[i].type == + if (hid->collection[i].type == HID_COLLECTION_APPLICATION && arg-- == 0) break; - + if (i == hid->maxcollection) return -EINVAL; @@ -562,7 +562,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd if (!uref_multi) return -ENOMEM; uref = &uref_multi->uref; - if (copy_from_user(uref, user_arg, sizeof(*uref))) + if (copy_from_user(uref, user_arg, sizeof(*uref))) goto fault; rinfo.report_type = uref->report_type; @@ -595,7 +595,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd return -ENOMEM; uref = &uref_multi->uref; if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { - if (copy_from_user(uref_multi, user_arg, + if (copy_from_user(uref_multi, user_arg, sizeof(*uref_multi))) goto fault; } else { @@ -603,7 +603,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd goto fault; } - if (cmd != HIDIOCGUSAGE && + if (cmd != HIDIOCGUSAGE && cmd != HIDIOCGUSAGES && uref->report_type == HID_REPORT_TYPE_INPUT) goto inval; @@ -651,16 +651,16 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd return field->usage[uref->usage_index].collection_index; case HIDIOCGUSAGES: for (i = 0; i < uref_multi->num_values; i++) - uref_multi->values[i] = + uref_multi->values[i] = field->value[uref->usage_index + i]; - if (copy_to_user(user_arg, uref_multi, + if (copy_to_user(user_arg, uref_multi, sizeof(*uref_multi))) goto fault; goto goodreturn; case HIDIOCSUSAGES: for (i = 0; i < uref_multi->num_values; i++) - field->value[uref->usage_index + i] = - uref_multi->values[i]; + field->value[uref->usage_index + i] = + uref_multi->values[i]; goto goodreturn; } @@ -670,7 +670,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd fault: kfree(uref_multi); return -EFAULT; -inval: +inval: kfree(uref_multi); return -EINVAL; @@ -734,7 +734,7 @@ static struct usb_class_driver hiddev_class = { .name = "usb/hid/hiddev%d", .fops = &hiddev_fops, .mode = S_IFCHR | S_IRUGO | S_IWUSR, - .minor_base = HIDDEV_MINOR_BASE, + .minor_base = HIDDEV_MINOR_BASE, }; /* @@ -747,7 +747,7 @@ int hiddev_connect(struct hid_device *hid) int retval; for (i = 0; i < hid->maxcollection; i++) - if (hid->collection[i].type == + if (hid->collection[i].type == HID_COLLECTION_APPLICATION && !IS_INPUT_APPLICATION(hid->collection[i].usage)) break; @@ -755,11 +755,11 @@ int hiddev_connect(struct hid_device *hid) if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) return -1; - if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) + if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) return -1; memset(hiddev, 0, sizeof(struct hiddev)); - retval = usb_register_dev(hid->intf, &hiddev_class); + retval = usb_register_dev(hid->intf, &hiddev_class); if (retval) { err("Not able to get a minor for this device."); kfree(hiddev); @@ -768,12 +768,12 @@ int hiddev_connect(struct hid_device *hid) init_waitqueue_head(&hiddev->wait); - hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; + hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; hiddev->hid = hid; hiddev->exist = 1; - hid->minor = hid->intf->minor; + hid->minor = hid->intf->minor; hid->hiddev = hiddev; return 0; @@ -818,7 +818,7 @@ void hiddev_disconnect(struct hid_device *hid) /* We never attach in this manner, and rely on HID to connect us. This * is why there is no disconnect routine defined in the usb_driver either. */ -static int hiddev_usbd_probe(struct usb_interface *intf, +static int hiddev_usbd_probe(struct usb_interface *intf, const struct usb_device_id *hiddev_info) { return -ENODEV; diff --git a/trunk/drivers/usb/input/itmtouch.c b/trunk/drivers/usb/input/itmtouch.c deleted file mode 100644 index 47dec6a1b344..000000000000 --- a/trunk/drivers/usb/input/itmtouch.c +++ /dev/null @@ -1,268 +0,0 @@ -/****************************************************************************** - * itmtouch.c -- Driver for ITM touchscreen panel - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based upon original work by Chris Collins . - * - * Kudos to ITM for providing me with the datasheet for the panel, - * even though it was a day later than I had finished writing this - * driver. - * - * It has meant that I've been able to correct my interpretation of the - * protocol packets however. - * - * CC -- 2003/9/29 - * - * History - * 1.0 & 1.1 2003 (CC) vojtech@suse.cz - * Original version for 2.4.x kernels - * - * 1.2 02/03/2005 (HCE) hc@mivu.no - * Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints. - * Unfortunately no calibration support at this time. - * - * 1.2.1 09/03/2005 (HCE) hc@mivu.no - * Code cleanup and adjusting syntax to start matching kernel standards - * - *****************************************************************************/ - -#include - -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif - -#include -#include -#include -#include -#include -#include - -/* only an 8 byte buffer necessary for a single packet */ -#define ITM_BUFSIZE 8 -#define PATH_SIZE 64 - -#define USB_VENDOR_ID_ITMINC 0x0403 -#define USB_PRODUCT_ID_TOUCHPANEL 0xf9e9 - -#define DRIVER_AUTHOR "Hans-Christian Egtvedt " -#define DRIVER_VERSION "v1.2.1" -#define DRIVER_DESC "USB ITM Inc Touch Panel Driver" -#define DRIVER_LICENSE "GPL" - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE( DRIVER_LICENSE ); - -struct itmtouch_dev { - struct usb_device *usbdev; /* usb device */ - struct input_dev inputdev; /* input device */ - struct urb *readurb; /* urb */ - char rbuf[ITM_BUFSIZE]; /* data */ - int users; - char name[128]; - char phys[64]; -}; - -static struct usb_device_id itmtouch_ids [] = { - { USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) }, - { } -}; - -static void itmtouch_irq(struct urb *urb, struct pt_regs *regs) -{ - struct itmtouch_dev * itmtouch = urb->context; - unsigned char *data = urb->transfer_buffer; - struct input_dev *dev = &itmtouch->inputdev; - int retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ETIMEDOUT: - /* this urb is timing out */ - dbg("%s - urb timed out - was the device unplugged?", - __FUNCTION__); - return; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __FUNCTION__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", - __FUNCTION__, urb->status); - goto exit; - } - - input_regs(dev, regs); - - /* if pressure has been released, then don't report X/Y */ - if (data[7] & 0x20) { - input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F)); - input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F)); - } - - input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F)); - input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20); - input_sync(dev); - -exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); - if (retval) - printk(KERN_ERR "%s - usb_submit_urb failed with result: %d", - __FUNCTION__, retval); -} - -static int itmtouch_open(struct input_dev *input) -{ - struct itmtouch_dev *itmtouch = input->private; - - itmtouch->readurb->dev = itmtouch->usbdev; - - if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void itmtouch_close(struct input_dev *input) -{ - struct itmtouch_dev *itmtouch = input->private; - - usb_kill_urb(itmtouch->readurb); -} - -static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct itmtouch_dev *itmtouch; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = interface_to_usbdev(intf); - unsigned int pipe; - unsigned int maxp; - char path[PATH_SIZE]; - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - - if (!(itmtouch = kcalloc(1, sizeof(struct itmtouch_dev), GFP_KERNEL))) { - err("%s - Out of memory.", __FUNCTION__); - return -ENOMEM; - } - - itmtouch->usbdev = udev; - - itmtouch->inputdev.private = itmtouch; - itmtouch->inputdev.open = itmtouch_open; - itmtouch->inputdev.close = itmtouch_close; - - usb_make_path(udev, path, PATH_SIZE); - - itmtouch->inputdev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - itmtouch->inputdev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - itmtouch->inputdev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - - itmtouch->inputdev.name = itmtouch->name; - itmtouch->inputdev.phys = itmtouch->phys; - itmtouch->inputdev.id.bustype = BUS_USB; - itmtouch->inputdev.id.vendor = udev->descriptor.idVendor; - itmtouch->inputdev.id.product = udev->descriptor.idProduct; - itmtouch->inputdev.id.version = udev->descriptor.bcdDevice; - itmtouch->inputdev.dev = &intf->dev; - - if (!strlen(itmtouch->name)) - sprintf(itmtouch->name, "USB ITM touchscreen"); - - /* device limits */ - /* as specified by the ITM datasheet, X and Y are 12bit, - * Z (pressure) is 8 bit. However, the fields are defined up - * to 14 bits for future possible expansion. - */ - input_set_abs_params(&itmtouch->inputdev, ABS_X, 0, 0x0FFF, 2, 0); - input_set_abs_params(&itmtouch->inputdev, ABS_Y, 0, 0x0FFF, 2, 0); - input_set_abs_params(&itmtouch->inputdev, ABS_PRESSURE, 0, 0xFF, 2, 0); - - /* initialise the URB so we can read from the transport stream */ - pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - - if (maxp > ITM_BUFSIZE) - maxp = ITM_BUFSIZE; - - itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL); - - if (!itmtouch->readurb) { - dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__); - kfree(itmtouch); - return -ENOMEM; - } - - usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf, - maxp, itmtouch_irq, itmtouch, endpoint->bInterval); - - input_register_device(&itmtouch->inputdev); - - printk(KERN_INFO "itmtouch: %s registered on %s\n", itmtouch->name, path); - usb_set_intfdata(intf, itmtouch); - - return 0; -} - -static void itmtouch_disconnect(struct usb_interface *intf) -{ - struct itmtouch_dev *itmtouch = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - - if (itmtouch) { - input_unregister_device(&itmtouch->inputdev); - usb_kill_urb(itmtouch->readurb); - usb_free_urb(itmtouch->readurb); - kfree(itmtouch); - } -} - -MODULE_DEVICE_TABLE(usb, itmtouch_ids); - -static struct usb_driver itmtouch_driver = { - .owner = THIS_MODULE, - .name = "itmtouch", - .probe = itmtouch_probe, - .disconnect = itmtouch_disconnect, - .id_table = itmtouch_ids, -}; - -static int __init itmtouch_init(void) -{ - info(DRIVER_DESC " " DRIVER_VERSION); - info(DRIVER_AUTHOR); - return usb_register(&itmtouch_driver); -} - -static void __exit itmtouch_exit(void) -{ - usb_deregister(&itmtouch_driver); -} - -module_init(itmtouch_init); -module_exit(itmtouch_exit); diff --git a/trunk/drivers/usb/input/kbtab.c b/trunk/drivers/usb/input/kbtab.c index d2f0f90a9bcd..a68c5b4e7b37 100644 --- a/trunk/drivers/usb/input/kbtab.c +++ b/trunk/drivers/usb/input/kbtab.c @@ -36,6 +36,7 @@ struct kbtab { struct input_dev dev; struct usb_device *usbdev; struct urb *irq; + int open; int x, y; int button; int pressure; @@ -78,12 +79,12 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs) /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ input_report_key(dev, BTN_RIGHT, data[0] & 0x02); - if (-1 == kb_pressure_click) { + if( -1 == kb_pressure_click){ input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); } else { input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); }; - + input_sync(dev); exit: @@ -104,9 +105,14 @@ static int kbtab_open(struct input_dev *dev) { struct kbtab *kbtab = dev->private; + if (kbtab->open++) + return 0; + kbtab->irq->dev = kbtab->usbdev; - if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) + if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) { + kbtab->open--; return -EIO; + } return 0; } @@ -115,7 +121,8 @@ static void kbtab_close(struct input_dev *dev) { struct kbtab *kbtab = dev->private; - usb_kill_urb(kbtab->irq); + if (!--kbtab->open) + usb_kill_urb(kbtab->irq); } static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -154,7 +161,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i kbtab->dev.absmax[ABS_X] = 0x2000; kbtab->dev.absmax[ABS_Y] = 0x1750; kbtab->dev.absmax[ABS_PRESSURE] = 0xff; - + kbtab->dev.absfuzz[ABS_X] = 4; kbtab->dev.absfuzz[ABS_Y] = 4; diff --git a/trunk/drivers/usb/input/mtouchusb.c b/trunk/drivers/usb/input/mtouchusb.c index 09b5cc7c66de..ab1a2a30ce7c 100644 --- a/trunk/drivers/usb/input/mtouchusb.c +++ b/trunk/drivers/usb/input/mtouchusb.c @@ -42,9 +42,9 @@ #include #ifdef CONFIG_USB_DEBUG - #define DEBUG + #define DEBUG #else - #undef DEBUG + #undef DEBUG #endif #include @@ -93,255 +93,275 @@ module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); struct mtouch_usb { - unsigned char *data; - dma_addr_t data_dma; - struct urb *irq; - struct usb_device *udev; - struct input_dev input; - char name[128]; - char phys[64]; + unsigned char *data; + dma_addr_t data_dma; + struct urb *irq; + struct usb_device *udev; + struct input_dev input; + int open; + char name[128]; + char phys[64]; }; -static struct usb_device_id mtouchusb_devices[] = { - { USB_DEVICE(0x0596, 0x0001) }, - { } +static struct usb_device_id mtouchusb_devices [] = { + { USB_DEVICE(0x0596, 0x0001) }, + { } }; static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) { - struct mtouch_usb *mtouch = urb->context; - int retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ETIMEDOUT: - /* this urb is timing out */ - dbg("%s - urb timed out - was the device unplugged?", - __FUNCTION__); - return; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __FUNCTION__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", - __FUNCTION__, urb->status); - goto exit; - } - - input_regs(&mtouch->input, regs); - input_report_key(&mtouch->input, BTN_TOUCH, - MTOUCHUSB_GET_TOUCHED(mtouch->data)); - input_report_abs(&mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data)); - input_report_abs(&mtouch->input, ABS_Y, + struct mtouch_usb *mtouch = urb->context; + int retval; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ETIMEDOUT: + /* this urb is timing out */ + dbg("%s - urb timed out - was the device unplugged?", + __FUNCTION__); + return; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __FUNCTION__, urb->status); + goto exit; + } + + input_regs(&mtouch->input, regs); + input_report_key(&mtouch->input, BTN_TOUCH, + MTOUCHUSB_GET_TOUCHED(mtouch->data)); + input_report_abs(&mtouch->input, ABS_X, + MTOUCHUSB_GET_XC(mtouch->data)); + input_report_abs(&mtouch->input, ABS_Y, (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) - - MTOUCHUSB_GET_YC(mtouch->data)); - input_sync(&mtouch->input); + - MTOUCHUSB_GET_YC(mtouch->data)); + input_sync(&mtouch->input); exit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err("%s - usb_submit_urb failed with result: %d", - __FUNCTION__, retval); + retval = usb_submit_urb (urb, GFP_ATOMIC); + if (retval) + err ("%s - usb_submit_urb failed with result: %d", + __FUNCTION__, retval); } -static int mtouchusb_open(struct input_dev *input) +static int mtouchusb_open (struct input_dev *input) { - struct mtouch_usb *mtouch = input->private; + struct mtouch_usb *mtouch = input->private; - mtouch->irq->dev = mtouch->udev; + if (mtouch->open++) + return 0; - if (usb_submit_urb(mtouch->irq, GFP_ATOMIC)) - return -EIO; + mtouch->irq->dev = mtouch->udev; - return 0; + if (usb_submit_urb (mtouch->irq, GFP_ATOMIC)) { + mtouch->open--; + return -EIO; + } + + return 0; } -static void mtouchusb_close(struct input_dev *input) +static void mtouchusb_close (struct input_dev *input) { - struct mtouch_usb *mtouch = input->private; + struct mtouch_usb *mtouch = input->private; - usb_kill_urb(mtouch->irq); + if (!--mtouch->open) + usb_kill_urb (mtouch->irq); } static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) { - dbg("%s - called", __FUNCTION__); + dbg("%s - called", __FUNCTION__); - mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, - SLAB_ATOMIC, &mtouch->data_dma); + mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, + SLAB_ATOMIC, &mtouch->data_dma); - if (!mtouch->data) - return -1; + if (!mtouch->data) + return -1; - return 0; + return 0; } static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) { - dbg("%s - called", __FUNCTION__); + dbg("%s - called", __FUNCTION__); - if (mtouch->data) - usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, - mtouch->data, mtouch->data_dma); + if (mtouch->data) + usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, + mtouch->data, mtouch->data_dma); } static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - struct mtouch_usb *mtouch; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = interface_to_usbdev(intf); - char path[64]; - int nRet; - - dbg("%s - called", __FUNCTION__); - - dbg("%s - setting interface", __FUNCTION__); - interface = intf->cur_altsetting; - - dbg("%s - setting endpoint", __FUNCTION__); - endpoint = &interface->endpoint[0].desc; - - if (!(mtouch = kmalloc(sizeof(struct mtouch_usb), GFP_KERNEL))) { - err("%s - Out of memory.", __FUNCTION__); - return -ENOMEM; - } - - memset(mtouch, 0, sizeof(struct mtouch_usb)); - mtouch->udev = udev; - - dbg("%s - allocating buffers", __FUNCTION__); - if (mtouchusb_alloc_buffers(udev, mtouch)) { - mtouchusb_free_buffers(udev, mtouch); - kfree(mtouch); - return -ENOMEM; - } - - mtouch->input.private = mtouch; - mtouch->input.open = mtouchusb_open; - mtouch->input.close = mtouchusb_close; - - usb_make_path(udev, path, 64); - sprintf(mtouch->phys, "%s/input0", path); - - mtouch->input.name = mtouch->name; - mtouch->input.phys = mtouch->phys; - mtouch->input.id.bustype = BUS_USB; - mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); - mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); - mtouch->input.dev = &intf->dev; - - mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); - mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - - /* Used to Scale Compensated Data and Flip Y */ - mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; - mtouch->input.absmax[ABS_X] = raw_coordinates ? - MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; - mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; - mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; - mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; - mtouch->input.absmax[ABS_Y] = raw_coordinates ? - MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; - mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; - mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; + struct mtouch_usb *mtouch; + struct usb_host_interface *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_device *udev = interface_to_usbdev (intf); + char path[64]; + int nRet; + + dbg("%s - called", __FUNCTION__); + + dbg("%s - setting interface", __FUNCTION__); + interface = intf->cur_altsetting; + + dbg("%s - setting endpoint", __FUNCTION__); + endpoint = &interface->endpoint[0].desc; + + if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) { + err("%s - Out of memory.", __FUNCTION__); + return -ENOMEM; + } + + memset(mtouch, 0, sizeof(struct mtouch_usb)); + mtouch->udev = udev; + + dbg("%s - allocating buffers", __FUNCTION__); + if (mtouchusb_alloc_buffers(udev, mtouch)) { + mtouchusb_free_buffers(udev, mtouch); + kfree(mtouch); + return -ENOMEM; + } + + mtouch->input.private = mtouch; + mtouch->input.open = mtouchusb_open; + mtouch->input.close = mtouchusb_close; + + usb_make_path(udev, path, 64); + sprintf(mtouch->phys, "%s/input0", path); + + mtouch->input.name = mtouch->name; + mtouch->input.phys = mtouch->phys; + mtouch->input.id.bustype = BUS_USB; + mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); + mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); + mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + mtouch->input.dev = &intf->dev; + + mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); + mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + + /* Used to Scale Compensated Data and Flip Y */ + mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; + mtouch->input.absmax[ABS_X] = raw_coordinates ? \ + MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; + mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; + mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; + mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; + mtouch->input.absmax[ABS_Y] = raw_coordinates ? \ + MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; + mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; + mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; if (udev->manufacturer) strcat(mtouch->name, udev->manufacturer); if (udev->product) sprintf(mtouch->name, "%s %s", mtouch->name, udev->product); - if (!strlen(mtouch->name)) - sprintf(mtouch->name, "USB Touchscreen %04x:%04x", - mtouch->input.id.vendor, mtouch->input.id.product); - - nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), - MTOUCHUSB_RESET, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); - dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", - __FUNCTION__, nRet); - - dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); - mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mtouch->irq) { - dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); - mtouchusb_free_buffers(udev, mtouch); - kfree(mtouch); - return -ENOMEM; - } - - dbg("%s - usb_fill_int_urb", __FUNCTION__); - usb_fill_int_urb(mtouch->irq, mtouch->udev, - usb_rcvintpipe(mtouch->udev, 0x81), - mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE, - mtouchusb_irq, mtouch, endpoint->bInterval); - - dbg("%s - input_register_device", __FUNCTION__); - input_register_device(&mtouch->input); - - nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), - MTOUCHUSB_ASYNC_REPORT, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); - dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", - __FUNCTION__, nRet); - - printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); - usb_set_intfdata(intf, mtouch); - - return 0; + if (!strlen(mtouch->name)) + sprintf(mtouch->name, "USB Touchscreen %04x:%04x", + mtouch->input.id.vendor, mtouch->input.id.product); + + nRet = usb_control_msg(mtouch->udev, + usb_rcvctrlpipe(udev, 0), + MTOUCHUSB_RESET, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 1, + 0, + NULL, + 0, + USB_CTRL_SET_TIMEOUT); + dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", + __FUNCTION__, nRet); + + dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); + mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); + if (!mtouch->irq) { + dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); + mtouchusb_free_buffers(udev, mtouch); + kfree(mtouch); + return -ENOMEM; + } + + dbg("%s - usb_fill_int_urb", __FUNCTION__); + usb_fill_int_urb(mtouch->irq, + mtouch->udev, + usb_rcvintpipe(mtouch->udev, 0x81), + mtouch->data, + MTOUCHUSB_REPORT_DATA_SIZE, + mtouchusb_irq, + mtouch, + endpoint->bInterval); + + dbg("%s - input_register_device", __FUNCTION__); + input_register_device(&mtouch->input); + + nRet = usb_control_msg(mtouch->udev, + usb_rcvctrlpipe(udev, 0), + MTOUCHUSB_ASYNC_REPORT, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 1, + 1, + NULL, + 0, + USB_CTRL_SET_TIMEOUT); + dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", + __FUNCTION__, nRet); + + printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); + usb_set_intfdata(intf, mtouch); + + return 0; } static void mtouchusb_disconnect(struct usb_interface *intf) { - struct mtouch_usb *mtouch = usb_get_intfdata(intf); - - dbg("%s - called", __FUNCTION__); - usb_set_intfdata(intf, NULL); - if (mtouch) { - dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); - usb_kill_urb(mtouch->irq); - input_unregister_device(&mtouch->input); - usb_free_urb(mtouch->irq); - mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); - kfree(mtouch); - } + struct mtouch_usb *mtouch = usb_get_intfdata (intf); + + dbg("%s - called", __FUNCTION__); + usb_set_intfdata(intf, NULL); + if (mtouch) { + dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); + usb_kill_urb(mtouch->irq); + input_unregister_device(&mtouch->input); + usb_free_urb(mtouch->irq); + mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); + kfree(mtouch); + } } -MODULE_DEVICE_TABLE(usb, mtouchusb_devices); +MODULE_DEVICE_TABLE (usb, mtouchusb_devices); static struct usb_driver mtouchusb_driver = { - .owner = THIS_MODULE, - .name = "mtouchusb", - .probe = mtouchusb_probe, - .disconnect = mtouchusb_disconnect, - .id_table = mtouchusb_devices, + .owner = THIS_MODULE, + .name = "mtouchusb", + .probe = mtouchusb_probe, + .disconnect = mtouchusb_disconnect, + .id_table = mtouchusb_devices, }; -static int __init mtouchusb_init(void) -{ - dbg("%s - called", __FUNCTION__); - return usb_register(&mtouchusb_driver); +static int __init mtouchusb_init(void) { + dbg("%s - called", __FUNCTION__); + return usb_register(&mtouchusb_driver); } -static void __exit mtouchusb_cleanup(void) -{ - dbg("%s - called", __FUNCTION__); - usb_deregister(&mtouchusb_driver); +static void __exit mtouchusb_cleanup(void) { + dbg("%s - called", __FUNCTION__); + usb_deregister(&mtouchusb_driver); } module_init(mtouchusb_init); module_exit(mtouchusb_cleanup); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/input/powermate.c b/trunk/drivers/usb/input/powermate.c index 3975b309d55f..7fa2f9b9fb69 100644 --- a/trunk/drivers/usb/input/powermate.c +++ b/trunk/drivers/usb/input/powermate.c @@ -10,7 +10,7 @@ * back to the host when polled by the USB controller. * * Testing with the knob I have has shown that it measures approximately 94 "clicks" - * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was + * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was * a variable speed cordless electric drill) has shown that the device can measure * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from * the host. If it counts more than 7 clicks before it is polled, it will wrap back @@ -120,9 +120,9 @@ static void powermate_irq(struct urb *urb, struct pt_regs *regs) /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ static void powermate_sync_state(struct powermate_device *pm) { - if (pm->requires_update == 0) + if (pm->requires_update == 0) return; /* no updates are required */ - if (pm->config->status == -EINPROGRESS) + if (pm->config->status == -EINPROGRESS) return; /* an update is already in progress; it'll issue this update when it completes */ if (pm->requires_update & UPDATE_PULSE_ASLEEP){ @@ -142,7 +142,7 @@ static void powermate_sync_state(struct powermate_device *pm) 2: multiply the speed the argument only has an effect for operations 0 and 2, and ranges between 1 (least effect) to 255 (maximum effect). - + thus, several states are equivalent and are coalesced into one state. we map this onto a range from 0 to 510, with: @@ -151,7 +151,7 @@ static void powermate_sync_state(struct powermate_device *pm) 256 -- 510 -- use multiple (510 = fastest). Only values of 'arg' quite close to 255 are particularly useful/spectacular. - */ + */ if (pm->pulse_speed < 255){ op = 0; // divide arg = 255 - pm->pulse_speed; @@ -199,14 +199,14 @@ static void powermate_config_complete(struct urb *urb, struct pt_regs *regs) if (urb->status) printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); - + spin_lock_irqsave(&pm->lock, flags); powermate_sync_state(pm); spin_unlock_irqrestore(&pm->lock, flags); } /* Set the LED up as described and begin the sync with the hardware if required */ -static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, +static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, int pulse_table, int pulse_asleep, int pulse_awake) { unsigned long flags; @@ -229,7 +229,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne /* mark state updates which are required */ if (static_brightness != pm->static_brightness){ pm->static_brightness = static_brightness; - pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; + pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; } if (pulse_asleep != pm->pulse_asleep){ pm->pulse_asleep = pulse_asleep; @@ -246,7 +246,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne } powermate_sync_state(pm); - + spin_unlock_irqrestore(&pm->lock, flags); } @@ -257,19 +257,19 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig struct powermate_device *pm = dev->private; if (type == EV_MSC && code == MSC_PULSELED){ - /* + /* bits 0- 7: 8 bits: LED brightness bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. bits 17-18: 2 bits: pulse table (0, 1, 2 valid) bit 19: 1 bit : pulse whilst asleep? bit 20: 1 bit : pulse constantly? - */ + */ int static_brightness = command & 0xFF; // bits 0-7 int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 int pulse_table = (command >> 17) & 0x3; // bits 17-18 int pulse_asleep = (command >> 19) & 0x1; // bit 19 int pulse_awake = (command >> 20) & 0x1; // bit 20 - + powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); } @@ -378,7 +378,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i switch (le16_to_cpu(udev->descriptor.idProduct)) { case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; - default: + default: pm->input.name = pm_name_soundknob; printk(KERN_WARNING "powermate: unknown product id %04x\n", le16_to_cpu(udev->descriptor.idProduct)); @@ -402,11 +402,11 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i usb_make_path(udev, path, 64); snprintf(pm->phys, 64, "%s/input0", path); printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys); - + /* force an update of everything */ pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters - + usb_set_intfdata(intf, pm); return 0; } diff --git a/trunk/drivers/usb/input/touchkitusb.c b/trunk/drivers/usb/input/touchkitusb.c index 386595ee21c0..a71f1bbd0a17 100644 --- a/trunk/drivers/usb/input/touchkitusb.c +++ b/trunk/drivers/usb/input/touchkitusb.c @@ -69,6 +69,7 @@ struct touchkit_usb { struct urb *irq; struct usb_device *udev; struct input_dev input; + int open; char name[128]; char phys[64]; }; @@ -133,10 +134,15 @@ static int touchkit_open(struct input_dev *input) { struct touchkit_usb *touchkit = input->private; + if (touchkit->open++) + return 0; + touchkit->irq->dev = touchkit->udev; - if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) + if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) { + touchkit->open--; return -EIO; + } return 0; } @@ -145,7 +151,8 @@ static void touchkit_close(struct input_dev *input) { struct touchkit_usb *touchkit = input->private; - usb_kill_urb(touchkit->irq); + if (!--touchkit->open) + usb_kill_urb(touchkit->irq); } static int touchkit_alloc_buffers(struct usb_device *udev, diff --git a/trunk/drivers/usb/input/usbkbd.c b/trunk/drivers/usb/input/usbkbd.c index f35db1974c42..7038fb9d1ced 100644 --- a/trunk/drivers/usb/input/usbkbd.c +++ b/trunk/drivers/usb/input/usbkbd.c @@ -9,18 +9,18 @@ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -72,6 +72,7 @@ struct usb_kbd { unsigned char newleds; char name[128]; char phys[64]; + int open; unsigned char *new; struct usb_ctrlrequest *cr; @@ -165,7 +166,7 @@ static void usb_kbd_led(struct urb *urb, struct pt_regs *regs) if (urb->status) warn("led urb status %d received", urb->status); - + if (*(kbd->leds) == kbd->newleds) return; @@ -179,9 +180,14 @@ static int usb_kbd_open(struct input_dev *dev) { struct usb_kbd *kbd = dev->private; + if (kbd->open++) + return 0; + kbd->irq->dev = kbd->usbdev; - if (usb_submit_urb(kbd->irq, GFP_KERNEL)) + if (usb_submit_urb(kbd->irq, GFP_KERNEL)) { + kbd->open--; return -EIO; + } return 0; } @@ -190,7 +196,8 @@ static void usb_kbd_close(struct input_dev *dev) { struct usb_kbd *kbd = dev->private; - usb_kill_urb(kbd->irq); + if (!--kbd->open) + usb_kill_urb(kbd->irq); } static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) @@ -223,7 +230,7 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); } -static int usb_kbd_probe(struct usb_interface *iface, +static int usb_kbd_probe(struct usb_interface *iface, const struct usb_device_id *id) { struct usb_device * dev = interface_to_usbdev(iface); @@ -265,7 +272,7 @@ static int usb_kbd_probe(struct usb_interface *iface, for (i = 0; i < 255; i++) set_bit(usb_kbd_keycode[i], kbd->dev.keybit); clear_bit(0, kbd->dev.keybit); - + kbd->dev.private = kbd; kbd->dev.event = usb_kbd_event; kbd->dev.open = usb_kbd_open; @@ -287,7 +294,7 @@ static int usb_kbd_probe(struct usb_interface *iface, sprintf(kbd->phys, "%s/input0", path); kbd->dev.name = kbd->name; - kbd->dev.phys = kbd->phys; + kbd->dev.phys = kbd->phys; kbd->dev.id.bustype = BUS_USB; kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); @@ -322,7 +329,7 @@ static int usb_kbd_probe(struct usb_interface *iface, static void usb_kbd_disconnect(struct usb_interface *intf) { struct usb_kbd *kbd = usb_get_intfdata (intf); - + usb_set_intfdata(intf, NULL); if (kbd) { usb_kill_urb(kbd->irq); diff --git a/trunk/drivers/usb/input/usbmouse.c b/trunk/drivers/usb/input/usbmouse.c index 1ec41b5effe6..01155bbddd43 100644 --- a/trunk/drivers/usb/input/usbmouse.c +++ b/trunk/drivers/usb/input/usbmouse.c @@ -9,18 +9,18 @@ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -51,6 +51,7 @@ struct usb_mouse { struct usb_device *usbdev; struct input_dev dev; struct urb *irq; + int open; signed char *data; dma_addr_t data_dma; @@ -100,9 +101,14 @@ static int usb_mouse_open(struct input_dev *dev) { struct usb_mouse *mouse = dev->private; + if (mouse->open++) + return 0; + mouse->irq->dev = mouse->usbdev; - if (usb_submit_urb(mouse->irq, GFP_KERNEL)) + if (usb_submit_urb(mouse->irq, GFP_KERNEL)) { + mouse->open--; return -EIO; + } return 0; } @@ -111,7 +117,8 @@ static void usb_mouse_close(struct input_dev *dev) { struct usb_mouse *mouse = dev->private; - usb_kill_urb(mouse->irq); + if (!--mouse->open) + usb_kill_urb(mouse->irq); } static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) @@ -125,19 +132,19 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 1) + if (interface->desc.bNumEndpoints != 1) return -ENODEV; endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & 0x80)) + if (!(endpoint->bEndpointAddress & 0x80)) return -ENODEV; - if ((endpoint->bmAttributes & 3) != 3) + if ((endpoint->bmAttributes & 3) != 3) return -ENODEV; pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) + if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return -ENOMEM; memset(mouse, 0, sizeof(struct usb_mouse)); @@ -202,7 +209,7 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ static void usb_mouse_disconnect(struct usb_interface *intf) { struct usb_mouse *mouse = usb_get_intfdata (intf); - + usb_set_intfdata(intf, NULL); if (mouse) { usb_kill_urb(mouse->irq); @@ -231,7 +238,7 @@ static struct usb_driver usb_mouse_driver = { static int __init usb_mouse_init(void) { int retval = usb_register(&usb_mouse_driver); - if (retval == 0) + if (retval == 0) info(DRIVER_VERSION ":" DRIVER_DESC); return retval; } diff --git a/trunk/drivers/usb/input/wacom.c b/trunk/drivers/usb/input/wacom.c index f6b34af66b3d..fec04dda088e 100644 --- a/trunk/drivers/usb/input/wacom.c +++ b/trunk/drivers/usb/input/wacom.c @@ -9,7 +9,7 @@ * Copyright (c) 2000 Daniel Egger * Copyright (c) 2001 Frederic Lepied * Copyright (c) 2004 Panagiotis Issaris - * Copyright (c) 2002-2005 Ping Cheng + * Copyright (c) 2002-2004 Ping Cheng * * ChangeLog: * v0.1 (vp) - Initial release @@ -18,7 +18,7 @@ * v0.4 (sm) - Support for more Intuos models, menustrip * relative mode, proximity. * v0.5 (vp) - Big cleanup, nifty features removed, - * they belong in userspace + * they belong in userspace * v1.8 (vp) - Submit URB only when operating, moved to CVS, * use input_report_key instead of report_btn and * other cleanups @@ -51,9 +51,6 @@ * - Cleanups here and there * v1.30.1 (pi) - Added Graphire3 support * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... - * v1.43 (pc) - Added support for Cintiq 21UX - - Fixed a Graphire bug - - Merged wacom_intuos3_irq into wacom_intuos_irq */ /* @@ -75,7 +72,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.43" +#define DRIVER_VERSION "v1.40" #define DRIVER_AUTHOR "Vojtech Pavlik " #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_LICENSE "GPL" @@ -86,16 +83,6 @@ MODULE_LICENSE(DRIVER_LICENSE); #define USB_VENDOR_ID_WACOM 0x056a -enum { - PENPARTNER = 0, - GRAPHIRE, - PL, - INTUOS, - INTUOS3, - CINTIQ, - MAX_TYPE -}; - struct wacom_features { char *name; int pktlen; @@ -115,6 +102,7 @@ struct wacom { struct urb *irq; struct wacom_features *features; int tool[2]; + int open; __u32 serial[2]; char phys[32]; }; @@ -161,7 +149,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) prox = data[1] & 0x40; input_regs(dev, regs); - + if (prox) { pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); @@ -178,7 +166,8 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) if (!wacom->tool[0]) { /* Going into proximity select tool */ wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN; - } else { + } + else { /* was entered with stylus2 pressed */ if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) { /* report out proximity for previous tool */ @@ -193,15 +182,16 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) wacom->tool[1] = BTN_TOOL_PEN; } input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */ - input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); - input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); + input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 7) | ((__u32)(data[1] & 0x03) << 14)); + input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 7) | ((__u32)(data[4] & 0x03) << 14)); input_report_abs(dev, ABS_PRESSURE, pressure); input_report_key(dev, BTN_TOUCH, data[4] & 0x08); input_report_key(dev, BTN_STYLUS, data[4] & 0x10); /* Only allow the stylus2 button to be reported for the pen tool. */ input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); - } else { + } + else { /* report proximity-out of a (valid) tool */ if (wacom->tool[1] != BTN_TOOL_RUBBER) { /* Unknown tool selected default to pen tool */ @@ -213,7 +203,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) wacom->tool[0] = prox; /* Save proximity state */ input_sync(dev); - exit: +exit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", @@ -242,16 +232,20 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - if (data[0] != 2) { + if (data[0] != 2) + { printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); goto exit; } input_regs(dev, regs); - if (data[1] & 0x04) { + if (data[1] & 0x04) + { input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20); input_report_key(dev, BTN_TOUCH, data[1] & 0x08); - } else { + } + else + { input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); input_report_key(dev, BTN_TOUCH, data[1] & 0x01); } @@ -263,7 +257,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) input_sync(dev); - exit: +exit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", @@ -306,7 +300,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); input_sync(dev); - exit: +exit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", @@ -346,47 +340,47 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) input_regs(dev, regs); - if (data[1] & 0x10) { /* in prox */ + switch ((data[1] >> 5) & 3) { - switch ((data[1] >> 5) & 3) { + case 0: /* Pen */ + input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80); + break; - case 0: /* Pen */ - wacom->tool[0] = BTN_TOOL_PEN; - break; + case 1: /* Rubber */ + input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80); + break; - case 1: /* Rubber */ - wacom->tool[0] = BTN_TOOL_RUBBER; - break; + case 2: /* Mouse with wheel */ + input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); + input_report_rel(dev, REL_WHEEL, (signed char) data[6]); + /* fall through */ - case 2: /* Mouse with wheel */ - input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); - input_report_rel(dev, REL_WHEEL, (signed char) data[6]); - /* fall through */ + case 3: /* Mouse without wheel */ + input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24); + input_report_key(dev, BTN_LEFT, data[1] & 0x01); + input_report_key(dev, BTN_RIGHT, data[1] & 0x02); + input_report_abs(dev, ABS_DISTANCE, data[7]); - case 3: /* Mouse without wheel */ - wacom->tool[0] = BTN_TOOL_MOUSE; - input_report_key(dev, BTN_LEFT, data[1] & 0x01); - input_report_key(dev, BTN_RIGHT, data[1] & 0x02); - input_report_abs(dev, ABS_DISTANCE, data[7]); - break; - } + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + + input_sync(dev); + goto exit; } if (data[1] & 0x80) { input_report_abs(dev, ABS_X, x); input_report_abs(dev, ABS_Y, y); } - if (wacom->tool[0] != BTN_TOOL_MOUSE) { - input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); - input_report_key(dev, BTN_TOUCH, data[1] & 0x01); - input_report_key(dev, BTN_STYLUS, data[1] & 0x02); - input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); - } - input_report_key(dev, wacom->tool[0], data[1] & 0x10); + input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); + input_report_key(dev, BTN_TOUCH, data[1] & 0x01); + input_report_key(dev, BTN_STYLUS, data[1] & 0x02); + input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); + input_sync(dev); - exit: +exit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", @@ -404,13 +398,14 @@ static int wacom_intuos_inout(struct urb *urb) idx = data[1] & 0x01; /* Enter report */ - if ((data[1] & 0xfc) == 0xc0) { + if ((data[1] & 0xfc) == 0xc0) + { /* serial number of the tool */ - wacom->serial[idx] = ((data[3] & 0x0f) << 28) + - (data[4] << 20) + (data[5] << 12) + - (data[6] << 4) + (data[7] >> 4); + wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) + + ((__u32)data[4] << 20) + ((__u32)data[5] << 12) + + ((__u32)data[6] << 4) + (data[7] >> 4); - switch ((data[2] << 4) | (data[3] >> 4)) { + switch (((__u32)data[2] << 4) | (data[3] >> 4)) { case 0x812: /* Inking pen */ case 0x801: /* Intuos3 Inking pen */ case 0x012: @@ -454,7 +449,7 @@ static int wacom_intuos_inout(struct urb *urb) case 0x112: case 0x913: /* Intuos3 Airbrush */ wacom->tool[idx] = BTN_TOOL_AIRBRUSH; - break; + break; /* Airbrush */ default: /* Unknown tool */ wacom->tool[idx] = BTN_TOOL_PEN; } @@ -483,8 +478,9 @@ static void wacom_intuos_general(struct urb *urb) unsigned int t; /* general pen packet */ - if ((data[1] & 0xb8) == 0xa0) { - t = (data[6] << 2) | ((data[7] >> 6) & 3); + if ((data[1] & 0xb8) == 0xa0) + { + t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); input_report_abs(dev, ABS_PRESSURE, t); input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); @@ -495,9 +491,10 @@ static void wacom_intuos_general(struct urb *urb) } /* airbrush second packet */ - if ((data[1] & 0xbc) == 0xb4) { + if ((data[1] & 0xbc) == 0xb4) + { input_report_abs(dev, ABS_WHEEL, - (data[6] << 2) | ((data[7] >> 6) & 3)); + ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); @@ -529,7 +526,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { + if (data[0] != 2 && data[0] != 5 && data[0] != 6) { dbg("wacom_intuos_irq: received unknown report #%d", data[0]); goto exit; } @@ -539,10 +536,107 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) /* tool number */ idx = data[1] & 0x01; + /* process in/out prox events */ + if (wacom_intuos_inout(urb)) goto exit; + + input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); + input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); + input_report_abs(dev, ABS_DISTANCE, data[9]); + + /* process general packets */ + wacom_intuos_general(urb); + + if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */ + + if (data[1] & 0x02) { /* Rotation packet */ + + t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); + input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2); + + } else { + + if ((data[1] & 0x10) == 0) { /* 4D mouse packets */ + + input_report_key(dev, BTN_LEFT, data[8] & 0x01); + input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); + input_report_key(dev, BTN_RIGHT, data[8] & 0x04); + + input_report_key(dev, BTN_SIDE, data[8] & 0x20); + input_report_key(dev, BTN_EXTRA, data[8] & 0x10); + t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); + input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); + + } else { + if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */ + input_report_key(dev, BTN_LEFT, data[8] & 0x04); + input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); + input_report_key(dev, BTN_RIGHT, data[8] & 0x10); + input_report_rel(dev, REL_WHEEL, + (-(__u32)(data[8] & 0x01) + (__u32)((data[8] & 0x02) >> 1))); + } + else { /* Lens cursor packets */ + input_report_key(dev, BTN_LEFT, data[8] & 0x01); + input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); + input_report_key(dev, BTN_RIGHT, data[8] & 0x04); + input_report_key(dev, BTN_SIDE, data[8] & 0x10); + input_report_key(dev, BTN_EXTRA, data[8] & 0x08); + } + } + } + } + + input_report_key(dev, wacom->tool[idx], 1); + input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); + input_sync(dev); + +exit: + retval = usb_submit_urb (urb, GFP_ATOMIC); + if (retval) + err ("%s - usb_submit_urb failed with result %d", + __FUNCTION__, retval); +} + +static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs) +{ + struct wacom *wacom = urb->context; + unsigned char *data = wacom->data; + struct input_dev *dev = &wacom->dev; + unsigned int t; + int idx, retval; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + goto exit; + } + + /* check for valid report */ + if (data[0] != 2 && data[0] != 5 && data[0] != 12) + { + printk(KERN_INFO "wacom_intuos3_irq: received unknown report #%d\n", data[0]); + goto exit; + } + + input_regs(dev, regs); + + /* tool index is always 0 here since there is no dual input tool */ + idx = data[1] & 0x01; + /* pad packets. Works as a second tool and is always in prox */ - if (data[0] == 12) { + if (data[0] == 12) + { /* initiate the pad as a device */ - if (wacom->tool[1] != BTN_TOOL_FINGER) { + if (wacom->tool[1] != BTN_TOOL_FINGER) + { wacom->tool[1] = BTN_TOOL_FINGER; input_report_key(dev, wacom->tool[1], 1); } @@ -562,78 +656,37 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) } /* process in/out prox events */ - if (wacom_intuos_inout(urb)) - goto exit; + if (wacom_intuos_inout(urb)) goto exit; - /* Cintiq doesn't send data when RDY bit isn't set */ - if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) - return; - - if (wacom->features->type >= INTUOS3) { - input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); - input_report_abs(dev, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); - input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); - } else { - input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); - input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); - input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); - } + input_report_abs(dev, ABS_X, ((__u32)data[2] << 9) | ((__u32)data[3] << 1) | ((data[9] >> 1) & 1)); + input_report_abs(dev, ABS_Y, ((__u32)data[4] << 9) | ((__u32)data[5] << 1) | (data[9] & 1)); + input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); /* process general packets */ wacom_intuos_general(urb); - /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */ - if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { - - if (data[1] & 0x02) { - /* Rotation packet */ - if (wacom->features->type >= INTUOS3) { - /* I3 marker pen rotation reported as wheel - * due to valuator limitation - */ - t = (data[6] << 3) | ((data[7] >> 5) & 7); - t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : - ((t-1) / 2 + 450)) : (450 - t / 2) ; - input_report_abs(dev, ABS_WHEEL, t); - } else { - /* 4D mouse rotation packet */ - t = (data[6] << 3) | ((data[7] >> 5) & 7); - input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? - ((t - 1) / 2) : -t / 2); - } - - } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) { - /* 4D mouse packet */ - input_report_key(dev, BTN_LEFT, data[8] & 0x01); - input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); - input_report_key(dev, BTN_RIGHT, data[8] & 0x04); - - input_report_key(dev, BTN_SIDE, data[8] & 0x20); - input_report_key(dev, BTN_EXTRA, data[8] & 0x10); - t = (data[6] << 2) | ((data[7] >> 6) & 3); - input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); + if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) + { + /* Marker pen rotation packet. Reported as wheel due to valuator limitation */ + if (data[1] & 0x02) + { + t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); + t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : + ((t-1) / 2 + 450)) : (450 - t / 2) ; + input_report_abs(dev, ABS_WHEEL, t); + } - } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { - /* 2D mouse packet */ + /* 2D mouse packets */ + if (wacom->tool[idx] == BTN_TOOL_MOUSE) + { input_report_key(dev, BTN_LEFT, data[8] & 0x04); input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); input_report_key(dev, BTN_RIGHT, data[8] & 0x10); - input_report_rel(dev, REL_WHEEL, ((data[8] & 0x02) >> 1) - - (data[8] & 0x01)); - - /* I3 2D mouse side buttons */ - if (wacom->features->type == INTUOS3) { - input_report_key(dev, BTN_SIDE, data[8] & 0x40); - input_report_key(dev, BTN_EXTRA, data[8] & 0x20); - } - - } else if (wacom->features->type < INTUOS3) { - /* Lens cursor packets */ - input_report_key(dev, BTN_LEFT, data[8] & 0x01); - input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); - input_report_key(dev, BTN_RIGHT, data[8] & 0x04); - input_report_key(dev, BTN_SIDE, data[8] & 0x10); - input_report_key(dev, BTN_EXTRA, data[8] & 0x08); + input_report_key(dev, BTN_SIDE, data[8] & 0x40); + input_report_key(dev, BTN_EXTRA, data[8] & 0x20); + /* mouse wheel is positive when rolled backwards */ + input_report_rel(dev, REL_WHEEL, ((__u32)((data[8] & 0x02) >> 1) + - (__u32)(data[8] & 0x01))); } } @@ -649,36 +702,35 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) } static struct wacom_features wacom_features[] = { - { "Wacom Penpartner", 7, 5040, 3780, 255, 32, PENPARTNER, wacom_penpartner_irq }, - { "Wacom Graphire", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, - { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, - { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, - { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, - { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, - { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom PL400", 8, 5408, 4056, 255, 32, PL, wacom_pl_irq }, - { "Wacom PL500", 8, 6144, 4608, 255, 32, PL, wacom_pl_irq }, - { "Wacom PL600", 8, 6126, 4604, 255, 32, PL, wacom_pl_irq }, - { "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_pl_irq }, - { "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_pl_irq }, - { "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq }, - { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, - { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, - { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq }, - { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq }, - { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq }, - { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq }, - { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, - { } + { "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq }, + { "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, + { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, + { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, 1, wacom_graphire_irq }, + { "Wacom Graphire3", 8, 10208, 7424, 511, 32, 1, wacom_graphire_irq }, + { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, 1, wacom_graphire_irq }, + { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom PL400", 8, 5408, 4056, 255, 32, 3, wacom_pl_irq }, + { "Wacom PL500", 8, 6144, 4608, 255, 32, 3, wacom_pl_irq }, + { "Wacom PL600", 8, 6126, 4604, 255, 32, 3, wacom_pl_irq }, + { "Wacom PL600SX", 8, 6260, 5016, 255, 32, 3, wacom_pl_irq }, + { "Wacom PL550", 8, 6144, 4608, 511, 32, 3, wacom_pl_irq }, + { "Wacom PL800", 8, 7220, 5780, 511, 32, 3, wacom_pl_irq }, + { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, + { "Wacom Volito", 8, 5104, 3712, 511, 32, 1, wacom_graphire_irq }, + { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, 3, wacom_ptu_irq }, + { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, 4, wacom_intuos3_irq }, + { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq }, + { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq }, + { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, + { } }; static struct usb_device_id wacom_ids[] = { @@ -709,7 +761,6 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, { } }; @@ -720,9 +771,14 @@ static int wacom_open(struct input_dev *dev) { struct wacom *wacom = dev->private; + if (wacom->open++) + return 0; + wacom->irq->dev = wacom->usbdev; - if (usb_submit_urb(wacom->irq, GFP_KERNEL)) + if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { + wacom->open--; return -EIO; + } return 0; } @@ -731,7 +787,8 @@ static void wacom_close(struct input_dev *dev) { struct wacom *wacom = dev->private; - usb_kill_urb(wacom->irq); + if (!--wacom->open) + usb_kill_urb(wacom->irq); } static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -766,33 +823,32 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); switch (wacom->features->type) { - case GRAPHIRE: + case 1: wacom->dev.evbit[0] |= BIT(EV_REL); wacom->dev.relbit[0] |= BIT(REL_WHEEL); wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); + wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); break; - case INTUOS3: - case CINTIQ: + case 4: /* new functions for Intuos3 */ wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); 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); wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY); /* fall through */ - case INTUOS: + case 2: wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); wacom->dev.relbit[0] |= BIT(REL_WHEEL); wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) + wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); break; - case PL: - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); + case 3: + wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); break; } diff --git a/trunk/drivers/usb/input/xpad.c b/trunk/drivers/usb/input/xpad.c index a7fa1b17dcfe..d65edb22e545 100644 --- a/trunk/drivers/usb/input/xpad.c +++ b/trunk/drivers/usb/input/xpad.c @@ -104,12 +104,13 @@ MODULE_DEVICE_TABLE (usb, xpad_table); struct usb_xpad { struct input_dev dev; /* input device interface */ struct usb_device *udev; /* usb device */ - + struct urb *irq_in; /* urb for interrupt in report */ unsigned char *idata; /* input data */ dma_addr_t idata_dma; - + char phys[65]; /* physical device path */ + int open_count; /* reference count */ }; /* @@ -127,35 +128,35 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d struct input_dev *dev = &xpad->dev; input_regs(dev, regs); - + /* left stick */ input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); - + /* right stick */ input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); - + /* triggers left/right */ input_report_abs(dev, ABS_Z, data[10]); input_report_abs(dev, ABS_RZ, data[11]); - + /* digital pad */ input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); - + /* start/back buttons and stick press left/right */ input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); input_report_key(dev, BTN_THUMBR, data[2] >> 7); - + /* "analog" buttons A, B, X, Y */ input_report_key(dev, BTN_A, data[4]); input_report_key(dev, BTN_B, data[5]); input_report_key(dev, BTN_X, data[6]); input_report_key(dev, BTN_Y, data[7]); - + /* "analog" buttons black, white */ input_report_key(dev, BTN_C, data[8]); input_report_key(dev, BTN_Z, data[9]); @@ -167,7 +168,7 @@ static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) { struct usb_xpad *xpad = urb->context; int retval; - + switch (urb->status) { case 0: /* success */ @@ -182,7 +183,7 @@ static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); goto exit; } - + xpad_process_packet(xpad, 0, xpad->idata, regs); exit: @@ -195,19 +196,25 @@ static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) static int xpad_open (struct input_dev *dev) { struct usb_xpad *xpad = dev->private; - + + if (xpad->open_count++) + return 0; + xpad->irq_in->dev = xpad->udev; - if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) + if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) { + xpad->open_count--; return -EIO; - + } + return 0; } static void xpad_close (struct input_dev *dev) { struct usb_xpad *xpad = dev->private; - - usb_kill_urb(xpad->irq_in); + + if (!--xpad->open_count) + usb_kill_urb(xpad->irq_in); } static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -217,19 +224,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id struct usb_endpoint_descriptor *ep_irq_in; char path[64]; int i; - + for (i = 0; xpad_device[i].idVendor; i++) { if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) break; } - + if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { err("cannot allocate memory for new pad"); return -ENOMEM; } memset(xpad, 0, sizeof(struct usb_xpad)); - + xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, SLAB_ATOMIC, &xpad->idata_dma); if (!xpad->idata) { @@ -244,18 +251,18 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id kfree(xpad); return -ENOMEM; } - + ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; - + usb_fill_int_urb(xpad->irq_in, udev, usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), xpad->idata, XPAD_PKT_LEN, xpad_irq_in, xpad, ep_irq_in->bInterval); xpad->irq_in->transfer_dma = xpad->idata_dma; xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - + xpad->udev = udev; - + xpad->dev.id.bustype = BUS_USB; xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); @@ -266,21 +273,21 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->dev.phys = xpad->phys; xpad->dev.open = xpad_open; xpad->dev.close = xpad_close; - + usb_make_path(udev, path, 64); snprintf(xpad->phys, 64, "%s/input0", path); - + xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - + for (i = 0; xpad_btn[i] >= 0; i++) set_bit(xpad_btn[i], xpad->dev.keybit); - + for (i = 0; xpad_abs[i] >= 0; i++) { - + signed short t = xpad_abs[i]; - + set_bit(t, xpad->dev.absbit); - + switch (t) { case ABS_X: case ABS_Y: @@ -303,11 +310,11 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id break; } } - + input_register_device(&xpad->dev); - + printk(KERN_INFO "input: %s on %s", xpad->dev.name, path); - + usb_set_intfdata(intf, xpad); return 0; } @@ -315,7 +322,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id static void xpad_disconnect(struct usb_interface *intf) { struct usb_xpad *xpad = usb_get_intfdata (intf); - + usb_set_intfdata(intf, NULL); if (xpad) { usb_kill_urb(xpad->irq_in); diff --git a/trunk/drivers/usb/net/pegasus.c b/trunk/drivers/usb/net/pegasus.c index 5f4496d8dbac..d976790312aa 100644 --- a/trunk/drivers/usb/net/pegasus.c +++ b/trunk/drivers/usb/net/pegasus.c @@ -1166,7 +1166,7 @@ static void pegasus_set_multicast(struct net_device *net) pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; if (netif_msg_link(pegasus)) pr_info("%s: Promiscuous mode enabled.\n", net->name); - } else if (net->mc_count || + } else if ((net->mc_count > multicast_filter_limit) || (net->flags & IFF_ALLMULTI)) { pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; diff --git a/trunk/drivers/usb/net/pegasus.h b/trunk/drivers/usb/net/pegasus.h index b98f2a833442..13ccedef5c7e 100644 --- a/trunk/drivers/usb/net/pegasus.h +++ b/trunk/drivers/usb/net/pegasus.h @@ -249,8 +249,6 @@ PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a, DEFAULT_GPIO_RESET) PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002, DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "LANEED USB Ethernet LD-USBL/TX", VENDOR_LANEED, 0x4005, - DEFAULT_GPIO_RESET | PEGASUS_II) PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1, diff --git a/trunk/drivers/usb/net/rtl8150.c b/trunk/drivers/usb/net/rtl8150.c index 626b016addff..8fb223385f2f 100644 --- a/trunk/drivers/usb/net/rtl8150.c +++ b/trunk/drivers/usb/net/rtl8150.c @@ -667,7 +667,7 @@ static void rtl8150_set_multicast(struct net_device *netdev) if (netdev->flags & IFF_PROMISC) { dev->rx_creg |= cpu_to_le16(0x0001); info("%s: promiscuous mode", netdev->name); - } else if (netdev->mc_count || + } else if ((netdev->mc_count > multicast_filter_limit) || (netdev->flags & IFF_ALLMULTI)) { dev->rx_creg &= cpu_to_le16(0xfffe); dev->rx_creg |= cpu_to_le16(0x0002); diff --git a/trunk/fs/Makefile b/trunk/fs/Makefile index 20edcf28bfd2..fc92e59e9faf 100644 --- a/trunk/fs/Makefile +++ b/trunk/fs/Makefile @@ -10,7 +10,6 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \ ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ - ioprio.o obj-$(CONFIG_EPOLL) += eventpoll.o obj-$(CONFIG_COMPAT) += compat.o diff --git a/trunk/fs/ioprio.c b/trunk/fs/ioprio.c deleted file mode 100644 index 663e420636d6..000000000000 --- a/trunk/fs/ioprio.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * fs/ioprio.c - * - * Copyright (C) 2004 Jens Axboe - * - * Helper functions for setting/querying io priorities of processes. The - * system calls closely mimmick getpriority/setpriority, see the man page for - * those. The prio argument is a composite of prio class and prio data, where - * the data argument has meaning within that class. The standard scheduling - * classes have 8 distinct prio levels, with 0 being the highest prio and 7 - * being the lowest. - * - * IOW, setting BE scheduling class with prio 2 is done ala: - * - * unsigned int prio = (IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT) | 2; - * - * ioprio_set(PRIO_PROCESS, pid, prio); - * - * See also Documentation/block/ioprio.txt - * - */ -#include -#include -#include - -static int set_task_ioprio(struct task_struct *task, int ioprio) -{ - struct io_context *ioc; - - if (task->uid != current->euid && - task->uid != current->uid && !capable(CAP_SYS_NICE)) - return -EPERM; - - task_lock(task); - - task->ioprio = ioprio; - - ioc = task->io_context; - if (ioc && ioc->set_ioprio) - ioc->set_ioprio(ioc, ioprio); - - task_unlock(task); - return 0; -} - -asmlinkage int sys_ioprio_set(int which, int who, int ioprio) -{ - int class = IOPRIO_PRIO_CLASS(ioprio); - int data = IOPRIO_PRIO_DATA(ioprio); - struct task_struct *p, *g; - struct user_struct *user; - int ret; - - switch (class) { - case IOPRIO_CLASS_RT: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - /* fall through, rt has prio field too */ - case IOPRIO_CLASS_BE: - if (data >= IOPRIO_BE_NR || data < 0) - return -EINVAL; - - break; - case IOPRIO_CLASS_IDLE: - break; - default: - return -EINVAL; - } - - ret = -ESRCH; - read_lock_irq(&tasklist_lock); - switch (which) { - case IOPRIO_WHO_PROCESS: - if (!who) - p = current; - else - p = find_task_by_pid(who); - if (p) - ret = set_task_ioprio(p, ioprio); - break; - case IOPRIO_WHO_PGRP: - if (!who) - who = process_group(current); - do_each_task_pid(who, PIDTYPE_PGID, p) { - ret = set_task_ioprio(p, ioprio); - if (ret) - break; - } while_each_task_pid(who, PIDTYPE_PGID, p); - break; - case IOPRIO_WHO_USER: - if (!who) - user = current->user; - else - user = find_user(who); - - if (!user) - break; - - do_each_thread(g, p) { - if (p->uid != who) - continue; - ret = set_task_ioprio(p, ioprio); - if (ret) - break; - } while_each_thread(g, p); - - if (who) - free_uid(user); - break; - default: - ret = -EINVAL; - } - - read_unlock_irq(&tasklist_lock); - return ret; -} - -asmlinkage int sys_ioprio_get(int which, int who) -{ - struct task_struct *g, *p; - struct user_struct *user; - int ret = -ESRCH; - - read_lock_irq(&tasklist_lock); - switch (which) { - case IOPRIO_WHO_PROCESS: - if (!who) - p = current; - else - p = find_task_by_pid(who); - if (p) - ret = p->ioprio; - break; - case IOPRIO_WHO_PGRP: - if (!who) - who = process_group(current); - do_each_task_pid(who, PIDTYPE_PGID, p) { - if (ret == -ESRCH) - ret = p->ioprio; - else - ret = ioprio_best(ret, p->ioprio); - } while_each_task_pid(who, PIDTYPE_PGID, p); - break; - case IOPRIO_WHO_USER: - if (!who) - user = current->user; - else - user = find_user(who); - - if (!user) - break; - - do_each_thread(g, p) { - if (p->uid != user->uid) - continue; - if (ret == -ESRCH) - ret = p->ioprio; - else - ret = ioprio_best(ret, p->ioprio); - } while_each_thread(g, p); - - if (who) - free_uid(user); - break; - default: - ret = -EINVAL; - } - - read_unlock_irq(&tasklist_lock); - return ret; -} - diff --git a/trunk/fs/reiserfs/journal.c b/trunk/fs/reiserfs/journal.c index d1bcf0da6728..7b87707acc36 100644 --- a/trunk/fs/reiserfs/journal.c +++ b/trunk/fs/reiserfs/journal.c @@ -645,22 +645,18 @@ struct buffer_chunk { static void write_chunk(struct buffer_chunk *chunk) { int i; - get_fs_excl(); for (i = 0; i < chunk->nr ; i++) { submit_logged_buffer(chunk->bh[i]) ; } chunk->nr = 0; - put_fs_excl(); } static void write_ordered_chunk(struct buffer_chunk *chunk) { int i; - get_fs_excl(); for (i = 0; i < chunk->nr ; i++) { submit_ordered_buffer(chunk->bh[i]) ; } chunk->nr = 0; - put_fs_excl(); } static int add_to_chunk(struct buffer_chunk *chunk, struct buffer_head *bh, @@ -922,8 +918,6 @@ static int flush_commit_list(struct super_block *s, struct reiserfs_journal_list return 0 ; } - get_fs_excl(); - /* before we can put our commit blocks on disk, we have to make sure everyone older than ** us is on disk too */ @@ -1061,7 +1055,6 @@ static int flush_commit_list(struct super_block *s, struct reiserfs_journal_list if (retval) reiserfs_abort (s, retval, "Journal write error in %s", __FUNCTION__); - put_fs_excl(); return retval; } @@ -1258,8 +1251,6 @@ static int flush_journal_list(struct super_block *s, return 0 ; } - get_fs_excl(); - /* if all the work is already done, get out of here */ if (atomic_read(&(jl->j_nonzerolen)) <= 0 && atomic_read(&(jl->j_commit_left)) <= 0) { @@ -1459,7 +1450,6 @@ static int flush_journal_list(struct super_block *s, put_journal_list(s, jl); if (flushall) up(&journal->j_flush_sem); - put_fs_excl(); return err ; } @@ -2729,7 +2719,6 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, struct sup th->t_trans_id = journal->j_trans_id ; unlock_journal(p_s_sb) ; INIT_LIST_HEAD (&th->t_list); - get_fs_excl(); return 0 ; out_fail: @@ -3537,7 +3526,6 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, struct super_b BUG_ON (th->t_refcount > 1); BUG_ON (!th->t_trans_id); - put_fs_excl(); current->journal_info = th->t_handle_save; reiserfs_check_lock_depth(p_s_sb, "journal end"); if (journal->j_len == 0) { diff --git a/trunk/include/asm-i386/unistd.h b/trunk/include/asm-i386/unistd.h index e25e4c71a879..176413fb9ae3 100644 --- a/trunk/include/asm-i386/unistd.h +++ b/trunk/include/asm-i386/unistd.h @@ -294,10 +294,8 @@ #define __NR_add_key 286 #define __NR_request_key 287 #define __NR_keyctl 288 -#define __NR_ioprio_set 289 -#define __NR_ioprio_get 290 -#define NR_syscalls 291 +#define NR_syscalls 289 /* * user-visible error numbers are in the range -1 - -128: see diff --git a/trunk/include/asm-ia64/unistd.h b/trunk/include/asm-ia64/unistd.h index 517f1649ee64..f7f43ec2483a 100644 --- a/trunk/include/asm-ia64/unistd.h +++ b/trunk/include/asm-ia64/unistd.h @@ -263,8 +263,6 @@ #define __NR_add_key 1271 #define __NR_request_key 1272 #define __NR_keyctl 1273 -#define __NR_ioprio_set 1274 -#define __NR_ioprio_get 1275 #define __NR_set_zone_reclaim 1276 #ifdef __KERNEL__ diff --git a/trunk/include/asm-ppc/unistd.h b/trunk/include/asm-ppc/unistd.h index e8b79220b29c..cc51e5c9acc2 100644 --- a/trunk/include/asm-ppc/unistd.h +++ b/trunk/include/asm-ppc/unistd.h @@ -277,10 +277,8 @@ #define __NR_request_key 270 #define __NR_keyctl 271 #define __NR_waitid 272 -#define __NR_ioprio_set 273 -#define __NR_ioprio_get 274 -#define __NR_syscalls 275 +#define __NR_syscalls 273 #define __NR(n) #n diff --git a/trunk/include/asm-x86_64/unistd.h b/trunk/include/asm-x86_64/unistd.h index 6560439a83e4..d767adcbf0ff 100644 --- a/trunk/include/asm-x86_64/unistd.h +++ b/trunk/include/asm-x86_64/unistd.h @@ -561,12 +561,8 @@ __SYSCALL(__NR_add_key, sys_add_key) __SYSCALL(__NR_request_key, sys_request_key) #define __NR_keyctl 250 __SYSCALL(__NR_keyctl, sys_keyctl) -#define __NR_ioprio_set 251 -__SYSCALL(__NR_ioprio_set, sys_ioprio_set) -#define __NR_ioprio_get 252 -__SYSCALL(__NR_ioprio_get, sys_ioprio_get) -#define __NR_syscall_max __NR_ioprio_get +#define __NR_syscall_max __NR_keyctl #ifndef __NO_STUBS /* user-visible error numbers are in the range -1 - -4095 */ diff --git a/trunk/include/linux/bio.h b/trunk/include/linux/bio.h index 36ef29fa0d8b..038022763f09 100644 --- a/trunk/include/linux/bio.h +++ b/trunk/include/linux/bio.h @@ -22,7 +22,6 @@ #include #include -#include /* Platforms may set this to teach the BIO layer about IOMMU hardware. */ #include @@ -150,19 +149,6 @@ struct bio { #define BIO_RW_FAILFAST 3 #define BIO_RW_SYNC 4 -/* - * upper 16 bits of bi_rw define the io priority of this bio - */ -#define BIO_PRIO_SHIFT (8 * sizeof(unsigned long) - IOPRIO_BITS) -#define bio_prio(bio) ((bio)->bi_rw >> BIO_PRIO_SHIFT) -#define bio_prio_valid(bio) ioprio_valid(bio_prio(bio)) - -#define bio_set_prio(bio, prio) do { \ - WARN_ON(prio >= (1 << IOPRIO_BITS)); \ - (bio)->bi_rw &= ((1UL << BIO_PRIO_SHIFT) - 1); \ - (bio)->bi_rw |= ((unsigned long) (prio) << BIO_PRIO_SHIFT); \ -} while (0) - /* * various member access, note that bio_data should of course not be used * on highmem page vectors diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index 21a8674cd149..b54a0348a890 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -54,23 +54,16 @@ struct as_io_context { struct cfq_queue; struct cfq_io_context { + void (*dtor)(struct cfq_io_context *); + void (*exit)(struct cfq_io_context *); + + struct io_context *ioc; + /* * circular list of cfq_io_contexts belonging to a process io context */ struct list_head list; struct cfq_queue *cfqq; - void *key; - - struct io_context *ioc; - - unsigned long last_end_request; - unsigned long last_queue; - unsigned long ttime_total; - unsigned long ttime_samples; - unsigned long ttime_mean; - - void (*dtor)(struct cfq_io_context *); - void (*exit)(struct cfq_io_context *); }; /* @@ -80,9 +73,7 @@ struct cfq_io_context { */ struct io_context { atomic_t refcount; - struct task_struct *task; - - int (*set_ioprio)(struct io_context *, unsigned int); + pid_t pid; /* * For request batching @@ -90,6 +81,8 @@ struct io_context { unsigned long last_waited; /* Time last woken after wait for request */ int nr_batch_requests; /* Number of requests left in the batch */ + spinlock_t lock; + struct as_io_context *aic; struct cfq_io_context *cic; }; @@ -141,8 +134,6 @@ struct request { void *elevator_private; - unsigned short ioprio; - int rq_status; /* should split this into a few status bits */ struct gendisk *rq_disk; int errors; diff --git a/trunk/include/linux/elevator.h b/trunk/include/linux/elevator.h index ea6bbc2d7407..ee54f81faad5 100644 --- a/trunk/include/linux/elevator.h +++ b/trunk/include/linux/elevator.h @@ -16,9 +16,9 @@ typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *); typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *); typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *); typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *); -typedef int (elevator_may_queue_fn) (request_queue_t *, int, struct bio *); +typedef int (elevator_may_queue_fn) (request_queue_t *, int); -typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, int); +typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, int); typedef void (elevator_put_req_fn) (request_queue_t *, struct request *); typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *); @@ -96,9 +96,9 @@ extern struct request *elv_former_request(request_queue_t *, struct request *); extern struct request *elv_latter_request(request_queue_t *, struct request *); extern int elv_register_queue(request_queue_t *q); extern void elv_unregister_queue(request_queue_t *q); -extern int elv_may_queue(request_queue_t *, int, struct bio *); +extern int elv_may_queue(request_queue_t *, int); extern void elv_completed_request(request_queue_t *, struct request *); -extern int elv_set_request(request_queue_t *, struct request *, struct bio *, int); +extern int elv_set_request(request_queue_t *, struct request *, int); extern void elv_put_request(request_queue_t *, struct request *); /* diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 047bde30836a..3ae8e37bdfc8 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -213,7 +213,6 @@ extern int dir_notify_enable; #include #include #include -#include #include #include @@ -823,34 +822,16 @@ enum { #define vfs_check_frozen(sb, level) \ wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) -static inline void get_fs_excl(void) -{ - atomic_inc(¤t->fs_excl); -} - -static inline void put_fs_excl(void) -{ - atomic_dec(¤t->fs_excl); -} - -static inline int has_fs_excl(void) -{ - return atomic_read(¤t->fs_excl); -} - - /* * Superblock locking. */ static inline void lock_super(struct super_block * sb) { - get_fs_excl(); down(&sb->s_lock); } static inline void unlock_super(struct super_block * sb) { - put_fs_excl(); up(&sb->s_lock); } diff --git a/trunk/include/linux/init_task.h b/trunk/include/linux/init_task.h index c727c195a91a..03206a425d7a 100644 --- a/trunk/include/linux/init_task.h +++ b/trunk/include/linux/init_task.h @@ -81,7 +81,6 @@ extern struct group_info init_groups; .mm = NULL, \ .active_mm = &init_mm, \ .run_list = LIST_HEAD_INIT(tsk.run_list), \ - .ioprio = 0, \ .time_slice = HZ, \ .tasks = LIST_HEAD_INIT(tsk.tasks), \ .ptrace_children= LIST_HEAD_INIT(tsk.ptrace_children), \ @@ -111,7 +110,6 @@ extern struct group_info init_groups; .proc_lock = SPIN_LOCK_UNLOCKED, \ .journal_info = NULL, \ .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ - .fs_excl = ATOMIC_INIT(0), \ } diff --git a/trunk/include/linux/input.h b/trunk/include/linux/input.h index b9cc0ac71f44..9d9598ed760d 100644 --- a/trunk/include/linux/input.h +++ b/trunk/include/linux/input.h @@ -859,10 +859,6 @@ struct input_dev { int (*erase_effect)(struct input_dev *dev, int effect_id); struct input_handle *grab; - - struct semaphore sem; /* serializes open and close operations */ - unsigned int users; - struct device *dev; struct list_head h_list; diff --git a/trunk/include/linux/ioprio.h b/trunk/include/linux/ioprio.h deleted file mode 100644 index 8a453a0b5e4b..000000000000 --- a/trunk/include/linux/ioprio.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef IOPRIO_H -#define IOPRIO_H - -#include - -/* - * Gives us 8 prio classes with 13-bits of data for each class - */ -#define IOPRIO_BITS (16) -#define IOPRIO_CLASS_SHIFT (13) -#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) - -#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) -#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) -#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) - -#define ioprio_valid(mask) (IOPRIO_PRIO_CLASS((mask)) != IOPRIO_CLASS_NONE) - -/* - * These are the io priority groups as implemented by CFQ. RT is the realtime - * class, it always gets premium service. BE is the best-effort scheduling - * class, the default for any process. IDLE is the idle scheduling class, it - * is only served when no one else is using the disk. - */ -enum { - IOPRIO_CLASS_NONE, - IOPRIO_CLASS_RT, - IOPRIO_CLASS_BE, - IOPRIO_CLASS_IDLE, -}; - -/* - * 8 best effort priority levels are supported - */ -#define IOPRIO_BE_NR (8) - -asmlinkage int sys_ioprio_set(int, int, int); -asmlinkage int sys_ioprio_get(int, int); - -enum { - IOPRIO_WHO_PROCESS = 1, - IOPRIO_WHO_PGRP, - IOPRIO_WHO_USER, -}; - -/* - * if process has set io priority explicitly, use that. if not, convert - * the cpu scheduler nice value to an io priority - */ -#define IOPRIO_NORM (4) -static inline int task_ioprio(struct task_struct *task) -{ - WARN_ON(!ioprio_valid(task->ioprio)); - return IOPRIO_PRIO_DATA(task->ioprio); -} - -static inline int task_nice_ioprio(struct task_struct *task) -{ - return (task_nice(task) + 20) / 5; -} - -/* - * For inheritance, return the highest of the two given priorities - */ -static inline int ioprio_best(unsigned short aprio, unsigned short bprio) -{ - unsigned short aclass = IOPRIO_PRIO_CLASS(aprio); - unsigned short bclass = IOPRIO_PRIO_CLASS(bprio); - - if (!ioprio_valid(aprio)) - return bprio; - if (!ioprio_valid(bprio)) - return aprio; - - if (aclass == IOPRIO_CLASS_NONE) - aclass = IOPRIO_CLASS_BE; - if (bclass == IOPRIO_CLASS_NONE) - bclass = IOPRIO_CLASS_BE; - - if (aclass == bclass) - return min(aprio, bprio); - if (aclass > bclass) - return bprio; - else - return aprio; -} - -#endif diff --git a/trunk/include/linux/joystick.h b/trunk/include/linux/joystick.h index 06b9af77eb7f..b7e0ab622cd7 100644 --- a/trunk/include/linux/joystick.h +++ b/trunk/include/linux/joystick.h @@ -111,35 +111,18 @@ struct js_corr { #define JS_SET_ALL 8 struct JS_DATA_TYPE { - __s32 buttons; - __s32 x; - __s32 y; + int buttons; + int x; + int y; }; -struct JS_DATA_SAVE_TYPE_32 { - __s32 JS_TIMEOUT; - __s32 BUSY; - __s32 JS_EXPIRETIME; - __s32 JS_TIMELIMIT; +struct JS_DATA_SAVE_TYPE { + int JS_TIMEOUT; + int BUSY; + long JS_EXPIRETIME; + long JS_TIMELIMIT; struct JS_DATA_TYPE JS_SAVE; struct JS_DATA_TYPE JS_CORR; }; -struct JS_DATA_SAVE_TYPE_64 { - __s32 JS_TIMEOUT; - __s32 BUSY; - __s64 JS_EXPIRETIME; - __s64 JS_TIMELIMIT; - struct JS_DATA_TYPE JS_SAVE; - struct JS_DATA_TYPE JS_CORR; -}; - -#if BITS_PER_LONG == 64 -#define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64 -#elif BITS_PER_LONG == 32 -#define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_32 -#else -#error Unexpected BITS_PER_LONG -#endif - #endif /* _LINUX_JOYSTICK_H */ diff --git a/trunk/include/linux/libps2.h b/trunk/include/linux/libps2.h index a710bddda4eb..923bdbc6d9e4 100644 --- a/trunk/include/linux/libps2.h +++ b/trunk/include/linux/libps2.h @@ -41,7 +41,6 @@ struct ps2dev { void ps2_init(struct ps2dev *ps2dev, struct serio *serio); int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); -void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command); int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 3af7450278b7..bf608808a60c 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -1284,8 +1284,6 @@ #define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2 0x0348 #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000 0x034C #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100 0x034E -#define PCI_DEVICE_ID_NVIDIA_NVENET_14 0x0372 -#define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373 #define PCI_VENDOR_ID_IMS 0x10e0 #define PCI_DEVICE_ID_IMS_8849 0x8849 diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index ff48815bd3a2..9530b1903160 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -608,8 +608,6 @@ struct task_struct { struct list_head run_list; prio_array_t *array; - unsigned short ioprio; - unsigned long sleep_avg; unsigned long long timestamp, last_ran; unsigned long long sched_time; /* sched_clock time spent running */ @@ -765,7 +763,6 @@ struct task_struct { nodemask_t mems_allowed; int cpuset_mems_generation; #endif - atomic_t fs_excl; /* holding fs exclusive resources */ }; static inline pid_t process_group(struct task_struct *tsk) @@ -1115,8 +1112,7 @@ extern void unhash_process(struct task_struct *p); /* * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring - * subscriptions and synchronises with wait4(). Also used in procfs. Also - * pins the final release of task.io_context. + * subscriptions and synchronises with wait4(). Also used in procfs. * * Nests both inside and outside of read_lock(&tasklist_lock). * It must not be nested with write_lock_irq(&tasklist_lock), diff --git a/trunk/include/linux/serio.h b/trunk/include/linux/serio.h index aa4d6493a034..a2d3b9ae06f4 100644 --- a/trunk/include/linux/serio.h +++ b/trunk/include/linux/serio.h @@ -83,7 +83,6 @@ static inline void serio_register_port(struct serio *serio) } void serio_unregister_port(struct serio *serio); -void serio_unregister_child_port(struct serio *serio); void __serio_unregister_port_delayed(struct serio *serio, struct module *owner); static inline void serio_unregister_port_delayed(struct serio *serio) { @@ -154,11 +153,6 @@ static inline int serio_pin_driver(struct serio *serio) return down_interruptible(&serio->drv_sem); } -static inline void serio_pin_driver_uninterruptible(struct serio *serio) -{ - down(&serio->drv_sem); -} - static inline void serio_unpin_driver(struct serio *serio) { up(&serio->drv_sem); diff --git a/trunk/include/linux/writeback.h b/trunk/include/linux/writeback.h index d5c3fe1bf33d..1262cb43c3ab 100644 --- a/trunk/include/linux/writeback.h +++ b/trunk/include/linux/writeback.h @@ -14,13 +14,11 @@ extern struct list_head inode_unused; * Yes, writeback.h requires sched.h * No, sched.h is not included from here. */ -static inline int task_is_pdflush(struct task_struct *task) +static inline int current_is_pdflush(void) { - return task->flags & PF_FLUSHER; + return current->flags & PF_FLUSHER; } -#define current_is_pdflush() task_is_pdflush(current) - /* * fs/fs-writeback.c */ diff --git a/trunk/include/net/ieee80211.h b/trunk/include/net/ieee80211.h deleted file mode 100644 index 7fe57f957a51..000000000000 --- a/trunk/include/net/ieee80211.h +++ /dev/null @@ -1,882 +0,0 @@ -/* - * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11 - * remains copyright by the original authors - * - * Portions of the merged code are based on Host AP (software wireless - * LAN access point) driver for Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen - * - * Adaption to a generic IEEE 802.11 stack by James Ketrenos - * - * Copyright (c) 2004, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ -#ifndef IEEE80211_H -#define IEEE80211_H - -#include /* ETH_ALEN */ -#include /* ARRAY_SIZE */ - -#if WIRELESS_EXT < 17 -#define IW_QUAL_QUAL_INVALID 0x10 -#define IW_QUAL_LEVEL_INVALID 0x20 -#define IW_QUAL_NOISE_INVALID 0x40 -#define IW_QUAL_QUAL_UPDATED 0x1 -#define IW_QUAL_LEVEL_UPDATED 0x2 -#define IW_QUAL_NOISE_UPDATED 0x4 -#endif - -#define IEEE80211_DATA_LEN 2304 -/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section - 6.2.1.1.2. - - The figure in section 7.1.2 suggests a body size of up to 2312 - bytes is allowed, which is a bit confusing, I suspect this - represents the 2304 bytes of real data, plus a possible 8 bytes of - WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ - - -#define IEEE80211_HLEN 30 -#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) - -struct ieee80211_hdr { - u16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; -} __attribute__ ((packed)); - -struct ieee80211_hdr_3addr { - u16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; -} __attribute__ ((packed)); - -enum eap_type { - EAP_PACKET = 0, - EAPOL_START, - EAPOL_LOGOFF, - EAPOL_KEY, - EAPOL_ENCAP_ASF_ALERT -}; - -static const char *eap_types[] = { - [EAP_PACKET] = "EAP-Packet", - [EAPOL_START] = "EAPOL-Start", - [EAPOL_LOGOFF] = "EAPOL-Logoff", - [EAPOL_KEY] = "EAPOL-Key", - [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert" -}; - -static inline const char *eap_get_type(int type) -{ - return (type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type]; -} - -struct eapol { - u8 snap[6]; - u16 ethertype; - u8 version; - u8 type; - u16 length; -} __attribute__ ((packed)); - -#define IEEE80211_3ADDR_LEN 24 -#define IEEE80211_4ADDR_LEN 30 -#define IEEE80211_FCS_LEN 4 - -#define MIN_FRAG_THRESHOLD 256U -#define MAX_FRAG_THRESHOLD 2346U - -/* Frame control field constants */ -#define IEEE80211_FCTL_VERS 0x0002 -#define IEEE80211_FCTL_FTYPE 0x000c -#define IEEE80211_FCTL_STYPE 0x00f0 -#define IEEE80211_FCTL_TODS 0x0100 -#define IEEE80211_FCTL_FROMDS 0x0200 -#define IEEE80211_FCTL_MOREFRAGS 0x0400 -#define IEEE80211_FCTL_RETRY 0x0800 -#define IEEE80211_FCTL_PM 0x1000 -#define IEEE80211_FCTL_MOREDATA 0x2000 -#define IEEE80211_FCTL_WEP 0x4000 -#define IEEE80211_FCTL_ORDER 0x8000 - -#define IEEE80211_FTYPE_MGMT 0x0000 -#define IEEE80211_FTYPE_CTL 0x0004 -#define IEEE80211_FTYPE_DATA 0x0008 - -/* management */ -#define IEEE80211_STYPE_ASSOC_REQ 0x0000 -#define IEEE80211_STYPE_ASSOC_RESP 0x0010 -#define IEEE80211_STYPE_REASSOC_REQ 0x0020 -#define IEEE80211_STYPE_REASSOC_RESP 0x0030 -#define IEEE80211_STYPE_PROBE_REQ 0x0040 -#define IEEE80211_STYPE_PROBE_RESP 0x0050 -#define IEEE80211_STYPE_BEACON 0x0080 -#define IEEE80211_STYPE_ATIM 0x0090 -#define IEEE80211_STYPE_DISASSOC 0x00A0 -#define IEEE80211_STYPE_AUTH 0x00B0 -#define IEEE80211_STYPE_DEAUTH 0x00C0 - -/* control */ -#define IEEE80211_STYPE_PSPOLL 0x00A0 -#define IEEE80211_STYPE_RTS 0x00B0 -#define IEEE80211_STYPE_CTS 0x00C0 -#define IEEE80211_STYPE_ACK 0x00D0 -#define IEEE80211_STYPE_CFEND 0x00E0 -#define IEEE80211_STYPE_CFENDACK 0x00F0 - -/* data */ -#define IEEE80211_STYPE_DATA 0x0000 -#define IEEE80211_STYPE_DATA_CFACK 0x0010 -#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 -#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 -#define IEEE80211_STYPE_NULLFUNC 0x0040 -#define IEEE80211_STYPE_CFACK 0x0050 -#define IEEE80211_STYPE_CFPOLL 0x0060 -#define IEEE80211_STYPE_CFACKPOLL 0x0070 - -#define IEEE80211_SCTL_FRAG 0x000F -#define IEEE80211_SCTL_SEQ 0xFFF0 - - -/* debug macros */ - -#ifdef CONFIG_IEEE80211_DEBUG -extern u32 ieee80211_debug_level; -#define IEEE80211_DEBUG(level, fmt, args...) \ -do { if (ieee80211_debug_level & (level)) \ - printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) -#else -#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0) -#endif /* CONFIG_IEEE80211_DEBUG */ - -/* - * To use the debug system; - * - * If you are defining a new debug classification, simply add it to the #define - * list here in the form of: - * - * #define IEEE80211_DL_xxxx VALUE - * - * shifting value to the left one bit from the previous entry. xxxx should be - * the name of the classification (for example, WEP) - * - * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your - * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want - * to send output to that classification. - * - * To add your debug level to the list of levels seen when you perform - * - * % cat /proc/net/ipw/debug_level - * - * you simply need to add your entry to the ipw_debug_levels array. - * - * If you do not see debug_level in /proc/net/ipw then you do not have - * CONFIG_IEEE80211_DEBUG defined in your kernel configuration - * - */ - -#define IEEE80211_DL_INFO (1<<0) -#define IEEE80211_DL_WX (1<<1) -#define IEEE80211_DL_SCAN (1<<2) -#define IEEE80211_DL_STATE (1<<3) -#define IEEE80211_DL_MGMT (1<<4) -#define IEEE80211_DL_FRAG (1<<5) -#define IEEE80211_DL_EAP (1<<6) -#define IEEE80211_DL_DROP (1<<7) - -#define IEEE80211_DL_TX (1<<8) -#define IEEE80211_DL_RX (1<<9) - -#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) -#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) -#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a) - -#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a) -#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a) -#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a) -#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a) -#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a) -#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a) -#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) -#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) -#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) -#include -#include -#include /* ARPHRD_ETHER */ - -#ifndef WIRELESS_SPY -#define WIRELESS_SPY // enable iwspy support -#endif -#include // new driver API - -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - -#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW (ETH_P_ECONET + 1) -#endif - -/* IEEE 802.11 defines */ - -#define P80211_OUI_LEN 3 - -struct ieee80211_snap_hdr { - - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ - -} __attribute__ ((packed)); - -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - -#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) -#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) -#define WLAN_GET_SEQ_SEQ(seq) ((seq) & IEEE80211_SCTL_SEQ) - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 - -#define WLAN_AUTH_CHALLENGE_LEN 128 - -#define WLAN_CAPABILITY_BSS (1<<0) -#define WLAN_CAPABILITY_IBSS (1<<1) -#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) -#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) -#define WLAN_CAPABILITY_PRIVACY (1<<4) -#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) -#define WLAN_CAPABILITY_PBCC (1<<6) -#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) - -/* Status codes */ -#define WLAN_STATUS_SUCCESS 0 -#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 -#define WLAN_STATUS_CAPS_UNSUPPORTED 10 -#define WLAN_STATUS_REASSOC_NO_ASSOC 11 -#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 -#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 -#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 -#define WLAN_STATUS_CHALLENGE_FAIL 15 -#define WLAN_STATUS_AUTH_TIMEOUT 16 -#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 -#define WLAN_STATUS_ASSOC_DENIED_RATES 18 -/* 802.11b */ -#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 -#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 -#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 - -/* Reason codes */ -#define WLAN_REASON_UNSPECIFIED 1 -#define WLAN_REASON_PREV_AUTH_NOT_VALID 2 -#define WLAN_REASON_DEAUTH_LEAVING 3 -#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 -#define WLAN_REASON_DISASSOC_AP_BUSY 5 -#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 -#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 -#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 -#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 - - -/* Information Element IDs */ -#define WLAN_EID_SSID 0 -#define WLAN_EID_SUPP_RATES 1 -#define WLAN_EID_FH_PARAMS 2 -#define WLAN_EID_DS_PARAMS 3 -#define WLAN_EID_CF_PARAMS 4 -#define WLAN_EID_TIM 5 -#define WLAN_EID_IBSS_PARAMS 6 -#define WLAN_EID_CHALLENGE 16 -#define WLAN_EID_RSN 48 -#define WLAN_EID_GENERIC 221 - -#define IEEE80211_MGMT_HDR_LEN 24 -#define IEEE80211_DATA_HDR3_LEN 24 -#define IEEE80211_DATA_HDR4_LEN 30 - - -#define IEEE80211_STATMASK_SIGNAL (1<<0) -#define IEEE80211_STATMASK_RSSI (1<<1) -#define IEEE80211_STATMASK_NOISE (1<<2) -#define IEEE80211_STATMASK_RATE (1<<3) -#define IEEE80211_STATMASK_WEMASK 0x7 - - -#define IEEE80211_CCK_MODULATION (1<<0) -#define IEEE80211_OFDM_MODULATION (1<<1) - -#define IEEE80211_24GHZ_BAND (1<<0) -#define IEEE80211_52GHZ_BAND (1<<1) - -#define IEEE80211_CCK_RATE_1MB 0x02 -#define IEEE80211_CCK_RATE_2MB 0x04 -#define IEEE80211_CCK_RATE_5MB 0x0B -#define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_6MB 0x0C -#define IEEE80211_OFDM_RATE_9MB 0x12 -#define IEEE80211_OFDM_RATE_12MB 0x18 -#define IEEE80211_OFDM_RATE_18MB 0x24 -#define IEEE80211_OFDM_RATE_24MB 0x30 -#define IEEE80211_OFDM_RATE_36MB 0x48 -#define IEEE80211_OFDM_RATE_48MB 0x60 -#define IEEE80211_OFDM_RATE_54MB 0x6C -#define IEEE80211_BASIC_RATE_MASK 0x80 - -#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) -#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) -#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) -#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) -#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) -#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) -#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) -#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) -#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) -#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) -#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) -#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) - -#define IEEE80211_CCK_RATES_MASK 0x0000000F -#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ - IEEE80211_CCK_RATE_2MB_MASK) -#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ - IEEE80211_CCK_RATE_5MB_MASK | \ - IEEE80211_CCK_RATE_11MB_MASK) - -#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 -#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ - IEEE80211_OFDM_RATE_12MB_MASK | \ - IEEE80211_OFDM_RATE_24MB_MASK) -#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ - IEEE80211_OFDM_RATE_9MB_MASK | \ - IEEE80211_OFDM_RATE_18MB_MASK | \ - IEEE80211_OFDM_RATE_36MB_MASK | \ - IEEE80211_OFDM_RATE_48MB_MASK | \ - IEEE80211_OFDM_RATE_54MB_MASK) -#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ - IEEE80211_CCK_DEFAULT_RATES_MASK) - -#define IEEE80211_NUM_OFDM_RATES 8 -#define IEEE80211_NUM_CCK_RATES 4 -#define IEEE80211_OFDM_SHIFT_MASK_A 4 - - - - -/* NOTE: This data is for statistical purposes; not all hardware provides this - * information for frames received. Not setting these will not cause - * any adverse affects. */ -struct ieee80211_rx_stats { - u32 mac_time; - s8 rssi; - u8 signal; - u8 noise; - u16 rate; /* in 100 kbps */ - u8 received_channel; - u8 control; - u8 mask; - u8 freq; - u16 len; -}; - -/* IEEE 802.11 requires that STA supports concurrent reception of at least - * three fragmented frames. This define can be increased to support more - * concurrent frames, but it should be noted that each entry can consume about - * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ -#define IEEE80211_FRAG_CACHE_LEN 4 - -struct ieee80211_frag_entry { - unsigned long first_frag_time; - unsigned int seq; - unsigned int last_frag; - struct sk_buff *skb; - u8 src_addr[ETH_ALEN]; - u8 dst_addr[ETH_ALEN]; -}; - -struct ieee80211_stats { - unsigned int tx_unicast_frames; - unsigned int tx_multicast_frames; - unsigned int tx_fragments; - unsigned int tx_unicast_octets; - unsigned int tx_multicast_octets; - unsigned int tx_deferred_transmissions; - unsigned int tx_single_retry_frames; - unsigned int tx_multiple_retry_frames; - unsigned int tx_retry_limit_exceeded; - unsigned int tx_discards; - unsigned int rx_unicast_frames; - unsigned int rx_multicast_frames; - unsigned int rx_fragments; - unsigned int rx_unicast_octets; - unsigned int rx_multicast_octets; - unsigned int rx_fcs_errors; - unsigned int rx_discards_no_buffer; - unsigned int tx_discards_wrong_sa; - unsigned int rx_discards_undecryptable; - unsigned int rx_message_in_msg_fragments; - unsigned int rx_message_in_bad_msg_fragments; -}; - -struct ieee80211_device; - -#define SEC_KEY_1 (1<<0) -#define SEC_KEY_2 (1<<1) -#define SEC_KEY_3 (1<<2) -#define SEC_KEY_4 (1<<3) -#define SEC_ACTIVE_KEY (1<<4) -#define SEC_AUTH_MODE (1<<5) -#define SEC_UNICAST_GROUP (1<<6) -#define SEC_LEVEL (1<<7) -#define SEC_ENABLED (1<<8) - -#define SEC_LEVEL_0 0 /* None */ -#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ -#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ -#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ -#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ - -#define WEP_KEYS 4 -#define WEP_KEY_LEN 13 - -struct ieee80211_security { - u16 active_key:2, - enabled:1, - auth_mode:2, - auth_algo:4, - unicast_uses_group:1; - u8 key_sizes[WEP_KEYS]; - u8 keys[WEP_KEYS][WEP_KEY_LEN]; - u8 level; - u16 flags; -} __attribute__ ((packed)); - - -/* - - 802.11 data frame from AP - - ,-------------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `-------------------------------------------------------------------' - -Total: 28-2340 bytes - -*/ - -struct ieee80211_header_data { - u16 frame_ctl; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; -}; - -#define BEACON_PROBE_SSID_ID_POSITION 12 - -/* Management Frame Information Element Types */ -#define MFIE_TYPE_SSID 0 -#define MFIE_TYPE_RATES 1 -#define MFIE_TYPE_FH_SET 2 -#define MFIE_TYPE_DS_SET 3 -#define MFIE_TYPE_CF_SET 4 -#define MFIE_TYPE_TIM 5 -#define MFIE_TYPE_IBSS_SET 6 -#define MFIE_TYPE_CHALLENGE 16 -#define MFIE_TYPE_RSN 48 -#define MFIE_TYPE_RATES_EX 50 -#define MFIE_TYPE_GENERIC 221 - -struct ieee80211_info_element_hdr { - u8 id; - u8 len; -} __attribute__ ((packed)); - -struct ieee80211_info_element { - u8 id; - u8 len; - u8 data[0]; -} __attribute__ ((packed)); - -/* - * These are the data types that can make up management packets - * - u16 auth_algorithm; - u16 auth_sequence; - u16 beacon_interval; - u16 capability; - u8 current_ap[ETH_ALEN]; - u16 listen_interval; - struct { - u16 association_id:14, reserved:2; - } __attribute__ ((packed)); - u32 time_stamp[2]; - u16 reason; - u16 status; -*/ - -struct ieee80211_authentication { - struct ieee80211_header_data header; - u16 algorithm; - u16 transaction; - u16 status; - struct ieee80211_info_element info_element; -} __attribute__ ((packed)); - - -struct ieee80211_probe_response { - struct ieee80211_header_data header; - u32 time_stamp[2]; - u16 beacon_interval; - u16 capability; - struct ieee80211_info_element info_element; -} __attribute__ ((packed)); - -struct ieee80211_assoc_request_frame { - u16 capability; - u16 listen_interval; - u8 current_ap[ETH_ALEN]; - struct ieee80211_info_element info_element; -} __attribute__ ((packed)); - -struct ieee80211_assoc_response_frame { - struct ieee80211_hdr_3addr header; - u16 capability; - u16 status; - u16 aid; - struct ieee80211_info_element info_element; /* supported rates */ -} __attribute__ ((packed)); - - -struct ieee80211_txb { - u8 nr_frags; - u8 encrypted; - u16 reserved; - u16 frag_size; - u16 payload_size; - struct sk_buff *fragments[0]; -}; - - -/* SWEEP TABLE ENTRIES NUMBER*/ -#define MAX_SWEEP_TAB_ENTRIES 42 -#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 -/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs - * only use 8, and then use extended rates for the remaining supported - * rates. Other APs, however, stick all of their supported rates on the - * main rates information element... */ -#define MAX_RATES_LENGTH ((u8)12) -#define MAX_RATES_EX_LENGTH ((u8)16) -#define MAX_NETWORK_COUNT 128 - -#define CRC_LENGTH 4U - -#define MAX_WPA_IE_LEN 64 - -#define NETWORK_EMPTY_ESSID (1<<0) -#define NETWORK_HAS_OFDM (1<<1) -#define NETWORK_HAS_CCK (1<<2) - -struct ieee80211_network { - /* These entries are used to identify a unique network */ - u8 bssid[ETH_ALEN]; - u8 channel; - /* Ensure null-terminated for any debug msgs */ - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - - /* These are network statistics */ - struct ieee80211_rx_stats stats; - u16 capability; - u8 rates[MAX_RATES_LENGTH]; - u8 rates_len; - u8 rates_ex[MAX_RATES_EX_LENGTH]; - u8 rates_ex_len; - unsigned long last_scanned; - u8 mode; - u8 flags; - u32 last_associate; - u32 time_stamp[2]; - u16 beacon_interval; - u16 listen_interval; - u16 atim_window; - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - struct list_head list; -}; - -enum ieee80211_state { - IEEE80211_UNINITIALIZED = 0, - IEEE80211_INITIALIZED, - IEEE80211_ASSOCIATING, - IEEE80211_ASSOCIATED, - IEEE80211_AUTHENTICATING, - IEEE80211_AUTHENTICATED, - IEEE80211_SHUTDOWN -}; - -#define DEFAULT_MAX_SCAN_AGE (15 * HZ) -#define DEFAULT_FTS 2346 -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] - - -extern inline int is_broadcast_ether_addr(const u8 *addr) -{ - return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ - (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); -} - -#define CFG_IEEE80211_RESERVE_FCS (1<<0) -#define CFG_IEEE80211_COMPUTE_FCS (1<<1) - -struct ieee80211_device { - struct net_device *dev; - - /* Bookkeeping structures */ - struct net_device_stats stats; - struct ieee80211_stats ieee_stats; - - /* Probe / Beacon management */ - struct list_head network_free_list; - struct list_head network_list; - struct ieee80211_network *networks; - int scans; - int scan_age; - - int iw_mode; /* operating mode (IW_MODE_*) */ - - spinlock_t lock; - - int tx_headroom; /* Set to size of any additional room needed at front - * of allocated Tx SKBs */ - u32 config; - - /* WEP and other encryption related settings at the device level */ - int open_wep; /* Set to 1 to allow unencrypted frames */ - - int reset_on_keychange; /* Set to 1 if the HW needs to be reset on - * WEP key changes */ - - /* If the host performs {en,de}cryption, then set to 1 */ - int host_encrypt; - int host_decrypt; - int ieee802_1x; /* is IEEE 802.1X used */ - - /* WPA data */ - int wpa_enabled; - int drop_unencrypted; - int tkip_countermeasures; - int privacy_invoked; - size_t wpa_ie_len; - u8 *wpa_ie; - - struct list_head crypt_deinit_list; - struct ieee80211_crypt_data *crypt[WEP_KEYS]; - int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ - struct timer_list crypt_deinit_timer; - - int bcrx_sta_key; /* use individual keys to override default keys even - * with RX of broad/multicast frames */ - - /* Fragmentation structures */ - struct ieee80211_frag_entry frag_cache[IEEE80211_FRAG_CACHE_LEN]; - unsigned int frag_next_idx; - u16 fts; /* Fragmentation Threshold */ - - /* Association info */ - u8 bssid[ETH_ALEN]; - - enum ieee80211_state state; - - int mode; /* A, B, G */ - int modulation; /* CCK, OFDM */ - int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ - int abg_ture; /* ABG flag */ - - /* Callback functions */ - void (*set_security)(struct net_device *dev, - struct ieee80211_security *sec); - int (*hard_start_xmit)(struct ieee80211_txb *txb, - struct net_device *dev); - int (*reset_port)(struct net_device *dev); - - /* This must be the last item so that it points to the data - * allocated beyond this structure by alloc_ieee80211 */ - u8 priv[0]; -}; - -#define IEEE_A (1<<0) -#define IEEE_B (1<<1) -#define IEEE_G (1<<2) -#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) - -extern inline void *ieee80211_priv(struct net_device *dev) -{ - return ((struct ieee80211_device *)netdev_priv(dev))->priv; -} - -extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) -{ - /* Single white space is for Linksys APs */ - if (essid_len == 1 && essid[0] == ' ') - return 1; - - /* Otherwise, if the entire essid is 0, we assume it is hidden */ - while (essid_len) { - essid_len--; - if (essid[essid_len] != '\0') - return 0; - } - - return 1; -} - -extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) -{ - /* - * It is possible for both access points and our device to support - * combinations of modes, so as long as there is one valid combination - * of ap/device supported modes, then return success - * - */ - if ((mode & IEEE_A) && - (ieee->modulation & IEEE80211_OFDM_MODULATION) && - (ieee->freq_band & IEEE80211_52GHZ_BAND)) - return 1; - - if ((mode & IEEE_G) && - (ieee->modulation & IEEE80211_OFDM_MODULATION) && - (ieee->freq_band & IEEE80211_24GHZ_BAND)) - return 1; - - if ((mode & IEEE_B) && - (ieee->modulation & IEEE80211_CCK_MODULATION) && - (ieee->freq_band & IEEE80211_24GHZ_BAND)) - return 1; - - return 0; -} - -extern inline int ieee80211_get_hdrlen(u16 fc) -{ - int hdrlen = 24; - - switch (WLAN_FC_GET_TYPE(fc)) { - case IEEE80211_FTYPE_DATA: - if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) - hdrlen = 30; /* Addr4 */ - break; - case IEEE80211_FTYPE_CTL: - switch (WLAN_FC_GET_STYPE(fc)) { - case IEEE80211_STYPE_CTS: - case IEEE80211_STYPE_ACK: - hdrlen = 10; - break; - default: - hdrlen = 16; - break; - } - break; - } - - return hdrlen; -} - - - -/* ieee80211.c */ -extern void free_ieee80211(struct net_device *dev); -extern struct net_device *alloc_ieee80211(int sizeof_priv); - -extern int ieee80211_set_encryption(struct ieee80211_device *ieee); - -/* ieee80211_tx.c */ - - -extern int ieee80211_xmit(struct sk_buff *skb, - struct net_device *dev); -extern void ieee80211_txb_free(struct ieee80211_txb *); - - -/* ieee80211_rx.c */ -extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats); -extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, - struct ieee80211_hdr *header, - struct ieee80211_rx_stats *stats); - -/* iee80211_wx.c */ -extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); - - -extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) -{ - ieee->scans++; -} - -extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) -{ - return ieee->scans; -} - -static inline const char *escape_essid(const char *essid, u8 essid_len) { - static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - const char *s = essid; - char *d = escaped; - - if (ieee80211_is_empty_essid(essid, essid_len)) { - memcpy(escaped, "", sizeof("")); - return escaped; - } - - essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); - while (essid_len--) { - if (*s == '\0') { - *d++ = '\\'; - *d++ = '0'; - s++; - } else { - *d++ = *s++; - } - } - *d = '\0'; - return escaped; -} - -#endif /* IEEE80211_H */ diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index 9d1b10ed0135..3ebcd60a19c6 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -784,8 +784,6 @@ fastcall NORET_TYPE void do_exit(long code) profile_task_exit(tsk); - WARN_ON(atomic_read(&tsk->fs_excl)); - if (unlikely(in_interrupt())) panic("Aiee, killing interrupt handler!"); if (unlikely(!tsk->pid)) diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index cdef6cea8900..2c7806873bfd 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -1090,11 +1090,6 @@ static task_t *copy_process(unsigned long clone_flags, spin_unlock(¤t->sighand->siglock); } - /* - * inherit ioprio - */ - p->ioprio = current->ioprio; - SET_LINKS(p); if (unlikely(p->ptrace & PT_PTRACED)) __ptrace_link(p, current->parent); diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index e2b0d3e4dd06..a07cff90d849 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -3448,7 +3448,15 @@ int task_nice(const task_t *p) { return TASK_NICE(p); } + +/* + * The only users of task_nice are binfmt_elf and binfmt_elf32. + * binfmt_elf is no longer modular, but binfmt_elf32 still is. + * Therefore, task_nice is needed if there is a compat_mode. + */ +#ifdef CONFIG_COMPAT EXPORT_SYMBOL_GPL(task_nice); +#endif /** * idle_cpu - is a given cpu idle currently? diff --git a/trunk/sound/oss/Kconfig b/trunk/sound/oss/Kconfig index 7bd95ceab7cc..3b1fafc8f4f5 100644 --- a/trunk/sound/oss/Kconfig +++ b/trunk/sound/oss/Kconfig @@ -52,7 +52,7 @@ config SOUND_CMPCI_MIDI config SOUND_CMPCI_JOYSTICK bool "Enable joystick" - depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT) + depends on SOUND_CMPCI && X86 help Say Y here in order to enable the joystick port on a sound card using the CMI8338 or the CMI8738 chipset. You need to config the diff --git a/trunk/sound/oss/es1370.c b/trunk/sound/oss/es1370.c index 8538085086e7..886f61c1c34a 100644 --- a/trunk/sound/oss/es1370.c +++ b/trunk/sound/oss/es1370.c @@ -162,10 +162,6 @@ #include #include -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK -#endif - /* --------------------------------------------------------------------- */ #undef OSS_DOCUMENTED_MIXER_SEMANTICS @@ -389,10 +385,7 @@ struct es1370_state { unsigned char obuf[MIDIOUTBUF]; } midi; -#ifdef SUPPORT_JOYSTICK struct gameport *gameport; -#endif - struct semaphore sem; }; @@ -2561,55 +2554,10 @@ static struct initvol { { SOUND_MIXER_WRITE_OGAIN, 0x4040 } }; -#ifdef SUPPORT_JOYSTICK - -static int __devinit es1370_register_gameport(struct es1370_state *s) -{ - struct gameport *gp; - - if (!request_region(0x200, JOY_EXTENT, "es1370")) { - printk(KERN_ERR "es1370: joystick io port 0x200 in use\n"); - return -EBUSY; - } - - s->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "es1370: can not allocate memory for gameport\n"); - release_region(0x200, JOY_EXTENT); - return -ENOMEM; - } - - gameport_set_name(gp, "ESS1370"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); - gp->dev.parent = &s->dev->dev; - gp->io = 0x200; - - s->ctrl |= CTRL_JYSTK_EN; - outl(s->ctrl, s->io + ES1370_REG_CONTROL); - - gameport_register_port(gp); - - return 0; -} - -static inline void es1370_unregister_gameport(struct es1370_state *s) -{ - if (s->gameport) { - int gpio = s->gameport->io; - gameport_unregister_port(s->gameport); - release_region(gpio, JOY_EXTENT); - - } -} - -#else -static inline int es1370_register_gameport(struct es1370_state *s) { return -ENOSYS; } -static inline void es1370_unregister_gameport(struct es1370_state *s) { } -#endif /* SUPPORT_JOYSTICK */ - static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { struct es1370_state *s; + struct gameport *gp = NULL; mm_segment_t fs; int i, val, ret; @@ -2658,14 +2606,28 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic /* note: setting CTRL_SERR_DIS is reported to break * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */ s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL); + if (!request_region(0x200, JOY_EXTENT, "es1370")) { + printk(KERN_ERR "es1370: joystick io port 0x200 in use\n"); + } else if (!(s->gameport = gp = gameport_allocate_port())) { + printk(KERN_ERR "es1370: can not allocate memory for gameport\n"); + release_region(0x200, JOY_EXTENT); + } else { + gameport_set_name(gp, "ESS1370"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); + gp->dev.parent = &s->dev->dev; + gp->io = 0x200; + s->ctrl |= CTRL_JYSTK_EN; + } if (lineout[devindex]) s->ctrl |= CTRL_XCTL0; if (micbias[devindex]) s->ctrl |= CTRL_XCTL1; s->sctrl = 0; - printk(KERN_INFO "es1370: adapter at io %#lx irq %u, line %s, mic impedance %s\n", - s->io, s->irq, (s->ctrl & CTRL_XCTL0) ? "out" : "in", - (s->ctrl & CTRL_XCTL1) ? "1" : "0"); + printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n" + KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n", + s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off", + (s->ctrl & CTRL_XCTL0) ? "out" : "in", + (s->ctrl & CTRL_XCTL1) ? "1" : "0"); /* register devices */ if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) { ret = s->dev_audio; @@ -2711,7 +2673,9 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic } set_fs(fs); - es1370_register_gameport(s); + /* register gameport */ + if (gp) + gameport_register_port(gp); /* store it in the driver field */ pci_set_drvdata(pcidev, s); @@ -2733,6 +2697,10 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic err_dev1: printk(KERN_ERR "es1370: cannot register misc device\n"); free_irq(s->irq, s); + if (s->gameport) { + release_region(s->gameport->io, JOY_EXTENT); + gameport_free_port(s->gameport); + } err_irq: release_region(s->io, ES1370_EXTENT); err_region: @@ -2751,7 +2719,11 @@ static void __devexit es1370_remove(struct pci_dev *dev) outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */ synchronize_irq(s->irq); free_irq(s->irq, s); - es1370_unregister_gameport(s); + if (s->gameport) { + int gpio = s->gameport->io; + gameport_unregister_port(s->gameport); + release_region(gpio, JOY_EXTENT); + } release_region(s->io, ES1370_EXTENT); unregister_sound_dsp(s->dev_audio); unregister_sound_mixer(s->dev_mixer); diff --git a/trunk/sound/oss/es1371.c b/trunk/sound/oss/es1371.c index 12a56d5ab498..9266b777387b 100644 --- a/trunk/sound/oss/es1371.c +++ b/trunk/sound/oss/es1371.c @@ -134,10 +134,6 @@ #include #include -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK -#endif - /* --------------------------------------------------------------------- */ #undef OSS_DOCUMENTED_MIXER_SEMANTICS @@ -458,10 +454,7 @@ struct es1371_state { unsigned char obuf[MIDIOUTBUF]; } midi; -#ifdef SUPPORT_JOYSTICK struct gameport *gameport; -#endif - struct semaphore sem; }; @@ -2794,63 +2787,12 @@ static struct { PCI_ANY_ID, PCI_ANY_ID } }; -#ifdef SUPPORT_JOYSTICK - -static int __devinit es1371_register_gameport(struct es1371_state *s) -{ - struct gameport *gp; - int gpio; - - for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) - if (request_region(gpio, JOY_EXTENT, "es1371")) - break; - - if (gpio < 0x200) { - printk(KERN_ERR PFX "no free joystick address found\n"); - return -EBUSY; - } - - s->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR PFX "can not allocate memory for gameport\n"); - release_region(gpio, JOY_EXTENT); - return -ENOMEM; - } - - gameport_set_name(gp, "ESS1371 Gameport"); - gameport_set_phys(gp, "isa%04x/gameport0", gpio); - gp->dev.parent = &s->dev->dev; - gp->io = gpio; - - s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); - outl(s->ctrl, s->io + ES1371_REG_CONTROL); - - gameport_register_port(gp); - - return 0; -} - -static inline void es1371_unregister_gameport(struct es1371_state *s) -{ - if (s->gameport) { - int gpio = s->gameport->io; - gameport_unregister_port(s->gameport); - release_region(gpio, JOY_EXTENT); - - } -} - -#else -static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; } -static inline void es1371_unregister_gameport(struct es1371_state *s) { } -#endif /* SUPPORT_JOYSTICK */ - - static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { struct es1371_state *s; + struct gameport *gp; mm_segment_t fs; - int i, val, res = -1; + int i, gpio, val, res = -1; int idx; unsigned long tmo; signed long tmo2; @@ -2941,6 +2883,23 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic } } + for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) + if (request_region(gpio, JOY_EXTENT, "es1371")) + break; + + if (gpio < 0x200) { + printk(KERN_ERR PFX "no free joystick address found\n"); + } else if (!(s->gameport = gp = gameport_allocate_port())) { + printk(KERN_ERR PFX "can not allocate memory for gameport\n"); + release_region(gpio, JOY_EXTENT); + } else { + gameport_set_name(gp, "ESS1371 Gameport"); + gameport_set_phys(gp, "isa%04x/gameport0", gpio); + gp->dev.parent = &s->dev->dev; + gp->io = gpio; + s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); + } + s->sctrl = 0; cssr = 0; s->spdif_volume = -1; @@ -3010,7 +2969,9 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic /* turn on S/PDIF output driver if requested */ outl(cssr, s->io+ES1371_REG_STATUS); - es1371_register_gameport(s); + /* register gameport */ + if (s->gameport) + gameport_register_port(s->gameport); /* store it in the driver field */ pci_set_drvdata(pcidev, s); @@ -3019,9 +2980,13 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic /* increment devindex */ if (devindex < NR_DEVICE-1) devindex++; - return 0; + return 0; err_gp: + if (s->gameport) { + release_region(s->gameport->io, JOY_EXTENT); + gameport_free_port(s->gameport); + } #ifdef ES1371_DEBUG if (s->ps) remove_proc_entry("es1371", NULL); @@ -3060,7 +3025,11 @@ static void __devexit es1371_remove(struct pci_dev *dev) outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */ synchronize_irq(s->irq); free_irq(s->irq, s); - es1371_unregister_gameport(s); + if (s->gameport) { + int gpio = s->gameport->io; + gameport_unregister_port(s->gameport); + release_region(gpio, JOY_EXTENT); + } release_region(s->io, ES1371_EXTENT); unregister_sound_dsp(s->dev_audio); unregister_sound_mixer(s->codec->dev_mixer); diff --git a/trunk/sound/oss/esssolo1.c b/trunk/sound/oss/esssolo1.c index a4ecab2f0522..fb09065d07c8 100644 --- a/trunk/sound/oss/esssolo1.c +++ b/trunk/sound/oss/esssolo1.c @@ -150,10 +150,6 @@ #define FMODE_DMFM 0x10 -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - static struct pci_driver solo1_driver; /* --------------------------------------------------------------------- */ @@ -231,9 +227,7 @@ struct solo1_state { unsigned char obuf[MIDIOUTBUF]; } midi; -#if SUPPORT_JOYSTICK struct gameport *gameport; -#endif }; /* --------------------------------------------------------------------- */ @@ -2287,7 +2281,6 @@ solo1_resume(struct pci_dev *pci_dev) { return 0; } -#ifdef SUPPORT_JOYSTICK static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) { struct gameport *gp; @@ -2314,19 +2307,6 @@ static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) return 0; } -static inline void solo1_unregister_gameport(struct solo1_state *s) -{ - if (s->gameport) { - int gpio = s->gameport->io; - gameport_unregister_port(s->gameport); - release_region(gpio, GAMEPORT_EXTENT); - } -} -#else -static inline int solo1_register_gameport(struct solo1_state *s, int io_port) { return -ENOSYS; } -static inline void solo1_unregister_gameport(struct solo1_state *s) { } -#endif /* SUPPORT_JOYSTICK */ - static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { struct solo1_state *s; @@ -2458,7 +2438,11 @@ static void __devexit solo1_remove(struct pci_dev *dev) synchronize_irq(s->irq); pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */ free_irq(s->irq, s); - solo1_unregister_gameport(s); + if (s->gameport) { + int gpio = s->gameport->io; + gameport_unregister_port(s->gameport); + release_region(gpio, GAMEPORT_EXTENT); + } release_region(s->iobase, IOBASE_EXTENT); release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT); release_region(s->ddmabase, DDMABASE_EXTENT); diff --git a/trunk/sound/oss/mad16.c b/trunk/sound/oss/mad16.c index aa3c50db66c4..a7067f169919 100644 --- a/trunk/sound/oss/mad16.c +++ b/trunk/sound/oss/mad16.c @@ -50,12 +50,9 @@ #include "sb.h" #include "mpu401.h" -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - static int mad16_conf; static int mad16_cdsel; +static struct gameport *gameport; static DEFINE_SPINLOCK(lock); #define C928 1 @@ -905,10 +902,6 @@ static int __initdata irq_map[16] = -1, -1, -1, -1 }; -#ifdef SUPPORT_JOYSTICK - -static struct gameport *gameport; - static int __devinit mad16_register_gameport(int io_port) { if (!request_region(io_port, 1, "mad16 gameport")) { @@ -932,20 +925,6 @@ static int __devinit mad16_register_gameport(int io_port) return 0; } -static inline void mad16_unregister_gameport(void) -{ - if (gameport) { - /* the gameport was initialized so we must free it up */ - gameport_unregister_port(gameport); - gameport = NULL; - release_region(0x201, 1); - } -} -#else -static inline int mad16_register_gameport(int io_port) { return -ENOSYS; } -static inline void mad16_unregister_gameport(void) { } -#endif - static int __devinit init_mad16(void) { int dmatype = 0; @@ -1081,7 +1060,12 @@ static void __exit cleanup_mad16(void) { if (found_mpu) unload_mad16_mpu(&cfg_mpu); - mad16_unregister_gameport(); + if (gameport) { + /* the gameport was initialized so we must free it up */ + gameport_unregister_port(gameport); + gameport = NULL; + release_region(0x201, 1); + } unload_mad16(&cfg); release_region(MC0_PORT, 12); } diff --git a/trunk/sound/oss/sonicvibes.c b/trunk/sound/oss/sonicvibes.c index 17d0e461f8d8..06047e7979af 100644 --- a/trunk/sound/oss/sonicvibes.c +++ b/trunk/sound/oss/sonicvibes.c @@ -122,9 +122,6 @@ #include "dm.h" -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif /* --------------------------------------------------------------------- */ @@ -368,9 +365,7 @@ struct sv_state { unsigned char obuf[MIDIOUTBUF]; } midi; -#if SUPPORT_JOYSTICK struct gameport *gameport; -#endif }; /* --------------------------------------------------------------------- */ @@ -2490,7 +2485,6 @@ static struct initvol { #define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) -#ifdef SUPPORT_JOYSTICK static int __devinit sv_register_gameport(struct sv_state *s, int io_port) { struct gameport *gp; @@ -2517,19 +2511,6 @@ static int __devinit sv_register_gameport(struct sv_state *s, int io_port) return 0; } -static inline void sv_unregister_gameport(struct sv_state *s) -{ - if (s->gameport) { - int gpio = s->gameport->io; - gameport_unregister_port(s->gameport); - release_region(gpio, SV_EXTENT_GAME); - } -} -#else -static inline int sv_register_gameport(struct sv_state *s, int io_port) { return -ENOSYS; } -static inline void sv_unregister_gameport(struct sv_state *s) { } -#endif /* SUPPORT_JOYSTICK */ - static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller"; @@ -2730,7 +2711,11 @@ static void __devexit sv_remove(struct pci_dev *dev) /*outb(0, s->iodmaa + SV_DMA_RESET);*/ /*outb(0, s->iodmac + SV_DMA_RESET);*/ free_irq(s->irq, s); - sv_unregister_gameport(s); + if (s->gameport) { + int gpio = s->gameport->io; + gameport_unregister_port(s->gameport); + release_region(gpio, SV_EXTENT_GAME); + } release_region(s->iodmac, SV_EXTENT_DMA); release_region(s->iodmaa, SV_EXTENT_DMA); release_region(s->ioenh, SV_EXTENT_ENH); diff --git a/trunk/sound/oss/trident.c b/trunk/sound/oss/trident.c index 5f0ad6bb43b9..47537f0a5b05 100644 --- a/trunk/sound/oss/trident.c +++ b/trunk/sound/oss/trident.c @@ -228,10 +228,6 @@ #define DRIVER_VERSION "0.14.10j-2.6" -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - /* magic numbers to protect our data structures */ #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ @@ -4256,25 +4252,24 @@ trident_ac97_init(struct trident_card *card) return num_ac97 + 1; } -#ifdef SUPPORT_JOYSTICK /* Gameport functions for the cards ADC gameport */ -static unsigned char trident_game_read(struct gameport *gameport) +static unsigned char +trident_game_read(struct gameport *gameport) { struct trident_card *card = gameport->port_data; - return inb(TRID_REG(card, T4D_GAME_LEG)); } -static void trident_game_trigger(struct gameport *gameport) +static void +trident_game_trigger(struct gameport *gameport) { struct trident_card *card = gameport->port_data; - outb(0xff, TRID_REG(card, T4D_GAME_LEG)); } -static int trident_game_cooked_read(struct gameport *gameport, - int *axes, int *buttons) +static int +trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) { struct trident_card *card = gameport->port_data; int i; @@ -4290,7 +4285,8 @@ static int trident_game_cooked_read(struct gameport *gameport, return 0; } -static int trident_game_open(struct gameport *gameport, int mode) +static int +trident_game_open(struct gameport *gameport, int mode) { struct trident_card *card = gameport->port_data; @@ -4309,7 +4305,8 @@ static int trident_game_open(struct gameport *gameport, int mode) return 0; } -static int __devinit trident_register_gameport(struct trident_card *card) +static int __devinit +trident_register_gameport(struct trident_card *card) { struct gameport *gp; @@ -4333,17 +4330,6 @@ static int __devinit trident_register_gameport(struct trident_card *card) return 0; } -static inline void trident_unregister_gameport(struct trident_card *card) -{ - if (card->gameport) - gameport_unregister_port(card->gameport); -} - -#else -static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; } -static inline void trident_unregister_gameport(struct trident_card *card) { } -#endif /* SUPPORT_JOYSTICK */ - /* install the driver, we do not allocate hardware channel nor DMA buffer */ /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ /* open/read/write/ioctl/mmap) */ @@ -4583,7 +4569,8 @@ trident_remove(struct pci_dev *pci_dev) } /* Unregister gameport */ - trident_unregister_gameport(card); + if (card->gameport) + gameport_unregister_port(card->gameport); /* Kill interrupts, and SP/DIF */ trident_disable_loop_interrupts(card); diff --git a/trunk/sound/oss/via82cxxx_audio.c b/trunk/sound/oss/via82cxxx_audio.c index 83edda93f0b4..b387e1e52485 100644 --- a/trunk/sound/oss/via82cxxx_audio.c +++ b/trunk/sound/oss/via82cxxx_audio.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -3392,10 +3391,10 @@ static int __devinit via_init_one (struct pci_dev *pdev, const struct pci_device if (rc) goto err_out_disable; - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + rc = pci_set_dma_mask(pdev, 0xffffffffULL); if (rc) goto err_out_res; - rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL); if (rc) goto err_out_res; diff --git a/trunk/sound/pci/cs4281.c b/trunk/sound/pci/cs4281.c index eb3c52b03af3..b6e1854e9389 100644 --- a/trunk/sound/pci/cs4281.c +++ b/trunk/sound/pci/cs4281.c @@ -1338,6 +1338,11 @@ static inline int snd_cs4281_create_gameport(cs4281_t *chip) { return -ENOSYS; } static inline void snd_cs4281_free_gameport(cs4281_t *chip) { } #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ + +/* + + */ + static int snd_cs4281_free(cs4281_t *chip) { snd_cs4281_free_gameport(chip);