From a5a34200774fbbdadf44a7c74d6ecd7445f713a5 Mon Sep 17 00:00:00 2001 From: Trent Jaeger Date: Tue, 13 Dec 2005 23:12:27 -0800 Subject: [PATCH] --- yaml --- r: 15516 b: refs/heads/master c: df71837d5024e2524cd51c93621e558aa7dd9f3f h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/DocBook/usb.tmpl | 1 - trunk/Documentation/cpu-freq/governors.txt | 62 +- trunk/MAINTAINERS | 8 +- trunk/arch/arm/mach-pxa/mainstone.c | 21 - trunk/arch/arm/mach-pxa/pxa27x.c | 6 - .../i386/kernel/cpu/cpufreq/cpufreq-nforce2.c | 3 +- .../i386/kernel/cpu/cpufreq/powernow-k8.c | 50 +- .../i386/kernel/cpu/cpufreq/powernow-k8.h | 9 +- .../i386/kernel/cpu/cpufreq/speedstep-ich.c | 47 +- .../i386/kernel/cpu/cpufreq/speedstep-lib.c | 32 +- .../i386/kernel/cpu/cpufreq/speedstep-lib.h | 1 - .../i386/kernel/cpu/cpufreq/speedstep-smi.c | 1 - trunk/arch/i386/kernel/cpu/proc.c | 6 +- trunk/arch/ia64/kernel/setup.c | 8 +- trunk/arch/mips/kernel/linux32.c | 4 +- trunk/arch/x86_64/kernel/setup.c | 6 +- trunk/drivers/block/Kconfig | 3 +- trunk/drivers/block/ub.c | 439 ++-- trunk/drivers/bluetooth/bcm203x.c | 1 + trunk/drivers/bluetooth/bfusb.c | 1 + trunk/drivers/bluetooth/bpa10x.c | 1 + trunk/drivers/bluetooth/hci_usb.c | 1 + trunk/drivers/char/ip2/i2pack.h | 2 +- trunk/drivers/char/watchdog/pcwd_usb.c | 1 + trunk/drivers/cpufreq/cpufreq.c | 24 - trunk/drivers/cpufreq/cpufreq_conservative.c | 10 +- trunk/drivers/cpufreq/cpufreq_ondemand.c | 10 +- .../input/joystick/iforce/iforce-usb.c | 1 + trunk/drivers/isdn/hisax/hfc_usb.c | 1 + trunk/drivers/isdn/hisax/st5481_init.c | 1 + trunk/drivers/media/dvb/b2c2/flexcop-usb.c | 1 + trunk/drivers/media/dvb/cinergyT2/cinergyT2.c | 1 + trunk/drivers/media/dvb/dvb-usb/a800.c | 1 + trunk/drivers/media/dvb/dvb-usb/cxusb.c | 1 + trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c | 1 + trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c | 1 + trunk/drivers/media/dvb/dvb-usb/digitv.c | 1 + trunk/drivers/media/dvb/dvb-usb/dtt200u.c | 1 + trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c | 1 + trunk/drivers/media/dvb/dvb-usb/umt-010.c | 1 + trunk/drivers/media/dvb/dvb-usb/vp702x.c | 1 + trunk/drivers/media/dvb/dvb-usb/vp7045.c | 1 + trunk/drivers/media/video/cpia_usb.c | 1 + .../drivers/media/video/em28xx/em28xx-video.c | 1 + trunk/drivers/net/irda/irda-usb.c | 1 + trunk/drivers/net/irda/stir4200.c | 1 + trunk/drivers/usb/Makefile | 1 - trunk/drivers/usb/atm/Kconfig | 13 - trunk/drivers/usb/atm/Makefile | 1 - trunk/drivers/usb/atm/cxacru.c | 1 + trunk/drivers/usb/atm/speedtch.c | 1 + trunk/drivers/usb/atm/ueagle-atm.c | 1820 ----------------- trunk/drivers/usb/atm/usbatm.c | 4 +- trunk/drivers/usb/atm/xusbatm.c | 1 + trunk/drivers/usb/class/audio.c | 1 + trunk/drivers/usb/class/cdc-acm.c | 232 +-- trunk/drivers/usb/class/cdc-acm.h | 33 +- trunk/drivers/usb/class/usb-midi.c | 1 + trunk/drivers/usb/class/usblp.c | 45 +- trunk/drivers/usb/core/Makefile | 2 +- trunk/drivers/usb/core/buffer.c | 3 - trunk/drivers/usb/core/devices.c | 24 +- trunk/drivers/usb/core/devio.c | 3 + trunk/drivers/usb/core/driver.c | 472 ----- trunk/drivers/usb/core/hcd.c | 10 +- trunk/drivers/usb/core/hcd.h | 1 - trunk/drivers/usb/core/hub.c | 486 ++--- trunk/drivers/usb/core/hub.h | 3 +- trunk/drivers/usb/core/message.c | 6 - trunk/drivers/usb/core/usb.c | 462 ++++- trunk/drivers/usb/core/usb.h | 6 +- trunk/drivers/usb/gadget/dummy_hcd.c | 91 +- trunk/drivers/usb/gadget/file_storage.c | 93 +- trunk/drivers/usb/gadget/serial.c | 2 - trunk/drivers/usb/host/Makefile | 4 - trunk/drivers/usb/host/ehci-hcd.c | 9 +- trunk/drivers/usb/host/ehci-hub.c | 4 +- trunk/drivers/usb/host/ehci-pci.c | 20 +- trunk/drivers/usb/host/ehci-q.c | 14 +- trunk/drivers/usb/host/isp116x-hcd.c | 422 ++-- trunk/drivers/usb/host/isp116x.h | 83 +- trunk/drivers/usb/host/ohci-hcd.c | 14 +- trunk/drivers/usb/host/ohci-hub.c | 2 +- trunk/drivers/usb/host/ohci-pxa27x.c | 121 +- trunk/drivers/usb/host/pci-quirks.c | 6 + trunk/drivers/usb/host/sl811-hcd.c | 14 +- trunk/drivers/usb/host/sl811_cs.c | 5 +- trunk/drivers/usb/host/uhci-debug.c | 14 +- trunk/drivers/usb/host/uhci-hcd.c | 32 +- trunk/drivers/usb/host/uhci-hcd.h | 32 +- trunk/drivers/usb/host/uhci-q.c | 30 +- trunk/drivers/usb/image/mdc800.c | 1 + trunk/drivers/usb/image/microtek.c | 1 + trunk/drivers/usb/input/Kconfig | 14 - trunk/drivers/usb/input/Makefile | 1 - trunk/drivers/usb/input/acecad.c | 1 + trunk/drivers/usb/input/aiptek.c | 7 +- trunk/drivers/usb/input/appletouch.c | 1 + trunk/drivers/usb/input/ati_remote.c | 22 +- trunk/drivers/usb/input/ati_remote2.c | 477 ----- trunk/drivers/usb/input/fixp-arith.h | 2 +- trunk/drivers/usb/input/hid-core.c | 3 +- trunk/drivers/usb/input/hid-input.c | 4 +- trunk/drivers/usb/input/hiddev.c | 1 + trunk/drivers/usb/input/itmtouch.c | 1 + trunk/drivers/usb/input/kbtab.c | 1 + trunk/drivers/usb/input/keyspan_remote.c | 3 +- trunk/drivers/usb/input/mtouchusb.c | 1 + trunk/drivers/usb/input/powermate.c | 1 + trunk/drivers/usb/input/touchkitusb.c | 149 +- trunk/drivers/usb/input/usbkbd.c | 1 + trunk/drivers/usb/input/usbmouse.c | 1 + trunk/drivers/usb/input/wacom.c | 1 + trunk/drivers/usb/input/xpad.c | 7 +- trunk/drivers/usb/input/yealink.c | 1 + trunk/drivers/usb/media/dabusb.c | 1 + trunk/drivers/usb/media/dsbr100.c | 1 + trunk/drivers/usb/media/ibmcam.c | 2 +- trunk/drivers/usb/media/konicawc.c | 6 +- trunk/drivers/usb/media/ov511.c | 3 +- trunk/drivers/usb/media/pwc/pwc-ctrl.c | 2 +- trunk/drivers/usb/media/pwc/pwc-if.c | 1 + trunk/drivers/usb/media/se401.c | 1 + trunk/drivers/usb/media/sn9c102_core.c | 24 +- trunk/drivers/usb/media/stv680.c | 1 + trunk/drivers/usb/media/stv680.h | 6 +- trunk/drivers/usb/media/usbvideo.c | 4 +- trunk/drivers/usb/media/vicam.c | 1 + trunk/drivers/usb/media/w9968cf.c | 7 +- trunk/drivers/usb/misc/auerswald.c | 5 +- trunk/drivers/usb/misc/cytherm.c | 1 + trunk/drivers/usb/misc/emi26.c | 1 + trunk/drivers/usb/misc/emi62.c | 1 + trunk/drivers/usb/misc/idmouse.c | 1 + trunk/drivers/usb/misc/ldusb.c | 1 + trunk/drivers/usb/misc/legousbtower.c | 1 + trunk/drivers/usb/misc/phidgetkit.c | 1 + trunk/drivers/usb/misc/phidgetservo.c | 1 + trunk/drivers/usb/misc/rio500.c | 5 +- trunk/drivers/usb/misc/sisusbvga/sisusb.c | 11 +- trunk/drivers/usb/misc/usblcd.c | 1 + trunk/drivers/usb/misc/usbled.c | 1 + trunk/drivers/usb/misc/usbtest.c | 1 + trunk/drivers/usb/misc/uss720.c | 1 + trunk/drivers/usb/mon/mon_text.c | 19 +- trunk/drivers/usb/net/asix.c | 5 +- trunk/drivers/usb/net/catc.c | 1 + trunk/drivers/usb/net/cdc_ether.c | 1 + trunk/drivers/usb/net/cdc_subset.c | 1 + trunk/drivers/usb/net/gl620a.c | 1 + trunk/drivers/usb/net/kaweth.c | 1 + trunk/drivers/usb/net/net1080.c | 1 + trunk/drivers/usb/net/pegasus.c | 144 +- trunk/drivers/usb/net/plusb.c | 1 + trunk/drivers/usb/net/rndis_host.c | 1 + trunk/drivers/usb/net/rtl8150.c | 1 + trunk/drivers/usb/net/zaurus.c | 1 + trunk/drivers/usb/net/zd1201.c | 11 +- trunk/drivers/usb/serial/airprime.c | 2 +- trunk/drivers/usb/serial/anydata.c | 2 +- trunk/drivers/usb/serial/belkin_sa.c | 2 +- trunk/drivers/usb/serial/cp2101.c | 2 +- trunk/drivers/usb/serial/cyberjack.c | 2 +- trunk/drivers/usb/serial/cypress_m8.c | 1 - trunk/drivers/usb/serial/digi_acceleport.c | 2 +- trunk/drivers/usb/serial/empeg.c | 2 +- trunk/drivers/usb/serial/ftdi_sio.c | 6 +- trunk/drivers/usb/serial/ftdi_sio.h | 13 - trunk/drivers/usb/serial/garmin_gps.c | 2 +- trunk/drivers/usb/serial/generic.c | 2 +- trunk/drivers/usb/serial/hp4x.c | 2 +- trunk/drivers/usb/serial/io_edgeport.c | 6 +- trunk/drivers/usb/serial/io_edgeport.h | 3 + trunk/drivers/usb/serial/io_fw_boot2.h | 2 +- trunk/drivers/usb/serial/io_ti.c | 4 +- trunk/drivers/usb/serial/ipaq.c | 2 +- trunk/drivers/usb/serial/ipw.c | 2 +- trunk/drivers/usb/serial/ir-usb.c | 2 +- trunk/drivers/usb/serial/keyspan.h | 2 +- trunk/drivers/usb/serial/keyspan_pda.c | 2 +- trunk/drivers/usb/serial/kl5kusb105.c | 2 +- trunk/drivers/usb/serial/kobil_sct.c | 2 +- trunk/drivers/usb/serial/mct_u232.c | 2 +- trunk/drivers/usb/serial/omninet.c | 2 +- trunk/drivers/usb/serial/option.c | 2 +- trunk/drivers/usb/serial/pl2303.c | 4 +- trunk/drivers/usb/serial/safe_serial.c | 6 +- trunk/drivers/usb/serial/ti_usb_3410_5052.c | 9 +- trunk/drivers/usb/serial/usb-serial.c | 48 +- trunk/drivers/usb/serial/usb-serial.h | 4 - trunk/drivers/usb/serial/visor.c | 2 +- trunk/drivers/usb/serial/whiteheat.c | 2 +- trunk/drivers/usb/storage/Kconfig | 23 - trunk/drivers/usb/storage/Makefile | 5 - trunk/drivers/usb/storage/alauda.c | 1119 ---------- trunk/drivers/usb/storage/alauda.h | 100 - trunk/drivers/usb/storage/debug.c | 1 - trunk/drivers/usb/storage/initializers.h | 4 + trunk/drivers/usb/storage/libusual.c | 266 --- trunk/drivers/usb/storage/onetouch.c | 27 - trunk/drivers/usb/storage/protocol.h | 14 + trunk/drivers/usb/storage/sddr09.c | 214 +- trunk/drivers/usb/storage/sddr09.h | 15 +- trunk/drivers/usb/storage/transport.h | 31 + trunk/drivers/usb/storage/unusual_devs.h | 74 +- trunk/drivers/usb/storage/usb.c | 160 +- trunk/drivers/usb/storage/usb.h | 40 +- trunk/drivers/usb/usb-skeleton.c | 29 +- trunk/drivers/w1/dscore.c | 1 + trunk/fs/compat.c | 2 +- trunk/fs/read_write.c | 34 +- trunk/include/asm-arm/arch-pxa/ohci.h | 18 - trunk/include/linux/cpufreq.h | 10 - trunk/include/linux/pfkeyv2.h | 13 +- trunk/include/linux/security.h | 132 ++ trunk/include/linux/usb.h | 33 +- trunk/include/linux/usb_usual.h | 126 -- trunk/include/linux/xfrm.h | 29 + trunk/include/net/flow.h | 7 +- trunk/include/net/xfrm.h | 27 +- trunk/net/core/flow.c | 8 +- trunk/net/key/af_key.c | 197 +- trunk/net/xfrm/xfrm_policy.c | 88 +- trunk/net/xfrm/xfrm_state.c | 9 +- trunk/net/xfrm/xfrm_user.c | 148 +- trunk/security/Kconfig | 13 + trunk/security/dummy.c | 45 +- trunk/sound/usb/usbaudio.c | 1 + trunk/sound/usb/usx2y/usbusx2y.c | 1 + 230 files changed, 2756 insertions(+), 6865 deletions(-) delete mode 100644 trunk/drivers/usb/atm/ueagle-atm.c delete mode 100644 trunk/drivers/usb/core/driver.c delete mode 100644 trunk/drivers/usb/input/ati_remote2.c delete mode 100644 trunk/drivers/usb/storage/alauda.c delete mode 100644 trunk/drivers/usb/storage/alauda.h delete mode 100644 trunk/drivers/usb/storage/libusual.c delete mode 100644 trunk/include/asm-arm/arch-pxa/ohci.h delete mode 100644 trunk/include/linux/usb_usual.h diff --git a/[refs] b/[refs] index df019bd0e7cb..220355b55701 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c6c88bbde4d8b2ffe9886b7130b2e23781d424e5 +refs/heads/master: df71837d5024e2524cd51c93621e558aa7dd9f3f diff --git a/trunk/Documentation/DocBook/usb.tmpl b/trunk/Documentation/DocBook/usb.tmpl index 320af25de3a2..15ce0f21e5e0 100644 --- a/trunk/Documentation/DocBook/usb.tmpl +++ b/trunk/Documentation/DocBook/usb.tmpl @@ -253,7 +253,6 @@ !Edrivers/usb/core/urb.c !Edrivers/usb/core/message.c !Edrivers/usb/core/file.c -!Edrivers/usb/core/driver.c !Edrivers/usb/core/usb.c !Edrivers/usb/core/hub.c diff --git a/trunk/Documentation/cpu-freq/governors.txt b/trunk/Documentation/cpu-freq/governors.txt index f4b8dc4237e6..933fae74c337 100644 --- a/trunk/Documentation/cpu-freq/governors.txt +++ b/trunk/Documentation/cpu-freq/governors.txt @@ -27,7 +27,6 @@ Contents: 2.2 Powersave 2.3 Userspace 2.4 Ondemand -2.5 Conservative 3. The Governor Interface in the CPUfreq Core @@ -111,64 +110,9 @@ directory. The CPUfreq govenor "ondemand" sets the CPU depending on the current usage. To do this the CPU must have the capability to -switch the frequency very quickly. There are a number of sysfs file -accessible parameters: - -sampling_rate: measured in uS (10^-6 seconds), this is how often you -want the kernel to look at the CPU usage and to make decisions on -what to do about the frequency. Typically this is set to values of -around '10000' or more. - -show_sampling_rate_(min|max): the minimum and maximum sampling rates -available that you may set 'sampling_rate' to. - -up_threshold: defines what the average CPU usaged between the samplings -of 'sampling_rate' needs to be for the kernel to make a decision on -whether it should increase the frequency. For example when it is set -to its default value of '80' it means that between the checking -intervals the CPU needs to be on average more than 80% in use to then -decide that the CPU frequency needs to be increased. - -sampling_down_factor: this parameter controls the rate that the CPU -makes a decision on when to decrease the frequency. When set to its -default value of '5' it means that at 1/5 the sampling_rate the kernel -makes a decision to lower the frequency. Five "lower rate" decisions -have to be made in a row before the CPU frequency is actually lower. -If set to '1' then the frequency decreases as quickly as it increases, -if set to '2' it decreases at half the rate of the increase. - -ignore_nice_load: this parameter takes a value of '0' or '1', when set -to '0' (its default) then all processes are counted towards towards the -'cpu utilisation' value. When set to '1' then processes that are -run with a 'nice' value will not count (and thus be ignored) in the -overal usage calculation. This is useful if you are running a CPU -intensive calculation on your laptop that you do not care how long it -takes to complete as you can 'nice' it and prevent it from taking part -in the deciding process of whether to increase your CPU frequency. - - -2.5 Conservative ----------------- - -The CPUfreq governor "conservative", much like the "ondemand" -governor, sets the CPU depending on the current usage. It differs in -behaviour in that it gracefully increases and decreases the CPU speed -rather than jumping to max speed the moment there is any load on the -CPU. This behaviour more suitable in a battery powered environment. -The governor is tweaked in the same manner as the "ondemand" governor -through sysfs with the addition of: - -freq_step: this describes what percentage steps the cpu freq should be -increased and decreased smoothly by. By default the cpu frequency will -increase in 5% chunks of your maximum cpu frequency. You can change this -value to anywhere between 0 and 100 where '0' will effectively lock your -CPU at a speed regardless of its load whilst '100' will, in theory, make -it behave identically to the "ondemand" governor. - -down_threshold: same as the 'up_threshold' found for the "ondemand" -governor but for the opposite direction. For example when set to its -default value of '20' it means that if the CPU usage needs to be below -20% between samples to have the frequency decreased. +switch the frequency very fast. + + 3. The Governor Interface in the CPUfreq Core ============================================= diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 3fd7687a6ad9..6af683025ae0 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -2640,12 +2640,6 @@ L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained -USB ISP116X DRIVER -P: Olav Kongas -M: ok@artecdesign.ee -L: linux-usb-devel@lists.sourceforge.net -S: Maintained - USB KAWASAKI LSI DRIVER P: Oliver Neukum M: oliver@neukum.name @@ -2657,7 +2651,7 @@ USB MASS STORAGE DRIVER P: Matthew Dharm M: mdharm-usb@one-eyed-alien.net L: linux-usb-users@lists.sourceforge.net -L: usb-storage@lists.one-eyed-alien.net +L: linux-usb-devel@lists.sourceforge.net S: Maintained W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ diff --git a/trunk/arch/arm/mach-pxa/mainstone.c b/trunk/arch/arm/mach-pxa/mainstone.c index 277498ae5b6c..07892f4012d8 100644 --- a/trunk/arch/arm/mach-pxa/mainstone.c +++ b/trunk/arch/arm/mach-pxa/mainstone.c @@ -43,7 +43,6 @@ #include #include #include -#include #include "generic.h" @@ -394,25 +393,6 @@ static struct platform_device *platform_devices[] __initdata = { &mst_flash_device[1], }; -static int mainstone_ohci_init(struct device *dev) -{ - /* setup Port1 GPIO pin. */ - pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */ - pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */ - - /* Set the Power Control Polarity Low and Power Sense - Polarity Low to active low. */ - UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & - ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); - - return 0; -} - -static struct pxaohci_platform_data mainstone_ohci_platform_data = { - .port_mode = PMM_PERPORT_MODE, - .init = mainstone_ohci_init, -}; - static void __init mainstone_init(void) { int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */ @@ -444,7 +424,6 @@ static void __init mainstone_init(void) pxa_set_mci_info(&mainstone_mci_platform_data); pxa_set_ficp_info(&mainstone_ficp_platform_data); - pxa_set_ohci_info(&mainstone_ohci_platform_data); } diff --git a/trunk/arch/arm/mach-pxa/pxa27x.c b/trunk/arch/arm/mach-pxa/pxa27x.c index b41b1efaa2cf..c722a9a91fcc 100644 --- a/trunk/arch/arm/mach-pxa/pxa27x.c +++ b/trunk/arch/arm/mach-pxa/pxa27x.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "generic.h" @@ -195,11 +194,6 @@ static struct platform_device ohci_device = { .resource = pxa27x_ohci_resources, }; -void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) -{ - ohci_device.dev.platform_data = info; -} - static struct platform_device *devices[] __initdata = { &ohci_device, }; diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/trunk/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c index 2b62dee35c6c..04a405345203 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c @@ -177,10 +177,9 @@ static unsigned int nforce2_fsb_read(int bootfsb) */ static int nforce2_set_fsb(unsigned int fsb) { - u32 temp = 0; + u32 pll, temp = 0; unsigned int tfsb; int diff; - int pll = 0; if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) { printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb); diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 0fbbd4c1072e..68a1fc87f4ca 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -45,7 +45,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.60.0" +#define VERSION "version 1.50.4" #include "powernow-k8.h" /* serialize freq changes */ @@ -216,10 +216,10 @@ static int write_new_vid(struct powernow_k8_data *data, u32 vid) do { wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS); - if (i++ > 100) { - printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n"); - return 1; - } + if (i++ > 100) { + printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n"); + return 1; + } } while (query_current_values_with_pending_wait(data)); if (savefid != data->currfid) { @@ -336,7 +336,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid /* Phase 2 - core frequency transition */ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) { - u32 vcoreqfid, vcocurrfid, vcofiddiff, fid_interval, savevid = data->currvid; + u32 vcoreqfid, vcocurrfid, vcofiddiff, savevid = data->currvid; if ((reqfid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) { printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n", @@ -359,11 +359,9 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) : vcoreqfid - vcocurrfid; while (vcofiddiff > 2) { - (data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2); - if (reqfid > data->currfid) { if (data->currfid > LO_FID_TABLE_TOP) { - if (write_new_fid(data, data->currfid + fid_interval)) { + if (write_new_fid(data, data->currfid + 2)) { return 1; } } else { @@ -373,7 +371,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) } } } else { - if (write_new_fid(data, data->currfid - fid_interval)) + if (write_new_fid(data, data->currfid - 2)) return 1; } @@ -466,7 +464,7 @@ static int check_supported_cpu(unsigned int cpu) set_cpus_allowed(current, cpumask_of_cpu(cpu)); if (smp_processor_id() != cpu) { - printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu); + printk(KERN_ERR "limiting to cpu %u failed\n", cpu); goto out; } @@ -476,7 +474,7 @@ static int check_supported_cpu(unsigned int cpu) eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || ((eax & CPUID_XFAM) != CPUID_XFAM_K8) || - ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) { + ((eax & CPUID_XMOD) > CPUID_XMOD_REV_F)) { printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); goto out; } @@ -519,24 +517,22 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8 printk(KERN_ERR BFX "maxvid exceeded with pstate %d\n", j); return -ENODEV; } - if (pst[j].fid > MAX_FID) { - printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j); - return -ENODEV; - } - if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) { + if ((pst[j].fid > MAX_FID) + || (pst[j].fid & 1) + || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) { /* Only first fid is allowed to be in "low" range */ - printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid); + printk(KERN_ERR PFX "two low fids - %d : 0x%x\n", j, pst[j].fid); return -EINVAL; } if (pst[j].fid < lastfid) lastfid = pst[j].fid; } if (lastfid & 1) { - printk(KERN_ERR BFX "lastfid invalid\n"); + printk(KERN_ERR PFX "lastfid invalid\n"); return -EINVAL; } if (lastfid > LO_FID_TABLE_TOP) - printk(KERN_INFO BFX "first fid not from lo freq table\n"); + printk(KERN_INFO PFX "first fid not from lo freq table\n"); return 0; } @@ -635,7 +631,7 @@ static int find_psb_table(struct powernow_k8_data *data) dprintk("table vers: 0x%x\n", psb->tableversion); if (psb->tableversion != PSB_VERSION_1_4) { - printk(KERN_ERR BFX "PSB table is not v1.4\n"); + printk(KERN_INFO BFX "PSB table is not v1.4\n"); return -ENODEV; } @@ -693,7 +689,7 @@ static int find_psb_table(struct powernow_k8_data *data) * BIOS and Kernel Developer's Guide, which is available on * www.amd.com */ - printk(KERN_ERR PFX "BIOS error - no PSB or ACPI _PSS objects\n"); + printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n"); return -ENODEV; } @@ -916,7 +912,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); if (smp_processor_id() != pol->cpu) { - printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); + printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu); goto err_out; } @@ -986,9 +982,6 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) cpumask_t oldmask = CPU_MASK_ALL; int rc, i; - if (!cpu_online(pol->cpu)) - return -ENODEV; - if (!check_supported_cpu(pol->cpu)) return -ENODEV; @@ -1028,7 +1021,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); if (smp_processor_id() != pol->cpu) { - printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); + printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu); goto err_out; } @@ -1169,9 +1162,10 @@ static void __exit powernowk8_exit(void) cpufreq_unregister_driver(&cpufreq_amd64_driver); } -MODULE_AUTHOR("Paul Devriendt and Mark Langsdorf "); +MODULE_AUTHOR("Paul Devriendt and Mark Langsdorf = interprocessor hypertransport link speed * (only applies to MP systems obviously) */ /* fids (frequency identifiers) are arranged in 2 tables - lo and hi */ -#define LO_FID_TABLE_TOP 7 /* fid values marking the boundary */ +#define LO_FID_TABLE_TOP 6 /* fid values marking the boundary */ #define HI_FID_TABLE_BOTTOM 8 /* between the low and high tables */ #define LO_VCOFREQ_TABLE_TOP 1400 /* corresponding vco frequency values */ @@ -107,7 +106,7 @@ struct powernow_k8_data { #define MIN_FREQ 800 /* Min and max freqs, per spec */ #define MAX_FREQ 5000 -#define INVALID_FID_MASK 0xffffffc0 /* not a valid fid if these bits are set */ +#define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */ #define INVALID_VID_MASK 0xffffffc0 /* not a valid vid if these bits are set */ #define VID_OFF 0x3f diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index b425cd3d1838..5b7d18a06afa 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -40,7 +40,6 @@ static struct pci_dev *speedstep_chipset_dev; */ static unsigned int speedstep_processor = 0; -static u32 pmbase; /* * There are only two frequency states for each processor. Values @@ -57,46 +56,33 @@ static struct cpufreq_frequency_table speedstep_freqs[] = { /** - * speedstep_find_register - read the PMBASE address + * speedstep_set_state - set the SpeedStep state + * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) * - * Returns: -ENODEV if no register could be found + * Tries to change the SpeedStep state. */ -static int speedstep_find_register (void) +static void speedstep_set_state (unsigned int state) { - if (!speedstep_chipset_dev) - return -ENODEV; + u32 pmbase; + u8 pm2_blk; + u8 value; + unsigned long flags; + + if (!speedstep_chipset_dev || (state > 0x1)) + return; /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) { printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); - return -ENODEV; + return; } pmbase &= 0xFFFFFFFE; if (!pmbase) { printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); - return -ENODEV; - } - - dprintk("pmbase is 0x%x\n", pmbase); - return 0; -} - -/** - * speedstep_set_state - set the SpeedStep state - * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) - * - * Tries to change the SpeedStep state. - */ -static void speedstep_set_state (unsigned int state) -{ - u8 pm2_blk; - u8 value; - unsigned long flags; - - if (state > 0x1) return; + } /* Disable IRQs */ local_irq_save(flags); @@ -329,11 +315,10 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) cpus_allowed = current->cpus_allowed; set_cpus_allowed(current, policy->cpus); - /* detect low and high frequency and transition latency */ + /* detect low and high frequency */ result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, - &policy->cpuinfo.transition_latency, &speedstep_set_state); set_cpus_allowed(current, cpus_allowed); if (result) @@ -350,6 +335,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) /* cpuinfo and default policy values */ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); @@ -414,9 +400,6 @@ static int __init speedstep_init(void) return -EINVAL; } - if (speedstep_find_register()) - return -ENODEV; - return cpufreq_register_driver(&speedstep_driver); } diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c index 7c47005a1805..d368b3f5fce8 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c @@ -320,13 +320,11 @@ EXPORT_SYMBOL_GPL(speedstep_detect_processor); unsigned int speedstep_get_freqs(unsigned int processor, unsigned int *low_speed, unsigned int *high_speed, - unsigned int *transition_latency, void (*set_state) (unsigned int state)) { unsigned int prev_speed; unsigned int ret = 0; unsigned long flags; - struct timeval tv1, tv2; if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) return -EINVAL; @@ -339,7 +337,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, return -EIO; dprintk("previous speed is %u\n", prev_speed); - + local_irq_save(flags); /* switch to low state */ @@ -352,17 +350,8 @@ unsigned int speedstep_get_freqs(unsigned int processor, dprintk("low speed is %u\n", *low_speed); - /* start latency measurement */ - if (transition_latency) - do_gettimeofday(&tv1); - /* switch to high state */ set_state(SPEEDSTEP_HIGH); - - /* end latency measurement */ - if (transition_latency) - do_gettimeofday(&tv2); - *high_speed = speedstep_get_processor_frequency(processor); if (!*high_speed) { ret = -EIO; @@ -380,25 +369,6 @@ unsigned int speedstep_get_freqs(unsigned int processor, if (*high_speed != prev_speed) set_state(SPEEDSTEP_LOW); - if (transition_latency) { - *transition_latency = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC + - tv2.tv_usec - tv1.tv_usec; - dprintk("transition latency is %u uSec\n", *transition_latency); - - /* convert uSec to nSec and add 20% for safety reasons */ - *transition_latency *= 1200; - - /* check if the latency measurement is too high or too low - * and set it to a safe value (500uSec) in that case - */ - if (*transition_latency > 10000000 || *transition_latency < 50000) { - printk (KERN_WARNING "speedstep: frequency transition measured seems out of " - "range (%u nSec), falling back to a safe one of %u nSec.\n", - *transition_latency, 500000); - *transition_latency = 500000; - } - } - out: local_irq_restore(flags); return (ret); diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h index 6a727fd3a77e..261a2c9b7f6b 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h +++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h @@ -44,5 +44,4 @@ extern unsigned int speedstep_get_processor_frequency(unsigned int processor); extern unsigned int speedstep_get_freqs(unsigned int processor, unsigned int *low_speed, unsigned int *high_speed, - unsigned int *transition_latency, void (*set_state) (unsigned int state)); diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index 28cc5d524afc..2718fb6f6aba 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c @@ -269,7 +269,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, - NULL, &speedstep_set_state); if (result) { diff --git a/trunk/arch/i386/kernel/cpu/proc.c b/trunk/arch/i386/kernel/cpu/proc.c index 6d91b274589c..e7921315ae9d 100644 --- a/trunk/arch/i386/kernel/cpu/proc.c +++ b/trunk/arch/i386/kernel/cpu/proc.c @@ -3,7 +3,6 @@ #include #include #include -#include /* * Get CPU information for use by the procfs. @@ -87,11 +86,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "stepping\t: unknown\n"); if ( cpu_has(c, X86_FEATURE_TSC) ) { - unsigned int freq = cpufreq_quick_get(n); - if (!freq) - freq = cpu_khz; seq_printf(m, "cpu MHz\t\t: %u.%03u\n", - freq / 1000, (freq % 1000)); + cpu_khz / 1000, (cpu_khz % 1000)); } /* Cache size */ diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c index 088e5dded8dc..5add0bcf87a7 100644 --- a/trunk/arch/ia64/kernel/setup.c +++ b/trunk/arch/ia64/kernel/setup.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -518,7 +517,6 @@ show_cpuinfo (struct seq_file *m, void *v) char family[32], features[128], *cp, sep; struct cpuinfo_ia64 *c = v; unsigned long mask; - unsigned int proc_freq; int i; mask = c->features; @@ -551,10 +549,6 @@ show_cpuinfo (struct seq_file *m, void *v) sprintf(cp, " 0x%lx", mask); } - proc_freq = cpufreq_quick_get(cpunum); - if (!proc_freq) - proc_freq = c->proc_freq / 1000; - seq_printf(m, "processor : %d\n" "vendor : %s\n" @@ -571,7 +565,7 @@ show_cpuinfo (struct seq_file *m, void *v) "BogoMIPS : %lu.%02lu\n", cpunum, c->vendor, family, c->model, c->revision, c->archrev, features, c->ppn, c->number, - proc_freq / 1000, proc_freq % 1000, + c->proc_freq / 1000000, c->proc_freq % 1000000, c->itc_freq / 1000000, c->itc_freq % 1000000, lpj*HZ/500000, (lpj*HZ/5000) % 100); #ifdef CONFIG_SMP diff --git a/trunk/arch/mips/kernel/linux32.c b/trunk/arch/mips/kernel/linux32.c index 60353f5acc48..330cf84d21fe 100644 --- a/trunk/arch/mips/kernel/linux32.c +++ b/trunk/arch/mips/kernel/linux32.c @@ -420,7 +420,7 @@ asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf, goto out; pos = merge_64(a4, a5); ret = rw_verify_area(READ, file, &pos, count); - if (ret < 0) + if (ret) goto out; ret = -EINVAL; if (!file->f_op || !(read = file->f_op->read)) @@ -455,7 +455,7 @@ asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, goto out; pos = merge_64(a4, a5); ret = rw_verify_area(WRITE, file, &pos, count); - if (ret < 0) + if (ret) goto out; ret = -EINVAL; if (!file->f_op || !(write = file->f_op->write)) diff --git a/trunk/arch/x86_64/kernel/setup.c b/trunk/arch/x86_64/kernel/setup.c index 64c4534b930c..750e01dcbdf4 100644 --- a/trunk/arch/x86_64/kernel/setup.c +++ b/trunk/arch/x86_64/kernel/setup.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -1257,11 +1256,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "stepping\t: unknown\n"); if (cpu_has(c,X86_FEATURE_TSC)) { - unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data)); - if (!freq) - freq = cpu_khz; seq_printf(m, "cpu MHz\t\t: %u.%03u\n", - freq / 1000, (freq % 1000)); + cpu_khz / 1000, (cpu_khz % 1000)); } /* Cache size */ diff --git a/trunk/drivers/block/Kconfig b/trunk/drivers/block/Kconfig index c4b9d2adfc08..7b1cd93892be 100644 --- a/trunk/drivers/block/Kconfig +++ b/trunk/drivers/block/Kconfig @@ -358,8 +358,7 @@ config BLK_DEV_UB This driver supports certain USB attached storage devices such as flash keys. - If you enable this driver, it is recommended to avoid conflicts - with usb-storage by enabling USB_LIBUSUAL. + Warning: Enabling this cripples the usb-storage driver. If unsure, say N. diff --git a/trunk/drivers/block/ub.c b/trunk/drivers/block/ub.c index 10740a065088..bfb23d543ff7 100644 --- a/trunk/drivers/block/ub.c +++ b/trunk/drivers/block/ub.c @@ -9,6 +9,7 @@ * * TODO (sorted by decreasing priority) * -- Kill first_open (Al Viro fixed the block layer now) + * -- Do resets with usb_device_reset (needs a thread context, use khubd) * -- set readonly flag for CDs, set removable flag for CF readers * -- do inquiry and verify we got a disk and not a tape (for LUN mismatch) * -- special case some senses, e.g. 3a/0 -> no media present, reduce retries @@ -28,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -106,6 +106,16 @@ * +--------+ */ +/* + * Definitions which have to be scattered once we understand the layout better. + */ + +/* Transport (despite PR in the name) */ +#define US_PR_BULK 0x50 /* bulk only */ + +/* Protocol */ +#define US_SC_SCSI 0x06 /* Transparent */ + /* * This many LUNs per USB device. * Every one of them takes a host, see UB_MAX_HOSTS. @@ -115,7 +125,7 @@ /* */ -#define UB_PARTS_PER_LUN 8 +#define UB_MINORS_PER_MAJOR 8 #define UB_MAX_CDB_SIZE 16 /* Corresponds to Bulk */ @@ -235,13 +245,6 @@ struct ub_scsi_cmd { void *back; }; -struct ub_request { - struct request *rq; - unsigned int current_try; - unsigned int nsg; /* sgv[nsg] */ - struct scatterlist sgv[UB_MAX_REQ_SG]; -}; - /* */ struct ub_capacity { @@ -337,8 +340,6 @@ struct ub_lun { int readonly; int first_open; /* Kludge. See ub_bd_open. */ - struct ub_request urq; - /* Use Ingo's mempool if or when we have more than one command. */ /* * Currently we never need more than one command for the whole device. @@ -359,7 +360,6 @@ struct ub_dev { atomic_t poison; /* The USB device is disconnected */ int openc; /* protected by ub_lock! */ /* kref is too implicit for our taste */ - int reset; /* Reset is running */ unsigned int tagcnt; char name[12]; struct usb_device *dev; @@ -387,9 +387,6 @@ struct ub_dev { struct bulk_cs_wrap work_bcs; struct usb_ctrlrequest work_cr; - struct work_struct reset_work; - wait_queue_head_t reset_wait; - int sg_stat[6]; struct ub_scsi_trace tr; }; @@ -398,14 +395,12 @@ struct ub_dev { */ static void ub_cleanup(struct ub_dev *sc); static int ub_request_fn_1(struct ub_lun *lun, struct request *rq); -static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, - struct ub_scsi_cmd *cmd, struct ub_request *urq); -static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, - struct ub_scsi_cmd *cmd, struct ub_request *urq); +static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, + struct ub_scsi_cmd *cmd, struct request *rq); +static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, + struct ub_scsi_cmd *cmd, struct request *rq); static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_end_rq(struct request *rq, int uptodate); -static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, - struct ub_request *urq, struct ub_scsi_cmd *cmd); static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_urb_complete(struct urb *urb, struct pt_regs *pt); static void ub_scsi_action(unsigned long _dev); @@ -420,8 +415,6 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int stalled_pipe); static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd); -static void ub_reset_enter(struct ub_dev *sc); -static void ub_reset_task(void *arg); static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun); static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, struct ub_capacity *ret); @@ -429,18 +422,13 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum); /* */ -#ifdef CONFIG_USB_LIBUSUAL - -#define ub_usb_ids storage_usb_ids -#else - static struct usb_device_id ub_usb_ids[] = { + // { USB_DEVICE_VER(0x0781, 0x0002, 0x0009, 0x0009) }, /* SDDR-31 */ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) }, { } }; MODULE_DEVICE_TABLE(usb, ub_usb_ids); -#endif /* CONFIG_USB_LIBUSUAL */ /* * Find me a way to identify "next free minor" for add_disk(), @@ -533,9 +521,6 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, cnt = 0; spin_lock_irqsave(&sc->lock, flags); - cnt += sprintf(page + cnt, - "poison %d reset %d\n", - atomic_read(&sc->poison), sc->reset); cnt += sprintf(page + cnt, "qlen %d qmax %d\n", sc->cmd_queue.qlen, sc->cmd_queue.qmax); @@ -785,8 +770,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) { struct ub_dev *sc = lun->udev; struct ub_scsi_cmd *cmd; - struct ub_request *urq; - int n_elem; + int rc; if (atomic_read(&sc->poison) || lun->changed) { blkdev_dequeue_request(rq); @@ -794,70 +778,65 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) return 0; } - if (lun->urq.rq != NULL) - return -1; if ((cmd = ub_get_cmd(lun)) == NULL) return -1; memset(cmd, 0, sizeof(struct ub_scsi_cmd)); blkdev_dequeue_request(rq); - - urq = &lun->urq; - memset(urq, 0, sizeof(struct ub_request)); - urq->rq = rq; - - /* - * get scatterlist from block layer - */ - n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]); - if (n_elem < 0) { - printk(KERN_INFO "%s: failed request map (%d)\n", - lun->name, n_elem); /* P3 */ - goto drop; - } - if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ - printk(KERN_WARNING "%s: request with %d segments\n", - lun->name, n_elem); - goto drop; - } - urq->nsg = n_elem; - sc->sg_stat[n_elem < 5 ? n_elem : 5]++; - if (blk_pc_request(rq)) { - ub_cmd_build_packet(sc, lun, cmd, urq); + rc = ub_cmd_build_packet(sc, lun, cmd, rq); } else { - ub_cmd_build_block(sc, lun, cmd, urq); + rc = ub_cmd_build_block(sc, lun, cmd, rq); + } + if (rc != 0) { + ub_put_cmd(lun, cmd); + ub_end_rq(rq, 0); + return 0; } cmd->state = UB_CMDST_INIT; cmd->lun = lun; cmd->done = ub_rw_cmd_done; - cmd->back = urq; + cmd->back = rq; cmd->tag = sc->tagcnt++; - if (ub_submit_scsi(sc, cmd) != 0) - goto drop; - - return 0; + if (ub_submit_scsi(sc, cmd) != 0) { + ub_put_cmd(lun, cmd); + ub_end_rq(rq, 0); + return 0; + } -drop: - ub_put_cmd(lun, cmd); - ub_end_rq(rq, 0); return 0; } -static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, - struct ub_scsi_cmd *cmd, struct ub_request *urq) +static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, + struct ub_scsi_cmd *cmd, struct request *rq) { - struct request *rq = urq->rq; + int ub_dir; + int n_elem; unsigned int block, nblks; if (rq_data_dir(rq) == WRITE) - cmd->dir = UB_DIR_WRITE; + ub_dir = UB_DIR_WRITE; else - cmd->dir = UB_DIR_READ; + ub_dir = UB_DIR_READ; + cmd->dir = ub_dir; - cmd->nsg = urq->nsg; - memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg); + /* + * get scatterlist from block layer + */ + n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]); + if (n_elem <= 0) { + printk(KERN_INFO "%s: failed request map (%d)\n", + sc->name, n_elem); /* P3 */ + return -1; /* request with no s/g entries? */ + } + if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ + printk(KERN_WARNING "%s: request with %d segments\n", + sc->name, n_elem); + return -1; + } + cmd->nsg = n_elem; + sc->sg_stat[n_elem < 5 ? n_elem : 5]++; /* * build the command @@ -868,7 +847,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, block = rq->sector >> lun->capacity.bshift; nblks = rq->nr_sectors >> lun->capacity.bshift; - cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10; + cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10; /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */ cmd->cdb[2] = block >> 24; cmd->cdb[3] = block >> 16; @@ -879,12 +858,14 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, cmd->cdb_len = 10; cmd->len = rq->nr_sectors * 512; + + return 0; } -static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, - struct ub_scsi_cmd *cmd, struct ub_request *urq) +static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, + struct ub_scsi_cmd *cmd, struct request *rq) { - struct request *rq = urq->rq; + int n_elem; if (rq->data_len == 0) { cmd->dir = UB_DIR_NONE; @@ -893,26 +874,40 @@ static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, cmd->dir = UB_DIR_WRITE; else cmd->dir = UB_DIR_READ; + } - cmd->nsg = urq->nsg; - memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg); + /* + * get scatterlist from block layer + */ + n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]); + if (n_elem < 0) { + printk(KERN_INFO "%s: failed request map (%d)\n", + sc->name, n_elem); /* P3 */ + return -1; + } + if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ + printk(KERN_WARNING "%s: request with %d segments\n", + sc->name, n_elem); + return -1; + } + cmd->nsg = n_elem; + sc->sg_stat[n_elem < 5 ? n_elem : 5]++; memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); cmd->cdb_len = rq->cmd_len; cmd->len = rq->data_len; + + return 0; } static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { + struct request *rq = cmd->back; struct ub_lun *lun = cmd->lun; - struct ub_request *urq = cmd->back; - struct request *rq; int uptodate; - rq = urq->rq; - if (cmd->error == 0) { uptodate = 1; @@ -933,16 +928,9 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) rq->errors = SAM_STAT_CHECK_CONDITION; else rq->errors = DID_ERROR << 16; - } else { - if (cmd->error == -EIO) { - if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0) - return; - } } } - urq->rq = NULL; - ub_put_cmd(lun, cmd); ub_end_rq(rq, uptodate); blk_start_queue(lun->disk->queue); @@ -950,43 +938,11 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) static void ub_end_rq(struct request *rq, int uptodate) { - end_that_request_first(rq, uptodate, rq->hard_nr_sectors); - end_that_request_last(rq); -} - -static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, - struct ub_request *urq, struct ub_scsi_cmd *cmd) -{ - - if (atomic_read(&sc->poison)) - return -ENXIO; - - ub_reset_enter(sc); - - if (urq->current_try >= 3) - return -EIO; - urq->current_try++; - /* P3 */ printk("%s: dir %c len/act %d/%d " - "[sense %x %02x %02x] retry %d\n", - sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len, - cmd->key, cmd->asc, cmd->ascq, urq->current_try); - - memset(cmd, 0, sizeof(struct ub_scsi_cmd)); - ub_cmd_build_block(sc, lun, cmd, urq); - - cmd->state = UB_CMDST_INIT; - cmd->lun = lun; - cmd->done = ub_rw_cmd_done; - cmd->back = urq; - - cmd->tag = sc->tagcnt++; + int rc; -#if 0 /* Wasteful */ - return ub_submit_scsi(sc, cmd); -#else - ub_cmdq_add(sc, cmd); - return 0; -#endif + rc = end_that_request_first(rq, uptodate, rq->hard_nr_sectors); + // assert(rc == 0); + end_that_request_last(rq); } /* @@ -1119,7 +1075,7 @@ static void ub_scsi_dispatch(struct ub_dev *sc) struct ub_scsi_cmd *cmd; int rc; - while (!sc->reset && (cmd = ub_cmdq_peek(sc)) != NULL) { + while ((cmd = ub_cmdq_peek(sc)) != NULL) { if (cmd->state == UB_CMDST_DONE) { ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); @@ -1142,12 +1098,11 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct urb *urb = &sc->work_urb; struct bulk_cs_wrap *bcs; - int len; int rc; if (atomic_read(&sc->poison)) { - ub_state_done(sc, cmd, -ENODEV); - return; + /* A little too simplistic, I feel... */ + goto Bad_End; } if (cmd->state == UB_CMDST_CLEAR) { @@ -1155,6 +1110,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) /* * STALL while clearning STALL. * The control pipe clears itself - nothing to do. + * XXX Might try to reset the device here and retry. */ printk(KERN_NOTICE "%s: stall on control pipe\n", sc->name); @@ -1173,6 +1129,11 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) } else if (cmd->state == UB_CMDST_CLR2STS) { if (urb->status == -EPIPE) { + /* + * STALL while clearning STALL. + * The control pipe clears itself - nothing to do. + * XXX Might try to reset the device here and retry. + */ printk(KERN_NOTICE "%s: stall on control pipe\n", sc->name); goto Bad_End; @@ -1190,6 +1151,11 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) } else if (cmd->state == UB_CMDST_CLRRS) { if (urb->status == -EPIPE) { + /* + * STALL while clearning STALL. + * The control pipe clears itself - nothing to do. + * XXX Might try to reset the device here and retry. + */ printk(KERN_NOTICE "%s: stall on control pipe\n", sc->name); goto Bad_End; @@ -1206,12 +1172,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ub_state_stat_counted(sc, cmd); } else if (cmd->state == UB_CMDST_CMD) { - switch (urb->status) { - case 0: - break; - case -EOVERFLOW: - goto Bad_End; - case -EPIPE: + if (urb->status == -EPIPE) { rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe); if (rc != 0) { printk(KERN_NOTICE "%s: " @@ -1221,20 +1182,17 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) * This is typically ENOMEM or some other such shit. * Retrying is pointless. Just do Bad End on it... */ - ub_state_done(sc, cmd, rc); - return; + goto Bad_End; } cmd->state = UB_CMDST_CLEAR; ub_cmdtr_state(sc, cmd); return; - case -ESHUTDOWN: /* unplug */ - case -EILSEQ: /* unplug timeout on uhci */ - ub_state_done(sc, cmd, -ENODEV); - return; - default: + } + if (urb->status != 0) { goto Bad_End; } if (urb->actual_length != US_BULK_CB_WRAP_LEN) { + /* XXX Must do reset here to unconfuse the device */ goto Bad_End; } @@ -1253,8 +1211,11 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) printk(KERN_NOTICE "%s: " "unable to submit clear (%d)\n", sc->name, rc); - ub_state_done(sc, cmd, rc); - return; + /* + * This is typically ENOMEM or some other such shit. + * Retrying is pointless. Just do Bad End on it... + */ + goto Bad_End; } cmd->state = UB_CMDST_CLR2STS; ub_cmdtr_state(sc, cmd); @@ -1263,50 +1224,14 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) if (urb->status == -EOVERFLOW) { /* * A babble? Failure, but we must transfer CSW now. + * XXX This is going to end in perpetual babble. Reset. */ cmd->error = -EOVERFLOW; /* A cheap trick... */ ub_state_stat(sc, cmd); return; } - - if (cmd->dir == UB_DIR_WRITE) { - /* - * Do not continue writes in case of a failure. - * Doing so would cause sectors to be mixed up, - * which is worse than sectors lost. - * - * We must try to read the CSW, or many devices - * get confused. - */ - len = urb->actual_length; - if (urb->status != 0 || - len != cmd->sgv[cmd->current_sg].length) { - cmd->act_len += len; - ub_cmdtr_act_len(sc, cmd); - - cmd->error = -EIO; - ub_state_stat(sc, cmd); - return; - } - - } else { - /* - * If an error occurs on read, we record it, and - * continue to fetch data in order to avoid bubble. - * - * As a small shortcut, we stop if we detect that - * a CSW mixed into data. - */ - if (urb->status != 0) - cmd->error = -EIO; - - len = urb->actual_length; - if (urb->status != 0 || - len != cmd->sgv[cmd->current_sg].length) { - if ((len & 0x1FF) == US_BULK_CS_WRAP_LEN) - goto Bad_End; - } - } + if (urb->status != 0) + goto Bad_End; cmd->act_len += urb->actual_length; ub_cmdtr_act_len(sc, cmd); @@ -1324,8 +1249,11 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) printk(KERN_NOTICE "%s: " "unable to submit clear (%d)\n", sc->name, rc); - ub_state_done(sc, cmd, rc); - return; + /* + * This is typically ENOMEM or some other such shit. + * Retrying is pointless. Just do Bad End on it... + */ + goto Bad_End; } /* @@ -1338,8 +1266,14 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ub_cmdtr_state(sc, cmd); return; } - - /* Catch everything, including -EOVERFLOW and other nasties. */ + if (urb->status == -EOVERFLOW) { + /* + * XXX We are screwed here. Retrying is pointless, + * because the pipelined data will not get in until + * we read with a big enough buffer. We must reset XXX. + */ + goto Bad_End; + } if (urb->status != 0) goto Bad_End; @@ -1385,15 +1319,15 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) return; } - len = le32_to_cpu(bcs->Residue); - if (len != cmd->len - cmd->act_len) { + rc = le32_to_cpu(bcs->Residue); + if (rc != cmd->len - cmd->act_len) { /* * It is all right to transfer less, the caller has * to check. But it's not all right if the device * counts disagree with our counts. */ /* P3 */ printk("%s: resid %d len %d act %d\n", - sc->name, len, cmd->len, cmd->act_len); + sc->name, rc, cmd->len, cmd->act_len); goto Bad_End; } @@ -1404,13 +1338,13 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ub_state_sense(sc, cmd); return; case US_BULK_STAT_PHASE: + /* XXX We must reset the transport here */ /* P3 */ printk("%s: status PHASE\n", sc->name); goto Bad_End; default: printk(KERN_INFO "%s: unknown CSW status 0x%x\n", sc->name, bcs->Status); - ub_state_done(sc, cmd, -EINVAL); - return; + goto Bad_End; } /* Not zeroing error to preserve a babble indicator */ @@ -1430,8 +1364,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) printk(KERN_WARNING "%s: " "wrong command state %d\n", sc->name, cmd->state); - ub_state_done(sc, cmd, -EINVAL); - return; + goto Bad_End; } return; @@ -1678,93 +1611,6 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) ub_scsi_urb_compl(sc, cmd); } -/* - * Reset management - */ - -static void ub_reset_enter(struct ub_dev *sc) -{ - - if (sc->reset) { - /* This happens often on multi-LUN devices. */ - return; - } - sc->reset = 1; - -#if 0 /* Not needed because the disconnect waits for us. */ - unsigned long flags; - spin_lock_irqsave(&ub_lock, flags); - sc->openc++; - spin_unlock_irqrestore(&ub_lock, flags); -#endif - -#if 0 /* We let them stop themselves. */ - struct list_head *p; - struct ub_lun *lun; - list_for_each(p, &sc->luns) { - lun = list_entry(p, struct ub_lun, link); - blk_stop_queue(lun->disk->queue); - } -#endif - - schedule_work(&sc->reset_work); -} - -static void ub_reset_task(void *arg) -{ - struct ub_dev *sc = arg; - unsigned long flags; - struct list_head *p; - struct ub_lun *lun; - int lkr, rc; - - if (!sc->reset) { - printk(KERN_WARNING "%s: Running reset unrequested\n", - sc->name); - return; - } - - if (atomic_read(&sc->poison)) { - printk(KERN_NOTICE "%s: Not resetting disconnected device\n", - sc->name); /* P3 This floods. Remove soon. XXX */ - } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) { - printk(KERN_NOTICE "%s: Not resetting multi-interface device\n", - sc->name); /* P3 This floods. Remove soon. XXX */ - } else { - if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) { - printk(KERN_NOTICE - "%s: usb_lock_device_for_reset failed (%d)\n", - sc->name, lkr); - } else { - rc = usb_reset_device(sc->dev); - if (rc < 0) { - printk(KERN_NOTICE "%s: " - "usb_lock_device_for_reset failed (%d)\n", - sc->name, rc); - } - - if (lkr) - usb_unlock_device(sc->dev); - } - } - - /* - * In theory, no commands can be running while reset is active, - * so nobody can ask for another reset, and so we do not need any - * queues of resets or anything. We do need a spinlock though, - * to interact with block layer. - */ - spin_lock_irqsave(&sc->lock, flags); - sc->reset = 0; - tasklet_schedule(&sc->tasklet); - list_for_each(p, &sc->luns) { - lun = list_entry(p, struct ub_lun, link); - blk_start_queue(lun->disk->queue); - } - wake_up(&sc->reset_wait); - spin_unlock_irqrestore(&sc->lock, flags); -} - /* * This is called from a process context. */ @@ -2300,7 +2146,7 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, if (ep_in == NULL || ep_out == NULL) { printk(KERN_NOTICE "%s: failed endpoint check\n", sc->name); - return -ENODEV; + return -EIO; } /* Calculate and store the pipe values */ @@ -2326,9 +2172,6 @@ static int ub_probe(struct usb_interface *intf, int rc; int i; - if (usb_usual_check_type(dev_id, USB_US_TYPE_UB)) - return -ENXIO; - rc = -ENOMEM; if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) goto err_core; @@ -2338,8 +2181,6 @@ static int ub_probe(struct usb_interface *intf, usb_init_urb(&sc->work_urb); tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); atomic_set(&sc->poison, 0); - INIT_WORK(&sc->reset_work, ub_reset_task, sc); - init_waitqueue_head(&sc->reset_wait); init_timer(&sc->work_timer); sc->work_timer.data = (unsigned long) sc; @@ -2360,8 +2201,7 @@ static int ub_probe(struct usb_interface *intf, /* XXX Verify that we can handle the device (from descriptors) */ - if (ub_get_pipes(sc, sc->dev, intf) != 0) - goto err_dev_desc; + ub_get_pipes(sc, sc->dev, intf); if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0) goto err_diag; @@ -2432,7 +2272,6 @@ static int ub_probe(struct usb_interface *intf, /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */ err_diag: -err_dev_desc: usb_set_intfdata(intf, NULL); // usb_put_intf(sc->intf); usb_put_dev(sc->dev); @@ -2470,14 +2309,14 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) ub_revalidate(sc, lun); rc = -ENOMEM; - if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL) + if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL) goto err_diskalloc; lun->disk = disk; sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a'); sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a'); disk->major = UB_MAJOR; - disk->first_minor = lun->id * UB_PARTS_PER_LUN; + disk->first_minor = lun->id * UB_MINORS_PER_MAJOR; disk->fops = &ub_bd_fops; disk->private_data = lun; disk->driverfs_dev = &sc->intf->dev; @@ -2540,11 +2379,6 @@ static void ub_disconnect(struct usb_interface *intf) */ atomic_set(&sc->poison, 1); - /* - * Wait for reset to end, if any. - */ - wait_event(sc->reset_wait, !sc->reset); - /* * Blow away queued commands. * @@ -2558,7 +2392,7 @@ static void ub_disconnect(struct usb_interface *intf) { struct ub_scsi_cmd *cmd; int cnt = 0; - while ((cmd = ub_cmdq_peek(sc)) != NULL) { + while ((cmd = ub_cmdq_pop(sc)) != NULL) { cmd->error = -ENOTCONN; cmd->state = UB_CMDST_DONE; ub_cmdtr_state(sc, cmd); @@ -2627,6 +2461,7 @@ static void ub_disconnect(struct usb_interface *intf) } static struct usb_driver ub_driver = { + .owner = THIS_MODULE, .name = "ub", .probe = ub_probe, .disconnect = ub_disconnect, @@ -2644,7 +2479,6 @@ static int __init ub_init(void) if ((rc = usb_register(&ub_driver)) != 0) goto err_register; - usb_usual_set_present(USB_US_TYPE_UB); return 0; err_register: @@ -2660,7 +2494,6 @@ static void __exit ub_exit(void) devfs_remove(DEVFS_NAME); unregister_blkdev(UB_MAJOR, DRV_NAME); - usb_usual_clear_present(USB_US_TYPE_UB); } module_init(ub_init); diff --git a/trunk/drivers/bluetooth/bcm203x.c b/trunk/drivers/bluetooth/bcm203x.c index 3e7a067cc087..8e7fb3551775 100644 --- a/trunk/drivers/bluetooth/bcm203x.c +++ b/trunk/drivers/bluetooth/bcm203x.c @@ -275,6 +275,7 @@ static void bcm203x_disconnect(struct usb_interface *intf) } static struct usb_driver bcm203x_driver = { + .owner = THIS_MODULE, .name = "bcm203x", .probe = bcm203x_probe, .disconnect = bcm203x_disconnect, diff --git a/trunk/drivers/bluetooth/bfusb.c b/trunk/drivers/bluetooth/bfusb.c index 8947c8837dac..067e27893e4a 100644 --- a/trunk/drivers/bluetooth/bfusb.c +++ b/trunk/drivers/bluetooth/bfusb.c @@ -768,6 +768,7 @@ static void bfusb_disconnect(struct usb_interface *intf) } static struct usb_driver bfusb_driver = { + .owner = THIS_MODULE, .name = "bfusb", .probe = bfusb_probe, .disconnect = bfusb_disconnect, diff --git a/trunk/drivers/bluetooth/bpa10x.c b/trunk/drivers/bluetooth/bpa10x.c index 9446960ac742..394796315adc 100644 --- a/trunk/drivers/bluetooth/bpa10x.c +++ b/trunk/drivers/bluetooth/bpa10x.c @@ -619,6 +619,7 @@ static void bpa10x_disconnect(struct usb_interface *intf) } static struct usb_driver bpa10x_driver = { + .owner = THIS_MODULE, .name = "bpa10x", .probe = bpa10x_probe, .disconnect = bpa10x_disconnect, diff --git a/trunk/drivers/bluetooth/hci_usb.c b/trunk/drivers/bluetooth/hci_usb.c index 92382e823285..057cb2b6e6d1 100644 --- a/trunk/drivers/bluetooth/hci_usb.c +++ b/trunk/drivers/bluetooth/hci_usb.c @@ -1044,6 +1044,7 @@ static void hci_usb_disconnect(struct usb_interface *intf) } static struct usb_driver hci_usb_driver = { + .owner = THIS_MODULE, .name = "hci_usb", .probe = hci_usb_probe, .disconnect = hci_usb_disconnect, diff --git a/trunk/drivers/char/ip2/i2pack.h b/trunk/drivers/char/ip2/i2pack.h index 00342a677c90..e9b87a78622c 100644 --- a/trunk/drivers/char/ip2/i2pack.h +++ b/trunk/drivers/char/ip2/i2pack.h @@ -358,7 +358,7 @@ typedef struct _failStat #define MB_OUT_STRIPPED 0x40 // Board has read all output from fifo #define MB_FATAL_ERROR 0x20 // Board has encountered a fatal error -#pragma pack() // Reset padding to command-line default +#pragma pack(4) // Reset padding to command-line default #endif // I2PACK_H diff --git a/trunk/drivers/char/watchdog/pcwd_usb.c b/trunk/drivers/char/watchdog/pcwd_usb.c index 1533f56baa42..092e9b133750 100644 --- a/trunk/drivers/char/watchdog/pcwd_usb.c +++ b/trunk/drivers/char/watchdog/pcwd_usb.c @@ -151,6 +151,7 @@ static void usb_pcwd_disconnect (struct usb_interface *interface); /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver usb_pcwd_driver = { + .owner = THIS_MODULE, .name = DRIVER_NAME, .probe = usb_pcwd_probe, .disconnect = usb_pcwd_disconnect, diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index a9163d02983a..815902c2c856 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -822,30 +822,6 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne } -/** - * cpufreq_quick_get - get the CPU frequency (in kHz) frpm policy->cur - * @cpu: CPU number - * - * This is the last known freq, without actually getting it from the driver. - * Return value will be same as what is shown in scaling_cur_freq in sysfs. - */ -unsigned int cpufreq_quick_get(unsigned int cpu) -{ - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - unsigned int ret = 0; - - if (policy) { - down(&policy->lock); - ret = policy->cur; - up(&policy->lock); - cpufreq_cpu_put(policy); - } - - return (ret); -} -EXPORT_SYMBOL(cpufreq_quick_get); - - /** * cpufreq_get - get the current CPU frequency (in kHz) * @cpu: CPU number diff --git a/trunk/drivers/cpufreq/cpufreq_conservative.c b/trunk/drivers/cpufreq/cpufreq_conservative.c index 39543a2bed0f..2ed5c4363b53 100644 --- a/trunk/drivers/cpufreq/cpufreq_conservative.c +++ b/trunk/drivers/cpufreq/cpufreq_conservative.c @@ -93,7 +93,7 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu) { return kstat_cpu(cpu).cpustat.idle + kstat_cpu(cpu).cpustat.iowait + - ( dbs_tuners_ins.ignore_nice ? + ( !dbs_tuners_ins.ignore_nice ? kstat_cpu(cpu).cpustat.nice : 0); } @@ -127,7 +127,7 @@ show_one(sampling_rate, sampling_rate); show_one(sampling_down_factor, sampling_down_factor); show_one(up_threshold, up_threshold); show_one(down_threshold, down_threshold); -show_one(ignore_nice_load, ignore_nice); +show_one(ignore_nice, ignore_nice); show_one(freq_step, freq_step); static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, @@ -207,7 +207,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused, return count; } -static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, +static ssize_t store_ignore_nice(struct cpufreq_policy *policy, const char *buf, size_t count) { unsigned int input; @@ -272,7 +272,7 @@ define_one_rw(sampling_rate); define_one_rw(sampling_down_factor); define_one_rw(up_threshold); define_one_rw(down_threshold); -define_one_rw(ignore_nice_load); +define_one_rw(ignore_nice); define_one_rw(freq_step); static struct attribute * dbs_attributes[] = { @@ -282,7 +282,7 @@ static struct attribute * dbs_attributes[] = { &sampling_down_factor.attr, &up_threshold.attr, &down_threshold.attr, - &ignore_nice_load.attr, + &ignore_nice.attr, &freq_step.attr, NULL }; diff --git a/trunk/drivers/cpufreq/cpufreq_ondemand.c b/trunk/drivers/cpufreq/cpufreq_ondemand.c index e69fd8dd1f1c..17741111246b 100644 --- a/trunk/drivers/cpufreq/cpufreq_ondemand.c +++ b/trunk/drivers/cpufreq/cpufreq_ondemand.c @@ -89,7 +89,7 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu) { return kstat_cpu(cpu).cpustat.idle + kstat_cpu(cpu).cpustat.iowait + - ( dbs_tuners_ins.ignore_nice ? + ( !dbs_tuners_ins.ignore_nice ? kstat_cpu(cpu).cpustat.nice : 0); } @@ -122,7 +122,7 @@ static ssize_t show_##file_name \ show_one(sampling_rate, sampling_rate); show_one(sampling_down_factor, sampling_down_factor); show_one(up_threshold, up_threshold); -show_one(ignore_nice_load, ignore_nice); +show_one(ignore_nice, ignore_nice); static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, const char *buf, size_t count) @@ -182,7 +182,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, return count; } -static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, +static ssize_t store_ignore_nice(struct cpufreq_policy *policy, const char *buf, size_t count) { unsigned int input; @@ -223,7 +223,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name) define_one_rw(sampling_rate); define_one_rw(sampling_down_factor); define_one_rw(up_threshold); -define_one_rw(ignore_nice_load); +define_one_rw(ignore_nice); static struct attribute * dbs_attributes[] = { &sampling_rate_max.attr, @@ -231,7 +231,7 @@ static struct attribute * dbs_attributes[] = { &sampling_rate.attr, &sampling_down_factor.attr, &up_threshold.attr, - &ignore_nice_load.attr, + &ignore_nice.attr, NULL }; diff --git a/trunk/drivers/input/joystick/iforce/iforce-usb.c b/trunk/drivers/input/joystick/iforce/iforce-usb.c index bc2fce60f9f8..64b4a3080985 100644 --- a/trunk/drivers/input/joystick/iforce/iforce-usb.c +++ b/trunk/drivers/input/joystick/iforce/iforce-usb.c @@ -235,6 +235,7 @@ static struct usb_device_id iforce_usb_ids [] = { MODULE_DEVICE_TABLE (usb, iforce_usb_ids); struct usb_driver iforce_usb_driver = { + .owner = THIS_MODULE, .name = "iforce", .probe = iforce_usb_probe, .disconnect = iforce_usb_disconnect, diff --git a/trunk/drivers/isdn/hisax/hfc_usb.c b/trunk/drivers/isdn/hisax/hfc_usb.c index ca5b4a3b683e..f8457ef48826 100644 --- a/trunk/drivers/isdn/hisax/hfc_usb.c +++ b/trunk/drivers/isdn/hisax/hfc_usb.c @@ -1715,6 +1715,7 @@ hfc_usb_disconnect(struct usb_interface /* our driver information structure */ /************************************/ static struct usb_driver hfc_drv = { + .owner = THIS_MODULE, .name = "hfc_usb", .id_table = hfcusb_idtab, .probe = hfc_usb_probe, diff --git a/trunk/drivers/isdn/hisax/st5481_init.c b/trunk/drivers/isdn/hisax/st5481_init.c index 99cb0f3d59a1..8e192a3a3490 100644 --- a/trunk/drivers/isdn/hisax/st5481_init.c +++ b/trunk/drivers/isdn/hisax/st5481_init.c @@ -180,6 +180,7 @@ static struct usb_device_id st5481_ids[] = { MODULE_DEVICE_TABLE (usb, st5481_ids); static struct usb_driver st5481_usb_driver = { + .owner = THIS_MODULE, .name = "st5481_usb", .probe = probe_st5481, .disconnect = disconnect_st5481, diff --git a/trunk/drivers/media/dvb/b2c2/flexcop-usb.c b/trunk/drivers/media/dvb/b2c2/flexcop-usb.c index a6c91db40ad6..0a78ba3737a5 100644 --- a/trunk/drivers/media/dvb/b2c2/flexcop-usb.c +++ b/trunk/drivers/media/dvb/b2c2/flexcop-usb.c @@ -544,6 +544,7 @@ static struct usb_device_id flexcop_usb_table [] = { /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver flexcop_usb_driver = { + .owner = THIS_MODULE, .name = "b2c2_flexcop_usb", .probe = flexcop_usb_probe, .disconnect = flexcop_usb_disconnect, diff --git a/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c b/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c index b996fb59b7e4..336fc284fa52 100644 --- a/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -986,6 +986,7 @@ static const struct usb_device_id cinergyt2_table [] __devinitdata = { MODULE_DEVICE_TABLE(usb, cinergyt2_table); static struct usb_driver cinergyt2_driver = { + .owner = THIS_MODULE, .name = "cinergyT2", .probe = cinergyt2_probe, .disconnect = cinergyt2_disconnect, diff --git a/trunk/drivers/media/dvb/dvb-usb/a800.c b/trunk/drivers/media/dvb/dvb-usb/a800.c index ce44aa6bbb83..8c7beffb045f 100644 --- a/trunk/drivers/media/dvb/dvb-usb/a800.c +++ b/trunk/drivers/media/dvb/dvb-usb/a800.c @@ -144,6 +144,7 @@ static struct dvb_usb_properties a800_properties = { }; static struct usb_driver a800_driver = { + .owner = THIS_MODULE, .name = "dvb_usb_a800", .probe = a800_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/dvb/dvb-usb/cxusb.c b/trunk/drivers/media/dvb/dvb-usb/cxusb.c index d05fab01cccd..3fe383f4bb4c 100644 --- a/trunk/drivers/media/dvb/dvb-usb/cxusb.c +++ b/trunk/drivers/media/dvb/dvb-usb/cxusb.c @@ -241,6 +241,7 @@ static struct dvb_usb_properties cxusb_properties = { }; static struct usb_driver cxusb_driver = { + .owner = THIS_MODULE, .name = "dvb_usb_cxusb", .probe = cxusb_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c b/trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c index 52ac3e5adf5d..aa271a2496d5 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -373,6 +373,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = { }; static struct usb_driver dibusb_driver = { + .owner = THIS_MODULE, .name = "dvb_usb_dibusb_mb", .probe = dibusb_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c b/trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c index 55802fba3c29..6a0912eab396 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -82,6 +82,7 @@ static struct dvb_usb_properties dibusb_mc_properties = { }; static struct usb_driver dibusb_mc_driver = { + .owner = THIS_MODULE, .name = "dvb_usb_dibusb_mc", .probe = dibusb_mc_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/dvb/dvb-usb/digitv.c b/trunk/drivers/media/dvb/dvb-usb/digitv.c index 450417a9e64b..f98e306a5759 100644 --- a/trunk/drivers/media/dvb/dvb-usb/digitv.c +++ b/trunk/drivers/media/dvb/dvb-usb/digitv.c @@ -233,6 +233,7 @@ static struct dvb_usb_properties digitv_properties = { }; static struct usb_driver digitv_driver = { + .owner = THIS_MODULE, .name = "dvb_usb_digitv", .probe = digitv_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/dvb/dvb-usb/dtt200u.c b/trunk/drivers/media/dvb/dvb-usb/dtt200u.c index 6e2bac873445..b595476332cd 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/trunk/drivers/media/dvb/dvb-usb/dtt200u.c @@ -198,6 +198,7 @@ static struct dvb_usb_properties wt220u_properties = { /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver dtt200u_usb_driver = { + .owner = THIS_MODULE, .name = "dvb_usb_dtt200u", .probe = dtt200u_usb_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c index fac48fc7a4ac..1841a66427bf 100644 --- a/trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c @@ -202,6 +202,7 @@ static struct dvb_usb_properties nova_t_properties = { }; static struct usb_driver nova_t_driver = { + .owner = THIS_MODULE, .name = "dvb_usb_nova_t_usb2", .probe = nova_t_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/dvb/dvb-usb/umt-010.c b/trunk/drivers/media/dvb/dvb-usb/umt-010.c index 14f1911c79bb..6fd67657c269 100644 --- a/trunk/drivers/media/dvb/dvb-usb/umt-010.c +++ b/trunk/drivers/media/dvb/dvb-usb/umt-010.c @@ -128,6 +128,7 @@ static struct dvb_usb_properties umt_properties = { }; static struct usb_driver umt_driver = { + .owner = THIS_MODULE, .name = "dvb_usb_umt_010", .probe = umt_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/dvb/dvb-usb/vp702x.c b/trunk/drivers/media/dvb/dvb-usb/vp702x.c index afa00fdb5ec0..de13c04e8e64 100644 --- a/trunk/drivers/media/dvb/dvb-usb/vp702x.c +++ b/trunk/drivers/media/dvb/dvb-usb/vp702x.c @@ -256,6 +256,7 @@ static struct dvb_usb_properties vp702x_properties = { /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver vp702x_usb_driver = { + .owner = THIS_MODULE, .name = "dvb-usb-vp702x", .probe = vp702x_usb_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/dvb/dvb-usb/vp7045.c b/trunk/drivers/media/dvb/dvb-usb/vp7045.c index 3835235b68df..75765e3a569c 100644 --- a/trunk/drivers/media/dvb/dvb-usb/vp7045.c +++ b/trunk/drivers/media/dvb/dvb-usb/vp7045.c @@ -253,6 +253,7 @@ static struct dvb_usb_properties vp7045_properties = { /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver vp7045_usb_driver = { + .owner = THIS_MODULE, .name = "dvb_usb_vp7045", .probe = vp7045_usb_probe, .disconnect = dvb_usb_device_exit, diff --git a/trunk/drivers/media/video/cpia_usb.c b/trunk/drivers/media/video/cpia_usb.c index 1439cb752874..9774e94d1e7d 100644 --- a/trunk/drivers/media/video/cpia_usb.c +++ b/trunk/drivers/media/video/cpia_usb.c @@ -582,6 +582,7 @@ MODULE_LICENSE("GPL"); static struct usb_driver cpia_driver = { + .owner = THIS_MODULE, .name = "cpia", .probe = cpia_probe, .disconnect = cpia_disconnect, diff --git a/trunk/drivers/media/video/em28xx/em28xx-video.c b/trunk/drivers/media/video/em28xx/em28xx-video.c index 3a56120397ae..06d76879bde2 100644 --- a/trunk/drivers/media/video/em28xx/em28xx-video.c +++ b/trunk/drivers/media/video/em28xx/em28xx-video.c @@ -1884,6 +1884,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) } static struct usb_driver em28xx_usb_driver = { + .owner = THIS_MODULE, .name = "em28xx", .probe = em28xx_usb_probe, .disconnect = em28xx_usb_disconnect, diff --git a/trunk/drivers/net/irda/irda-usb.c b/trunk/drivers/net/irda/irda-usb.c index fa176ffb4ad5..c22c0517883c 100644 --- a/trunk/drivers/net/irda/irda-usb.c +++ b/trunk/drivers/net/irda/irda-usb.c @@ -1539,6 +1539,7 @@ static void irda_usb_disconnect(struct usb_interface *intf) * USB device callbacks */ static struct usb_driver irda_driver = { + .owner = THIS_MODULE, .name = "irda-usb", .probe = irda_usb_probe, .disconnect = irda_usb_disconnect, diff --git a/trunk/drivers/net/irda/stir4200.c b/trunk/drivers/net/irda/stir4200.c index 31867e4b891b..3961a754e920 100644 --- a/trunk/drivers/net/irda/stir4200.c +++ b/trunk/drivers/net/irda/stir4200.c @@ -1152,6 +1152,7 @@ static int stir_resume(struct usb_interface *intf) * USB device callbacks */ static struct usb_driver irda_driver = { + .owner = THIS_MODULE, .name = "stir4200", .probe = stir_probe, .disconnect = stir_disconnect, diff --git a/trunk/drivers/usb/Makefile b/trunk/drivers/usb/Makefile index 3639c3f8d357..a50c2bc506f2 100644 --- a/trunk/drivers/usb/Makefile +++ b/trunk/drivers/usb/Makefile @@ -22,7 +22,6 @@ obj-$(CONFIG_USB_MIDI) += class/ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ -obj-$(CONFIG_USB) += storage/ obj-$(CONFIG_USB_AIPTEK) += input/ obj-$(CONFIG_USB_ATI_REMOTE) += input/ diff --git a/trunk/drivers/usb/atm/Kconfig b/trunk/drivers/usb/atm/Kconfig index 550ddfa71a43..f429862e0974 100644 --- a/trunk/drivers/usb/atm/Kconfig +++ b/trunk/drivers/usb/atm/Kconfig @@ -44,19 +44,6 @@ config USB_CXACRU To compile this driver as a module, choose M here: the module will be called cxacru. -config USB_UEAGLEATM - tristate "ADI 930 and eagle USB DSL modem" - depends on USB_ATM - select FW_LOADER - help - Say Y here if you have an ADSL USB modem based on the ADI 930 - or eagle chipset. In order to use your modem you will need to - install firmwares and CMV (Command Management Variables); see - for details. - - To compile this driver as a module, choose M here: the - module will be called ueagle-atm. - config USB_XUSBATM tristate "Other USB DSL modem support" depends on USB_ATM diff --git a/trunk/drivers/usb/atm/Makefile b/trunk/drivers/usb/atm/Makefile index 4c4a776ab1cd..85099718c683 100644 --- a/trunk/drivers/usb/atm/Makefile +++ b/trunk/drivers/usb/atm/Makefile @@ -4,7 +4,6 @@ obj-$(CONFIG_USB_CXACRU) += cxacru.o obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o -obj-$(CONFIG_USB_UEAGLEATM) += ueagle-atm.o obj-$(CONFIG_USB_ATM) += usbatm.o obj-$(CONFIG_USB_XUSBATM) += xusbatm.o diff --git a/trunk/drivers/usb/atm/cxacru.c b/trunk/drivers/usb/atm/cxacru.c index af0a41e7870e..9d59dc62e6d2 100644 --- a/trunk/drivers/usb/atm/cxacru.c +++ b/trunk/drivers/usb/atm/cxacru.c @@ -853,6 +853,7 @@ static int cxacru_usb_probe(struct usb_interface *intf, const struct usb_device_ } static struct usb_driver cxacru_usb_driver = { + .owner = THIS_MODULE, .name = cxacru_driver_name, .probe = cxacru_usb_probe, .disconnect = usbatm_usb_disconnect, diff --git a/trunk/drivers/usb/atm/speedtch.c b/trunk/drivers/usb/atm/speedtch.c index b28336148658..d0cbbb7f0385 100644 --- a/trunk/drivers/usb/atm/speedtch.c +++ b/trunk/drivers/usb/atm/speedtch.c @@ -659,6 +659,7 @@ MODULE_DEVICE_TABLE(usb, speedtch_usb_ids); static int speedtch_usb_probe(struct usb_interface *, const struct usb_device_id *); static struct usb_driver speedtch_usb_driver = { + .owner = THIS_MODULE, .name = speedtch_driver_name, .probe = speedtch_usb_probe, .disconnect = usbatm_usb_disconnect, diff --git a/trunk/drivers/usb/atm/ueagle-atm.c b/trunk/drivers/usb/atm/ueagle-atm.c deleted file mode 100644 index 7d2a679989ed..000000000000 --- a/trunk/drivers/usb/atm/ueagle-atm.c +++ /dev/null @@ -1,1820 +0,0 @@ -/*- - * Copyright (c) 2003, 2004 - * Damien Bergamini . All rights reserved. - * - * Copyright (c) 2005 Matthieu Castet - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * BSD license below: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * GPL license : - * 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. - * - * - * HISTORY : some part of the code was base on ueagle 1.3 BSD driver, - * Damien Bergamini agree to put his code under a DUAL GPL/BSD license. - * - * The rest of the code was was rewritten from scratch. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "usbatm.h" - -#define EAGLEUSBVERSION "ueagle 1.1" - - -/* - * Debug macros - */ -#define uea_dbg(usb_dev, format, args...) \ - do { \ - if (debug >= 1) \ - dev_dbg(&(usb_dev)->dev, \ - "[ueagle-atm dbg] %s: " format, \ - __FUNCTION__, ##args); \ - } while (0) - -#define uea_vdbg(usb_dev, format, args...) \ - do { \ - if (debug >= 2) \ - dev_dbg(&(usb_dev)->dev, \ - "[ueagle-atm vdbg] " format, ##args); \ - } while (0) - -#define uea_enters(usb_dev) \ - uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__) - -#define uea_leaves(usb_dev) \ - uea_vdbg(usb_dev, "leaving %s\n", __FUNCTION__) - -#define uea_err(usb_dev, format,args...) \ - dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args) - -#define uea_warn(usb_dev, format,args...) \ - dev_warn(&(usb_dev)->dev ,"[Ueagle-atm] " format, ##args) - -#define uea_info(usb_dev, format,args...) \ - dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args) - -struct uea_cmvs { - u32 address; - u16 offset; - u32 data; -} __attribute__ ((packed)); - -struct uea_softc { - struct usb_device *usb_dev; - struct usbatm_data *usbatm; - - int modem_index; - unsigned int driver_info; - - int booting; - int reset; - - wait_queue_head_t sync_q; - - struct task_struct *kthread; - u32 data; - wait_queue_head_t cmv_ack_wait; - int cmv_ack; - - struct work_struct task; - u16 pageno; - u16 ovl; - - const struct firmware *dsp_firm; - struct urb *urb_int; - - u8 cmv_function; - u16 cmv_idx; - u32 cmv_address; - u16 cmv_offset; - - /* keep in sync with eaglectl */ - struct uea_stats { - struct { - u32 state; - u32 flags; - u32 mflags; - u32 vidcpe; - u32 vidco; - u32 dsrate; - u32 usrate; - u32 dsunc; - u32 usunc; - u32 dscorr; - u32 uscorr; - u32 txflow; - u32 rxflow; - u32 usattenuation; - u32 dsattenuation; - u32 dsmargin; - u32 usmargin; - u32 firmid; - } phy; - } stats; -}; - -/* - * Elsa IDs - */ -#define ELSA_VID 0x05CC -#define ELSA_PID_PSTFIRM 0x3350 -#define ELSA_PID_PREFIRM 0x3351 - -/* - * Sagem USB IDs - */ -#define EAGLE_VID 0x1110 -#define EAGLE_I_PID_PREFIRM 0x9010 /* Eagle I */ -#define EAGLE_I_PID_PSTFIRM 0x900F /* Eagle I */ - -#define EAGLE_IIC_PID_PREFIRM 0x9024 /* Eagle IIC */ -#define EAGLE_IIC_PID_PSTFIRM 0x9023 /* Eagle IIC */ - -#define EAGLE_II_PID_PREFIRM 0x9022 /* Eagle II */ -#define EAGLE_II_PID_PSTFIRM 0x9021 /* Eagle II */ - -/* - * Eagle III Pid - */ -#define EAGLE_III_PID_PREFIRM 0x9032 /* Eagle III */ -#define EAGLE_III_PID_PSTFIRM 0x9031 /* Eagle III */ - -/* - * USR USB IDs - */ -#define USR_VID 0x0BAF -#define MILLER_A_PID_PREFIRM 0x00F2 -#define MILLER_A_PID_PSTFIRM 0x00F1 -#define MILLER_B_PID_PREFIRM 0x00FA -#define MILLER_B_PID_PSTFIRM 0x00F9 -#define HEINEKEN_A_PID_PREFIRM 0x00F6 -#define HEINEKEN_A_PID_PSTFIRM 0x00F5 -#define HEINEKEN_B_PID_PREFIRM 0x00F8 -#define HEINEKEN_B_PID_PSTFIRM 0x00F7 - -#define PREFIRM 0 -#define PSTFIRM (1<<7) -enum { - ADI930 = 0, - EAGLE_I, - EAGLE_II, - EAGLE_III -}; - -/* macros for both struct usb_device_id and struct uea_softc */ -#define UEA_IS_PREFIRM(x) \ - (!((x)->driver_info & PSTFIRM)) -#define UEA_CHIP_VERSION(x) \ - ((x)->driver_info & 0xf) - -#define IS_ISDN(sc) \ - (le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80) - -#define INS_TO_USBDEV(ins) ins->usb_dev - -#define GET_STATUS(data) \ - ((data >> 8) & 0xf) -#define IS_OPERATIONAL(sc) \ - (GET_STATUS(sc->stats.phy.state) == 2) - -/* - * Set of macros to handle unaligned data in the firmware blob. - * The FW_GET_BYTE() macro is provided only for consistency. - */ - -#define FW_GET_BYTE(p) *((__u8 *) (p)) -#define FW_GET_WORD(p) le16_to_cpu(get_unaligned((__le16 *) (p))) -#define FW_GET_LONG(p) le32_to_cpu(get_unaligned((__le32 *) (p))) - -#define FW_DIR "ueagle-atm/" -#define NB_MODEM 4 - -#define BULK_TIMEOUT 300 -#define CTRL_TIMEOUT 1000 - -#define ACK_TIMEOUT msecs_to_jiffies(1500) - -#define UEA_INTR_IFACE_NO 0 -#define UEA_US_IFACE_NO 1 -#define UEA_DS_IFACE_NO 2 - -#define FASTEST_ISO_INTF 8 - -#define UEA_BULK_DATA_PIPE 0x02 -#define UEA_IDMA_PIPE 0x04 -#define UEA_INTR_PIPE 0x04 -#define UEA_ISO_DATA_PIPE 0x08 - -#define UEA_SET_BLOCK 0x0001 -#define UEA_SET_MODE 0x0003 -#define UEA_SET_2183_DATA 0x0004 -#define UEA_SET_TIMEOUT 0x0011 - -#define UEA_LOOPBACK_OFF 0x0002 -#define UEA_LOOPBACK_ON 0x0003 -#define UEA_BOOT_IDMA 0x0006 -#define UEA_START_RESET 0x0007 -#define UEA_END_RESET 0x0008 - -#define UEA_SWAP_MAILBOX (0x3fcd | 0x4000) -#define UEA_MPTX_START (0x3fce | 0x4000) -#define UEA_MPTX_MAILBOX (0x3fd6 | 0x4000) -#define UEA_MPRX_MAILBOX (0x3fdf | 0x4000) - -/* structure describing a block within a DSP page */ -struct block_info { - __le16 wHdr; -#define UEA_BIHDR 0xabcd - __le16 wAddress; - __le16 wSize; - __le16 wOvlOffset; - __le16 wOvl; /* overlay */ - __le16 wLast; -} __attribute__ ((packed)); -#define BLOCK_INFO_SIZE 12 - -/* structure representing a CMV (Configuration and Management Variable) */ -struct cmv { - __le16 wPreamble; -#define PREAMBLE 0x535c - __u8 bDirection; -#define MODEMTOHOST 0x01 -#define HOSTTOMODEM 0x10 - __u8 bFunction; -#define FUNCTION_TYPE(f) ((f) >> 4) -#define MEMACCESS 0x1 -#define ADSLDIRECTIVE 0x7 - -#define FUNCTION_SUBTYPE(f) ((f) & 0x0f) -/* for MEMACCESS */ -#define REQUESTREAD 0x0 -#define REQUESTWRITE 0x1 -#define REPLYREAD 0x2 -#define REPLYWRITE 0x3 -/* for ADSLDIRECTIVE */ -#define KERNELREADY 0x0 -#define MODEMREADY 0x1 - -#define MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf)) - __le16 wIndex; - __le32 dwSymbolicAddress; -#define MAKESA(a, b, c, d) \ - (((c) & 0xff) << 24 | \ - ((d) & 0xff) << 16 | \ - ((a) & 0xff) << 8 | \ - ((b) & 0xff)) - -#define SA_CNTL MAKESA('C', 'N', 'T', 'L') -#define SA_DIAG MAKESA('D', 'I', 'A', 'G') -#define SA_INFO MAKESA('I', 'N', 'F', 'O') -#define SA_OPTN MAKESA('O', 'P', 'T', 'N') -#define SA_RATE MAKESA('R', 'A', 'T', 'E') -#define SA_STAT MAKESA('S', 'T', 'A', 'T') - __le16 wOffsetAddress; - __le32 dwData; -} __attribute__ ((packed)); -#define CMV_SIZE 16 - -/* structure representing swap information */ -struct swap_info { - __u8 bSwapPageNo; - __u8 bOvl; /* overlay */ -} __attribute__ ((packed)); - -/* structure representing interrupt data */ -struct intr_pkt { - __u8 bType; - __u8 bNotification; - __le16 wValue; - __le16 wIndex; - __le16 wLength; - __le16 wInterrupt; -#define INT_LOADSWAPPAGE 0x0001 -#define INT_INCOMINGCMV 0x0002 - union { - struct { - struct swap_info swapinfo; - __le16 wDataSize; - } __attribute__ ((packed)) s1; - - struct { - struct cmv cmv; - __le16 wDataSize; - } __attribute__ ((packed)) s2; - } __attribute__ ((packed)) u; -#define bSwapPageNo u.s1.swapinfo.bSwapPageNo -#define bOvl u.s1.swapinfo.bOvl -} __attribute__ ((packed)); -#define INTR_PKT_SIZE 28 - -static struct usb_driver uea_driver; -static DECLARE_MUTEX(uea_semaphore); -static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"}; - -static int modem_index; -static unsigned int debug; -static int sync_wait[NB_MODEM]; -static char *cmv_file[NB_MODEM]; - -module_param(debug, uint, 0644); -MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)"); -module_param_array(sync_wait, bool, NULL, 0644); -MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM"); -module_param_array(cmv_file, charp, NULL, 0644); -MODULE_PARM_DESC(cmv_file, - "file name with configuration and management variables"); - -#define UPDATE_ATM_STAT(type, val) \ - do { \ - if (sc->usbatm->atm_dev) \ - sc->usbatm->atm_dev->type = val; \ - } while (0) - -/* Firmware loading */ -#define LOAD_INTERNAL 0xA0 -#define F8051_USBCS 0x7f92 - -/** - * uea_send_modem_cmd - Send a command for pre-firmware devices. - */ -static int uea_send_modem_cmd(struct usb_device *usb, - u16 addr, u16 size, u8 * buff) -{ - int ret = -ENOMEM; - u8 *xfer_buff; - - xfer_buff = kmalloc(size, GFP_KERNEL); - if (xfer_buff) { - memcpy(xfer_buff, buff, size); - ret = usb_control_msg(usb, - usb_sndctrlpipe(usb, 0), - LOAD_INTERNAL, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, addr, 0, xfer_buff, - size, CTRL_TIMEOUT); - kfree(xfer_buff); - } - - if (ret < 0) - return ret; - - return (ret == size) ? 0 : -EIO; -} - -static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *context) -{ - struct usb_device *usb = context; - u8 *pfw, value; - u32 crc = 0; - int ret, size; - - uea_enters(usb); - if (!fw_entry) { - uea_err(usb, "firmware is not available\n"); - goto err; - } - - pfw = fw_entry->data; - size = fw_entry->size; - if (size < 4) - goto err_fw_corrupted; - - crc = FW_GET_LONG(pfw); - pfw += 4; - size -= 4; - if (crc32_be(0, pfw, size) != crc) - goto err_fw_corrupted; - - /* - * Start to upload formware : send reset - */ - value = 1; - ret = uea_send_modem_cmd(usb, F8051_USBCS, sizeof(value), &value); - - if (ret < 0) { - uea_err(usb, "modem reset failed with error %d\n", ret); - goto err; - } - - while (size > 3) { - u8 len = FW_GET_BYTE(pfw); - u16 add = FW_GET_WORD(pfw + 1); - - size -= len + 3; - if (size < 0) - goto err_fw_corrupted; - - ret = uea_send_modem_cmd(usb, add, len, pfw + 3); - if (ret < 0) { - uea_err(usb, "uploading firmware data failed " - "with error %d\n", ret); - goto err; - } - pfw += len + 3; - } - - if (size != 0) - goto err_fw_corrupted; - - /* - * Tell the modem we finish : de-assert reset - */ - value = 0; - ret = uea_send_modem_cmd(usb, F8051_USBCS, 1, &value); - if (ret < 0) - uea_err(usb, "modem de-assert failed with error %d\n", ret); - else - uea_info(usb, "firmware uploaded\n"); - - uea_leaves(usb); - return; - -err_fw_corrupted: - uea_err(usb, "firmware is corrupted\n"); -err: - uea_leaves(usb); -} - -/** - * uea_load_firmware - Load usb firmware for pre-firmware devices. - */ -static int uea_load_firmware(struct usb_device *usb, unsigned int ver) -{ - int ret; - char *fw_name = FW_DIR "eagle.fw"; - - uea_enters(usb); - uea_info(usb, "pre-firmware device, uploading firmware\n"); - - switch (ver) { - case ADI930: - fw_name = FW_DIR "adi930.fw"; - break; - case EAGLE_I: - fw_name = FW_DIR "eagleI.fw"; - break; - case EAGLE_II: - fw_name = FW_DIR "eagleII.fw"; - break; - case EAGLE_III: - fw_name = FW_DIR "eagleIII.fw"; - break; - } - - ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware); - if (ret) - uea_err(usb, "firmware %s is not available\n", fw_name); - else - uea_info(usb, "loading firmware %s\n", fw_name); - - uea_leaves(usb); - return ret; -} - -/* modem management : dsp firmware, send/read CMV, monitoring statistic - */ - -/* - * Make sure that the DSP code provided is safe to use. - */ -static int check_dsp(u8 *dsp, unsigned int len) -{ - u8 pagecount, blockcount; - u16 blocksize; - u32 pageoffset; - unsigned int i, j, p, pp; - - pagecount = FW_GET_BYTE(dsp); - p = 1; - - /* enough space for page offsets? */ - if (p + 4 * pagecount > len) - return 1; - - for (i = 0; i < pagecount; i++) { - - pageoffset = FW_GET_LONG(dsp + p); - p += 4; - - if (pageoffset == 0) - continue; - - /* enough space for blockcount? */ - if (pageoffset >= len) - return 1; - - pp = pageoffset; - blockcount = FW_GET_BYTE(dsp + pp); - pp += 1; - - for (j = 0; j < blockcount; j++) { - - /* enough space for block header? */ - if (pp + 4 > len) - return 1; - - pp += 2; /* skip blockaddr */ - blocksize = FW_GET_WORD(dsp + pp); - pp += 2; - - /* enough space for block data? */ - if (pp + blocksize > len) - return 1; - - pp += blocksize; - } - } - - return 0; -} - -/* - * send data to the idma pipe - * */ -static int uea_idma_write(struct uea_softc *sc, void *data, u32 size) -{ - int ret = -ENOMEM; - u8 *xfer_buff; - int bytes_read; - - xfer_buff = kmalloc(size, GFP_KERNEL); - if (!xfer_buff) { - uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n"); - return ret; - } - - memcpy(xfer_buff, data, size); - - ret = usb_bulk_msg(sc->usb_dev, - usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE), - xfer_buff, size, &bytes_read, BULK_TIMEOUT); - - kfree(xfer_buff); - if (ret < 0) - return ret; - if (size != bytes_read) { - uea_err(INS_TO_USBDEV(sc), "size != bytes_read %d %d\n", size, - bytes_read); - return -EIO; - } - - return 0; -} - -static int request_dsp(struct uea_softc *sc) -{ - int ret; - char *dsp_name; - - if (UEA_CHIP_VERSION(sc) == ADI930) { - if (IS_ISDN(sc)) - dsp_name = FW_DIR "DSP9i.bin"; - else - dsp_name = FW_DIR "DSP9p.bin"; - } else { - if (IS_ISDN(sc)) - dsp_name = FW_DIR "DSPei.bin"; - else - dsp_name = FW_DIR "DSPep.bin"; - } - - ret = request_firmware(&sc->dsp_firm, - dsp_name, &sc->usb_dev->dev); - if (ret < 0) { - uea_err(INS_TO_USBDEV(sc), - "requesting firmware %s failed with error %d\n", - dsp_name, ret); - return ret; - } - - if (check_dsp(sc->dsp_firm->data, sc->dsp_firm->size)) { - uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", - dsp_name); - release_firmware(sc->dsp_firm); - sc->dsp_firm = NULL; - return -EILSEQ; - } - - return 0; -} - -/* - * The uea_load_page() function must be called within a process context - */ -static void uea_load_page(void *xsc) -{ - struct uea_softc *sc = xsc; - u16 pageno = sc->pageno; - u16 ovl = sc->ovl; - struct block_info bi; - - u8 *p; - u8 pagecount, blockcount; - u16 blockaddr, blocksize; - u32 pageoffset; - int i; - - /* reload firmware when reboot start and it's loaded already */ - if (ovl == 0 && pageno == 0 && sc->dsp_firm) { - release_firmware(sc->dsp_firm); - sc->dsp_firm = NULL; - } - - if (sc->dsp_firm == NULL && request_dsp(sc) < 0) - return; - - p = sc->dsp_firm->data; - pagecount = FW_GET_BYTE(p); - p += 1; - - if (pageno >= pagecount) - goto bad1; - - p += 4 * pageno; - pageoffset = FW_GET_LONG(p); - - if (pageoffset == 0) - goto bad1; - - p = sc->dsp_firm->data + pageoffset; - blockcount = FW_GET_BYTE(p); - p += 1; - - uea_dbg(INS_TO_USBDEV(sc), - "sending %u blocks for DSP page %u\n", blockcount, pageno); - - bi.wHdr = cpu_to_le16(UEA_BIHDR); - bi.wOvl = cpu_to_le16(ovl); - bi.wOvlOffset = cpu_to_le16(ovl | 0x8000); - - for (i = 0; i < blockcount; i++) { - blockaddr = FW_GET_WORD(p); - p += 2; - - blocksize = FW_GET_WORD(p); - p += 2; - - bi.wSize = cpu_to_le16(blocksize); - bi.wAddress = cpu_to_le16(blockaddr); - bi.wLast = cpu_to_le16((i == blockcount - 1) ? 1 : 0); - - /* send block info through the IDMA pipe */ - if (uea_idma_write(sc, &bi, BLOCK_INFO_SIZE)) - goto bad2; - - /* send block data through the IDMA pipe */ - if (uea_idma_write(sc, p, blocksize)) - goto bad2; - - p += blocksize; - } - - return; - -bad2: - uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", i); - return; -bad1: - uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n",pageno); -} - -static inline void wake_up_cmv_ack(struct uea_softc *sc) -{ - sc->cmv_ack = 1; - wake_up(&sc->cmv_ack_wait); -} - -static inline int wait_cmv_ack(struct uea_softc *sc) -{ - int ret = wait_event_timeout(sc->cmv_ack_wait, - sc->cmv_ack, ACK_TIMEOUT); - sc->cmv_ack = 0; - - if (ret < 0) - return ret; - - return (ret == 0) ? -ETIMEDOUT : 0; - -} - -#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00 - -static int uea_request(struct uea_softc *sc, - u16 value, u16 index, u16 size, void *data) -{ - u8 *xfer_buff; - int ret = -ENOMEM; - - xfer_buff = kmalloc(size, GFP_KERNEL); - if (!xfer_buff) { - uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n"); - return ret; - } - memcpy(xfer_buff, data, size); - - ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0), - UCDC_SEND_ENCAPSULATED_COMMAND, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, xfer_buff, size, CTRL_TIMEOUT); - - kfree(xfer_buff); - if (ret < 0) { - uea_err(INS_TO_USBDEV(sc), "usb_control_msg error %d\n", ret); - return ret; - } - - if (ret != size) { - uea_err(INS_TO_USBDEV(sc), - "usb_control_msg send only %d bytes (instead of %d)\n", - ret, size); - return -EIO; - } - - return 0; -} - -static int uea_cmv(struct uea_softc *sc, - u8 function, u32 address, u16 offset, u32 data) -{ - struct cmv cmv; - int ret; - - /* we send a request, but we expect a reply */ - sc->cmv_function = function | 0x2; - sc->cmv_idx++; - sc->cmv_address = address; - sc->cmv_offset = offset; - - cmv.wPreamble = cpu_to_le16(PREAMBLE); - cmv.bDirection = HOSTTOMODEM; - cmv.bFunction = function; - cmv.wIndex = cpu_to_le16(sc->cmv_idx); - put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress); - cmv.wOffsetAddress = cpu_to_le16(offset); - put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData); - - ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv); - if (ret < 0) - return ret; - return wait_cmv_ack(sc); -} - -static inline int uea_read_cmv(struct uea_softc *sc, - u32 address, u16 offset, u32 *data) -{ - int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTREAD), - address, offset, 0); - if (ret < 0) - uea_err(INS_TO_USBDEV(sc), - "reading cmv failed with error %d\n", ret); - else - *data = sc->data; - - return ret; -} - -static inline int uea_write_cmv(struct uea_softc *sc, - u32 address, u16 offset, u32 data) -{ - int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTWRITE), - address, offset, data); - if (ret < 0) - uea_err(INS_TO_USBDEV(sc), - "writing cmv failed with error %d\n", ret); - - return ret; -} - -/* - * Monitor the modem and update the stat - * return 0 if everything is ok - * return < 0 if an error occurs (-EAGAIN reboot needed) - */ -static int uea_stat(struct uea_softc *sc) -{ - u32 data; - int ret; - - uea_enters(INS_TO_USBDEV(sc)); - data = sc->stats.phy.state; - - ret = uea_read_cmv(sc, SA_STAT, 0, &sc->stats.phy.state); - if (ret < 0) - return ret; - - switch (GET_STATUS(sc->stats.phy.state)) { - case 0: /* not yet synchronized */ - uea_dbg(INS_TO_USBDEV(sc), - "modem not yet synchronized\n"); - return 0; - - case 1: /* initialization */ - uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n"); - return 0; - - case 2: /* operational */ - uea_vdbg(INS_TO_USBDEV(sc), "modem operational\n"); - break; - - case 3: /* fail ... */ - uea_info(INS_TO_USBDEV(sc), "modem synchronization failed\n"); - return -EAGAIN; - - case 4 ... 6: /* test state */ - uea_warn(INS_TO_USBDEV(sc), - "modem in test mode - not supported\n"); - return -EAGAIN; - - case 7: /* fast-retain ... */ - uea_info(INS_TO_USBDEV(sc), "modem in fast-retain mode\n"); - return 0; - default: - uea_err(INS_TO_USBDEV(sc), "modem invalid SW mode %d\n", - GET_STATUS(sc->stats.phy.state)); - return -EAGAIN; - } - - if (GET_STATUS(data) != 2) { - uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_OFF, 0, NULL); - uea_info(INS_TO_USBDEV(sc), "modem operational\n"); - - /* release the dsp firmware as it is not needed until - * the next failure - */ - if (sc->dsp_firm) { - release_firmware(sc->dsp_firm); - sc->dsp_firm = NULL; - } - - ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid); - if (ret < 0) - return ret; - uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n", - sc->stats.phy.firmid); - } - - /* always update it as atm layer could not be init when we switch to - * operational state - */ - UPDATE_ATM_STAT(signal, ATM_PHY_SIG_FOUND); - - /* wake up processes waiting for synchronization */ - wake_up(&sc->sync_q); - - ret = uea_read_cmv(sc, SA_DIAG, 2, &sc->stats.phy.flags); - if (ret < 0) - return ret; - sc->stats.phy.mflags |= sc->stats.phy.flags; - - /* in case of a flags ( for example delineation LOSS (& 0x10)), - * we check the status again in order to detect the failure earlier - */ - if (sc->stats.phy.flags) { - uea_dbg(INS_TO_USBDEV(sc), "Stat flag = %d\n", - sc->stats.phy.flags); - return 0; - } - - ret = uea_read_cmv(sc, SA_RATE, 0, &data); - if (ret < 0) - return ret; - - /* in bulk mode the modem have problem with high rate - * changing internal timing could improve things, but the - * value is misterious. - * ADI930 don't support it (-EPIPE error). - */ - if (UEA_CHIP_VERSION(sc) != ADI930 - && sc->stats.phy.dsrate != (data >> 16) * 32) { - /* Original timming from ADI(used in windows driver) - * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits - */ - u16 timeout = (data <= 0x20ffff) ? 0 : 1; - ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL); - uea_info(INS_TO_USBDEV(sc), - "setting new timeout %d%s\n", timeout, - ret < 0?" failed":""); - } - sc->stats.phy.dsrate = (data >> 16) * 32; - sc->stats.phy.usrate = (data & 0xffff) * 32; - UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424); - - ret = uea_read_cmv(sc, SA_DIAG, 23, &data); - if (ret < 0) - return ret; - sc->stats.phy.dsattenuation = (data & 0xff) / 2; - - ret = uea_read_cmv(sc, SA_DIAG, 47, &data); - if (ret < 0) - return ret; - sc->stats.phy.usattenuation = (data & 0xff) / 2; - - ret = uea_read_cmv(sc, SA_DIAG, 25, &sc->stats.phy.dsmargin); - if (ret < 0) - return ret; - - ret = uea_read_cmv(sc, SA_DIAG, 49, &sc->stats.phy.usmargin); - if (ret < 0) - return ret; - - ret = uea_read_cmv(sc, SA_DIAG, 51, &sc->stats.phy.rxflow); - if (ret < 0) - return ret; - - ret = uea_read_cmv(sc, SA_DIAG, 52, &sc->stats.phy.txflow); - if (ret < 0) - return ret; - - ret = uea_read_cmv(sc, SA_DIAG, 54, &sc->stats.phy.dsunc); - if (ret < 0) - return ret; - - /* only for atu-c */ - ret = uea_read_cmv(sc, SA_DIAG, 58, &sc->stats.phy.usunc); - if (ret < 0) - return ret; - - ret = uea_read_cmv(sc, SA_DIAG, 53, &sc->stats.phy.dscorr); - if (ret < 0) - return ret; - - /* only for atu-c */ - ret = uea_read_cmv(sc, SA_DIAG, 57, &sc->stats.phy.uscorr); - if (ret < 0) - return ret; - - ret = uea_read_cmv(sc, SA_INFO, 8, &sc->stats.phy.vidco); - if (ret < 0) - return ret; - - ret = uea_read_cmv(sc, SA_INFO, 13, &sc->stats.phy.vidcpe); - if (ret < 0) - return ret; - - return 0; -} - -static int request_cmvs(struct uea_softc *sc, - struct uea_cmvs **cmvs, const struct firmware **fw) -{ - int ret, size; - u8 *data; - char *file; - static char cmv_name[256] = FW_DIR; - - if (cmv_file[sc->modem_index] == NULL) { - if (UEA_CHIP_VERSION(sc) == ADI930) - file = (IS_ISDN(sc)) ? "CMV9i.bin" : "CMV9p.bin"; - else - file = (IS_ISDN(sc)) ? "CMVei.bin" : "CMVep.bin"; - } else - file = cmv_file[sc->modem_index]; - - strcpy(cmv_name, FW_DIR); - strlcat(cmv_name, file, sizeof(cmv_name)); - - ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev); - if (ret < 0) { - uea_err(INS_TO_USBDEV(sc), - "requesting firmware %s failed with error %d\n", - cmv_name, ret); - return ret; - } - - data = (u8 *) (*fw)->data; - size = *data * sizeof(struct uea_cmvs) + 1; - if (size != (*fw)->size) { - uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", - cmv_name); - release_firmware(*fw); - return -EILSEQ; - } - - *cmvs = (struct uea_cmvs *)(data + 1); - return *data; -} - -/* Start boot post firmware modem: - * - send reset commands through usb control pipe - * - start workqueue for DSP loading - * - send CMV options to modem - */ - -static int uea_start_reset(struct uea_softc *sc) -{ - u16 zero = 0; /* ;-) */ - int i, len, ret; - struct uea_cmvs *cmvs; - const struct firmware *cmvs_fw; - - uea_enters(INS_TO_USBDEV(sc)); - uea_info(INS_TO_USBDEV(sc), "(re)booting started\n"); - - sc->booting = 1; - UPDATE_ATM_STAT(signal, ATM_PHY_SIG_LOST); - - /* reset statistics */ - memset(&sc->stats, 0, sizeof(struct uea_stats)); - - /* tell the modem that we want to boot in IDMA mode */ - uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL); - uea_request(sc, UEA_SET_MODE, UEA_BOOT_IDMA, 0, NULL); - - /* enter reset mode */ - uea_request(sc, UEA_SET_MODE, UEA_START_RESET, 0, NULL); - - /* original driver use 200ms, but windows driver use 100ms */ - msleep(100); - - /* leave reset mode */ - uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL); - - /* clear tx and rx mailboxes */ - uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero); - uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero); - uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero); - - msleep(1000); - sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY); - sc->booting = 0; - - /* start loading DSP */ - sc->pageno = 0; - sc->ovl = 0; - schedule_work(&sc->task); - - /* wait for modem ready CMV */ - ret = wait_cmv_ack(sc); - if (ret < 0) - return ret; - - /* Enter in R-IDLE (cmv) until instructed otherwise */ - ret = uea_write_cmv(sc, SA_CNTL, 0, 1); - if (ret < 0) - return ret; - - /* get options */ - ret = len = request_cmvs(sc, &cmvs, &cmvs_fw); - if (ret < 0) - return ret; - - /* send options */ - for (i = 0; i < len; i++) { - ret = uea_write_cmv(sc, FW_GET_LONG(&cmvs[i].address), - FW_GET_WORD(&cmvs[i].offset), - FW_GET_LONG(&cmvs[i].data)); - if (ret < 0) - goto out; - } - /* Enter in R-ACT-REQ */ - ret = uea_write_cmv(sc, SA_CNTL, 0, 2); -out: - release_firmware(cmvs_fw); - sc->reset = 0; - uea_leaves(INS_TO_USBDEV(sc)); - return ret; -} - -/* - * In case of an error wait 1s before rebooting the modem - * if the modem don't request reboot (-EAGAIN). - * Monitor the modem every 1s. - */ - -static int uea_kthread(void *data) -{ - struct uea_softc *sc = data; - int ret = -EAGAIN; - - uea_enters(INS_TO_USBDEV(sc)); - while (!kthread_should_stop()) { - if (ret < 0 || sc->reset) - ret = uea_start_reset(sc); - if (!ret) - ret = uea_stat(sc); - if (ret != -EAGAIN) - msleep(1000); - } - uea_leaves(INS_TO_USBDEV(sc)); - return ret; -} - -/* Load second usb firmware for ADI930 chip */ -static int load_XILINX_firmware(struct uea_softc *sc) -{ - const struct firmware *fw_entry; - int ret, size, u, ln; - u8 *pfw, value; - char *fw_name = FW_DIR "930-fpga.bin"; - - uea_enters(INS_TO_USBDEV(sc)); - - ret = request_firmware(&fw_entry, fw_name, &sc->usb_dev->dev); - if (ret) { - uea_err(INS_TO_USBDEV(sc), "firmware %s is not available\n", - fw_name); - goto err0; - } - - pfw = fw_entry->data; - size = fw_entry->size; - if (size != 0x577B) { - uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", - fw_name); - ret = -EILSEQ; - goto err1; - } - for (u = 0; u < size; u += ln) { - ln = min(size - u, 64); - ret = uea_request(sc, 0xe, 0, ln, pfw + u); - if (ret < 0) { - uea_err(INS_TO_USBDEV(sc), - "elsa download data failed (%d)\n", ret); - goto err1; - } - } - - /* finish to send the fpga - */ - ret = uea_request(sc, 0xe, 1, 0, NULL); - if (ret < 0) { - uea_err(INS_TO_USBDEV(sc), - "elsa download data failed (%d)\n", ret); - goto err1; - } - - /* - * Tell the modem we finish : de-assert reset - */ - value = 0; - ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value); - if (ret < 0) - uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret); - - -err1: - release_firmware(fw_entry); -err0: - uea_leaves(INS_TO_USBDEV(sc)); - return ret; -} - -static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv) -{ - uea_enters(INS_TO_USBDEV(sc)); - if (le16_to_cpu(cmv->wPreamble) != PREAMBLE) - goto bad1; - - if (cmv->bDirection != MODEMTOHOST) - goto bad1; - - /* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to - * the first MEMACESS cmv. Ignore it... - */ - if (cmv->bFunction != sc->cmv_function) { - if (UEA_CHIP_VERSION(sc) == ADI930 - && cmv->bFunction == MAKEFUNCTION(2, 2)) { - cmv->wIndex = cpu_to_le16(sc->cmv_idx); - put_unaligned(cpu_to_le32(sc->cmv_address), &cmv->dwSymbolicAddress); - cmv->wOffsetAddress = cpu_to_le16(sc->cmv_offset); - } - else - goto bad2; - } - - if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) { - wake_up_cmv_ack(sc); - return; - } - - /* in case of MEMACCESS */ - if (le16_to_cpu(cmv->wIndex) != sc->cmv_idx || - le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) != - sc->cmv_address - || le16_to_cpu(cmv->wOffsetAddress) != sc->cmv_offset) - goto bad2; - - sc->data = le32_to_cpu(get_unaligned(&cmv->dwData)); - sc->data = sc->data << 16 | sc->data >> 16; - - wake_up_cmv_ack(sc); - return; - -bad2: - uea_err(INS_TO_USBDEV(sc), "unexpected cmv received," - "Function : %d, Subfunction : %d\n", - FUNCTION_TYPE(cmv->bFunction), - FUNCTION_SUBTYPE(cmv->bFunction)); - return; - -bad1: - uea_err(INS_TO_USBDEV(sc), "invalid cmv received, " - "wPreamble %d, bDirection %d\n", - le16_to_cpu(cmv->wPreamble), cmv->bDirection); -} - -/* - * interrupt handler - */ -static void uea_intr(struct urb *urb, struct pt_regs *regs) -{ - struct uea_softc *sc = (struct uea_softc *)urb->context; - struct intr_pkt *intr; - uea_enters(INS_TO_USBDEV(sc)); - - if (urb->status < 0) { - uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n", - urb->status); - return; - } - - intr = (struct intr_pkt *) urb->transfer_buffer; - - /* device-to-host interrupt */ - if (intr->bType != 0x08 || sc->booting) { - uea_err(INS_TO_USBDEV(sc), "wrong intr\n"); - // rebooting ? - // sc->reset = 1; - goto resubmit; - } - - switch (le16_to_cpu(intr->wInterrupt)) { - case INT_LOADSWAPPAGE: - sc->pageno = intr->bSwapPageNo; - sc->ovl = intr->bOvl >> 4 | intr->bOvl << 4; - schedule_work(&sc->task); - break; - - case INT_INCOMINGCMV: - uea_dispatch_cmv(sc, &intr->u.s2.cmv); - break; - - default: - uea_err(INS_TO_USBDEV(sc), "unknown intr %u\n", - le16_to_cpu(intr->wInterrupt)); - } - -resubmit: - usb_submit_urb(sc->urb_int, GFP_ATOMIC); -} - -/* - * Start the modem : init the data and start kernel thread - */ -static int uea_boot(struct uea_softc *sc) -{ - int ret; - struct intr_pkt *intr; - - uea_enters(INS_TO_USBDEV(sc)); - - INIT_WORK(&sc->task, uea_load_page, sc); - init_waitqueue_head(&sc->sync_q); - init_waitqueue_head(&sc->cmv_ack_wait); - - if (UEA_CHIP_VERSION(sc) == ADI930) - load_XILINX_firmware(sc); - - intr = kmalloc(INTR_PKT_SIZE, GFP_KERNEL); - if (!intr) { - uea_err(INS_TO_USBDEV(sc), - "cannot allocate interrupt package\n"); - uea_leaves(INS_TO_USBDEV(sc)); - return -ENOMEM; - } - - sc->urb_int = usb_alloc_urb(0, GFP_KERNEL); - if (!sc->urb_int) { - uea_err(INS_TO_USBDEV(sc), "cannot allocate interrupt URB\n"); - goto err; - } - - usb_fill_int_urb(sc->urb_int, sc->usb_dev, - usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE), - intr, INTR_PKT_SIZE, uea_intr, sc, - sc->usb_dev->actconfig->interface[0]->altsetting[0]. - endpoint[0].desc.bInterval); - - ret = usb_submit_urb(sc->urb_int, GFP_KERNEL); - if (ret < 0) { - uea_err(INS_TO_USBDEV(sc), - "urb submition failed with error %d\n", ret); - goto err1; - } - - sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm"); - if (sc->kthread == ERR_PTR(-ENOMEM)) { - uea_err(INS_TO_USBDEV(sc), "failed to create thread\n"); - goto err2; - } - - uea_leaves(INS_TO_USBDEV(sc)); - return 0; - -err2: - usb_kill_urb(sc->urb_int); -err1: - kfree(intr); -err: - usb_free_urb(sc->urb_int); - uea_leaves(INS_TO_USBDEV(sc)); - return -ENOMEM; -} - -/* - * Stop the modem : kill kernel thread and free data - */ -static void uea_stop(struct uea_softc *sc) -{ - int ret; - uea_enters(INS_TO_USBDEV(sc)); - ret = kthread_stop(sc->kthread); - uea_info(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret); - - /* stop any pending boot process */ - flush_scheduled_work(); - - uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL); - - usb_kill_urb(sc->urb_int); - kfree(sc->urb_int->transfer_buffer); - usb_free_urb(sc->urb_int); - - if (sc->dsp_firm) - release_firmware(sc->dsp_firm); - uea_leaves(INS_TO_USBDEV(sc)); -} - -/* syfs interface */ -static struct uea_softc *dev_to_uea(struct device *dev) -{ - struct usb_interface *intf; - struct usbatm_data *usbatm; - - intf = to_usb_interface(dev); - if (!intf) - return NULL; - - usbatm = usb_get_intfdata(intf); - if (!usbatm) - return NULL; - - return usbatm->driver_data; -} - -static ssize_t read_status(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int ret = -ENODEV; - struct uea_softc *sc; - - down(&uea_semaphore); - sc = dev_to_uea(dev); - if (!sc) - goto out; - ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state); -out: - up(&uea_semaphore); - return ret; -} - -static ssize_t reboot(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int ret = -ENODEV; - struct uea_softc *sc; - - down(&uea_semaphore); - sc = dev_to_uea(dev); - if (!sc) - goto out; - sc->reset = 1; - ret = count; -out: - up(&uea_semaphore); - return ret; -} - -static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot); - -static ssize_t read_human_status(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int ret = -ENODEV; - struct uea_softc *sc; - - down(&uea_semaphore); - sc = dev_to_uea(dev); - if (!sc) - goto out; - - switch (GET_STATUS(sc->stats.phy.state)) { - case 0: - ret = sprintf(buf, "Modem is booting\n"); - break; - case 1: - ret = sprintf(buf, "Modem is initializing\n"); - break; - case 2: - ret = sprintf(buf, "Modem is operational\n"); - break; - default: - ret = sprintf(buf, "Modem synchronization failed\n"); - break; - } -out: - up(&uea_semaphore); - return ret; -} - -static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, read_human_status, NULL); - -static ssize_t read_delin(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int ret = -ENODEV; - struct uea_softc *sc; - - down(&uea_semaphore); - sc = dev_to_uea(dev); - if (!sc) - goto out; - - if (sc->stats.phy.flags & 0x0C00) - ret = sprintf(buf, "ERROR\n"); - else if (sc->stats.phy.flags & 0x0030) - ret = sprintf(buf, "LOSS\n"); - else - ret = sprintf(buf, "GOOD\n"); -out: - up(&uea_semaphore); - return ret; -} - -static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL); - -#define UEA_ATTR(name, reset) \ - \ -static ssize_t read_##name(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - int ret = -ENODEV; \ - struct uea_softc *sc; \ - \ - down(&uea_semaphore); \ - sc = dev_to_uea(dev); \ - if (!sc) \ - goto out; \ - ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.name); \ - if (reset) \ - sc->stats.phy.name = 0; \ -out: \ - up(&uea_semaphore); \ - return ret; \ -} \ - \ -static DEVICE_ATTR(stat_##name, S_IRUGO, read_##name, NULL) - -UEA_ATTR(mflags, 1); -UEA_ATTR(vidcpe, 0); -UEA_ATTR(usrate, 0); -UEA_ATTR(dsrate, 0); -UEA_ATTR(usattenuation, 0); -UEA_ATTR(dsattenuation, 0); -UEA_ATTR(usmargin, 0); -UEA_ATTR(dsmargin, 0); -UEA_ATTR(txflow, 0); -UEA_ATTR(rxflow, 0); -UEA_ATTR(uscorr, 0); -UEA_ATTR(dscorr, 0); -UEA_ATTR(usunc, 0); -UEA_ATTR(dsunc, 0); - -/* Retrieve the device End System Identifier (MAC) */ - -#define htoi(x) (isdigit(x) ? x-'0' : toupper(x)-'A'+10) -static int uea_getesi(struct uea_softc *sc, u_char * esi) -{ - unsigned char mac_str[2 * ETH_ALEN + 1]; - int i; - if (usb_string - (sc->usb_dev, sc->usb_dev->descriptor.iSerialNumber, mac_str, - sizeof(mac_str)) != 2 * ETH_ALEN) - return 1; - - for (i = 0; i < ETH_ALEN; i++) - esi[i] = htoi(mac_str[2 * i]) * 16 + htoi(mac_str[2 * i + 1]); - - return 0; -} - -/* ATM stuff */ -static int uea_atm_open(struct usbatm_data *usbatm, struct atm_dev *atm_dev) -{ - struct uea_softc *sc = usbatm->driver_data; - - return uea_getesi(sc, atm_dev->esi); -} - -static int uea_heavy(struct usbatm_data *usbatm, struct usb_interface *intf) -{ - struct uea_softc *sc = usbatm->driver_data; - - wait_event(sc->sync_q, IS_OPERATIONAL(sc)); - - return 0; - -} - -static int claim_interface(struct usb_device *usb_dev, - struct usbatm_data *usbatm, int ifnum) -{ - int ret; - struct usb_interface *intf = usb_ifnum_to_if(usb_dev, ifnum); - - if (!intf) { - uea_err(usb_dev, "interface %d not found\n", ifnum); - return -ENODEV; - } - - ret = usb_driver_claim_interface(&uea_driver, intf, usbatm); - if (ret != 0) - uea_err(usb_dev, "can't claim interface %d, error %d\n", ifnum, - ret); - return ret; -} - -static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf) -{ - /* sysfs interface */ - device_create_file(&intf->dev, &dev_attr_stat_status); - device_create_file(&intf->dev, &dev_attr_stat_mflags); - device_create_file(&intf->dev, &dev_attr_stat_human_status); - device_create_file(&intf->dev, &dev_attr_stat_delin); - device_create_file(&intf->dev, &dev_attr_stat_vidcpe); - device_create_file(&intf->dev, &dev_attr_stat_usrate); - device_create_file(&intf->dev, &dev_attr_stat_dsrate); - device_create_file(&intf->dev, &dev_attr_stat_usattenuation); - device_create_file(&intf->dev, &dev_attr_stat_dsattenuation); - device_create_file(&intf->dev, &dev_attr_stat_usmargin); - device_create_file(&intf->dev, &dev_attr_stat_dsmargin); - device_create_file(&intf->dev, &dev_attr_stat_txflow); - device_create_file(&intf->dev, &dev_attr_stat_rxflow); - device_create_file(&intf->dev, &dev_attr_stat_uscorr); - device_create_file(&intf->dev, &dev_attr_stat_dscorr); - device_create_file(&intf->dev, &dev_attr_stat_usunc); - device_create_file(&intf->dev, &dev_attr_stat_dsunc); -} - -static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, - const struct usb_device_id *id, int *heavy) -{ - struct usb_device *usb = interface_to_usbdev(intf); - struct uea_softc *sc; - int ret, ifnum = intf->altsetting->desc.bInterfaceNumber; - - uea_enters(usb); - - /* interface 0 is for firmware/monitoring */ - if (ifnum != UEA_INTR_IFACE_NO) - return -ENODEV; - - *heavy = sync_wait[modem_index]; - - /* interface 1 is for outbound traffic */ - ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO); - if (ret < 0) - return ret; - - /* ADI930 has only 2 interfaces and inbound traffic - * is on interface 1 - */ - if (UEA_CHIP_VERSION(id) != ADI930) { - /* interface 2 is for inbound traffic */ - ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO); - if (ret < 0) - return ret; - } - - sc = kzalloc(sizeof(struct uea_softc), GFP_KERNEL); - if (!sc) { - uea_err(INS_TO_USBDEV(sc), "uea_init: not enough memory !\n"); - return -ENOMEM; - } - - sc->usb_dev = usb; - usbatm->driver_data = sc; - sc->usbatm = usbatm; - sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0; - sc->driver_info = id->driver_info; - - ret = uea_boot(sc); - if (ret < 0) { - kfree(sc); - return ret; - } - - create_fs_entries(sc, intf); - return 0; -} - -static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf) -{ - /* sysfs interface */ - device_remove_file(&intf->dev, &dev_attr_stat_status); - device_remove_file(&intf->dev, &dev_attr_stat_mflags); - device_remove_file(&intf->dev, &dev_attr_stat_human_status); - device_remove_file(&intf->dev, &dev_attr_stat_delin); - device_remove_file(&intf->dev, &dev_attr_stat_vidcpe); - device_remove_file(&intf->dev, &dev_attr_stat_usrate); - device_remove_file(&intf->dev, &dev_attr_stat_dsrate); - device_remove_file(&intf->dev, &dev_attr_stat_usattenuation); - device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation); - device_remove_file(&intf->dev, &dev_attr_stat_usmargin); - device_remove_file(&intf->dev, &dev_attr_stat_dsmargin); - device_remove_file(&intf->dev, &dev_attr_stat_txflow); - device_remove_file(&intf->dev, &dev_attr_stat_rxflow); - device_remove_file(&intf->dev, &dev_attr_stat_uscorr); - device_remove_file(&intf->dev, &dev_attr_stat_dscorr); - device_remove_file(&intf->dev, &dev_attr_stat_usunc); - device_remove_file(&intf->dev, &dev_attr_stat_dsunc); -} - -static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) -{ - struct uea_softc *sc = usbatm->driver_data; - - destroy_fs_entries(sc, intf); - uea_stop(sc); - kfree(sc); -} - -static struct usbatm_driver uea_usbatm_driver = { - .driver_name = "ueagle-atm", - .owner = THIS_MODULE, - .bind = uea_bind, - .atm_start = uea_atm_open, - .unbind = uea_unbind, - .heavy_init = uea_heavy, - .in = UEA_BULK_DATA_PIPE, - .out = UEA_BULK_DATA_PIPE, -}; - -static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *usb = interface_to_usbdev(intf); - - uea_enters(usb); - uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s\n", - le16_to_cpu(usb->descriptor.idVendor), - le16_to_cpu(usb->descriptor.idProduct), - chip_name[UEA_CHIP_VERSION(id)]); - - usb_reset_device(usb); - - if (UEA_IS_PREFIRM(id)) - return uea_load_firmware(usb, UEA_CHIP_VERSION(id)); - - return usbatm_usb_probe(intf, id, &uea_usbatm_driver); -} - -static void uea_disconnect(struct usb_interface *intf) -{ - struct usb_device *usb = interface_to_usbdev(intf); - int ifnum = intf->altsetting->desc.bInterfaceNumber; - uea_enters(usb); - - /* ADI930 has 2 interfaces and eagle 3 interfaces. - * Pre-firmware device has one interface - */ - if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) { - down(&uea_semaphore); - usbatm_usb_disconnect(intf); - up(&uea_semaphore); - uea_info(usb, "ADSL device removed\n"); - } - - uea_leaves(usb); -} - -/* - * List of supported VID/PID - */ -static const struct usb_device_id uea_ids[] = { - {USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM), .driver_info = ADI930 | PREFIRM}, - {USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM}, - {USB_DEVICE(EAGLE_VID, EAGLE_I_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, - {USB_DEVICE(EAGLE_VID, EAGLE_I_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM}, - {USB_DEVICE(EAGLE_VID, EAGLE_II_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM}, - {USB_DEVICE(EAGLE_VID, EAGLE_II_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM}, - {USB_DEVICE(EAGLE_VID, EAGLE_IIC_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM}, - {USB_DEVICE(EAGLE_VID, EAGLE_IIC_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM}, - {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PREFIRM), .driver_info = EAGLE_III | PREFIRM}, - {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PSTFIRM), .driver_info = EAGLE_III | PSTFIRM}, - {USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, - {USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM}, - {USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, - {USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM}, - {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM}, - {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM}, - {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM}, - {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM}, - {} -}; - -/* - * USB driver descriptor - */ -static struct usb_driver uea_driver = { - .name = "ueagle-atm", - .id_table = uea_ids, - .probe = uea_probe, - .disconnect = uea_disconnect, -}; - -MODULE_DEVICE_TABLE(usb, uea_ids); - -/** - * uea_init - Initialize the module. - * Register to USB subsystem - */ -static int __init uea_init(void) -{ - printk(KERN_INFO "[ueagle-atm] driver " EAGLEUSBVERSION " loaded\n"); - - usb_register(&uea_driver); - - return 0; -} - -module_init(uea_init); - -/** - * uea_exit - Destroy module - * Deregister with USB subsystem - */ -static void __exit uea_exit(void) -{ - /* - * This calls automatically the uea_disconnect method if necessary: - */ - usb_deregister(&uea_driver); - - printk(KERN_INFO "[ueagle-atm] driver unloaded\n"); -} - -module_exit(uea_exit); - -MODULE_AUTHOR("Damien Bergamini/Matthieu Castet/Stanislaw W. Gruszka"); -MODULE_DESCRIPTION("ADI 930/Eagle USB ADSL Modem driver"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/trunk/drivers/usb/atm/usbatm.c b/trunk/drivers/usb/atm/usbatm.c index 9baa6296fc95..2e6593e6c1bd 100644 --- a/trunk/drivers/usb/atm/usbatm.c +++ b/trunk/drivers/usb/atm/usbatm.c @@ -646,14 +646,14 @@ static void usbatm_destroy_instance(struct kref *kref) kfree(instance); } -static void usbatm_get_instance(struct usbatm_data *instance) +void usbatm_get_instance(struct usbatm_data *instance) { dbg("%s", __func__); kref_get(&instance->refcount); } -static void usbatm_put_instance(struct usbatm_data *instance) +void usbatm_put_instance(struct usbatm_data *instance) { dbg("%s", __func__); diff --git a/trunk/drivers/usb/atm/xusbatm.c b/trunk/drivers/usb/atm/xusbatm.c index 5c76e3aaaa5e..7fe7fb484d10 100644 --- a/trunk/drivers/usb/atm/xusbatm.c +++ b/trunk/drivers/usb/atm/xusbatm.c @@ -140,6 +140,7 @@ static int xusbatm_usb_probe(struct usb_interface *intf, } static struct usb_driver xusbatm_usb_driver = { + .owner = THIS_MODULE, .name = xusbatm_driver_name, .probe = xusbatm_usb_probe, .disconnect = usbatm_usb_disconnect, diff --git a/trunk/drivers/usb/class/audio.c b/trunk/drivers/usb/class/audio.c index 3ad9ee8b84a9..50858273f8d3 100644 --- a/trunk/drivers/usb/class/audio.c +++ b/trunk/drivers/usb/class/audio.c @@ -2732,6 +2732,7 @@ static struct usb_device_id usb_audio_ids [] = { MODULE_DEVICE_TABLE (usb, usb_audio_ids); static struct usb_driver usb_audio_driver = { + .owner = THIS_MODULE, .name = "audio", .probe = usb_audio_probe, .disconnect = usb_audio_disconnect, diff --git a/trunk/drivers/usb/class/cdc-acm.c b/trunk/drivers/usb/class/cdc-acm.c index 248279e44c99..1b4751412970 100644 --- a/trunk/drivers/usb/class/cdc-acm.c +++ b/trunk/drivers/usb/class/cdc-acm.c @@ -6,7 +6,6 @@ * Copyright (c) 1999 Johannes Erdfelt * Copyright (c) 2000 Vojtech Pavlik * Copyright (c) 2004 Oliver Neukum - * Copyright (c) 2005 David Kubicek * * USB Abstract Control Model driver for USB modems and ISDN adapters * @@ -30,7 +29,6 @@ * config we want, sysadmin changes bConfigurationValue in sysfs. * v0.23 - use softirq for rx processing, as needed by tty layer * v0.24 - change probe method to evaluate CDC union descriptor - * v0.25 - downstream tasks paralelized to maximize throughput */ /* @@ -65,15 +63,14 @@ #include #include #include -#include #include "cdc-acm.h" /* * Version Information */ -#define DRIVER_VERSION "v0.25" -#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek" +#define DRIVER_VERSION "v0.23" +#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik" #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" static struct usb_driver acm_driver; @@ -287,9 +284,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs) /* data interface returns incoming bytes, or we got unthrottled */ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs) { - struct acm_rb *buf; - struct acm_ru *rcv = urb->context; - struct acm *acm = rcv->instance; + struct acm *acm = urb->context; dbg("Entering acm_read_bulk with status %d\n", urb->status); if (!ACM_READY(acm)) @@ -298,109 +293,49 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs) if (urb->status) dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status); - buf = rcv->buffer; - buf->size = urb->actual_length; - - spin_lock(&acm->read_lock); - list_add_tail(&rcv->list, &acm->spare_read_urbs); - list_add_tail(&buf->list, &acm->filled_read_bufs); - spin_unlock(&acm->read_lock); - - tasklet_schedule(&acm->urb_task); + /* calling tty_flip_buffer_push() in_irq() isn't allowed */ + tasklet_schedule(&acm->bh); } static void acm_rx_tasklet(unsigned long _acm) { struct acm *acm = (void *)_acm; - struct acm_rb *buf; + struct urb *urb = acm->readurb; struct tty_struct *tty = acm->tty; - struct acm_ru *rcv; - //unsigned long flags; + unsigned char *data = urb->transfer_buffer; int i = 0; dbg("Entering acm_rx_tasklet"); - if (!ACM_READY(acm) || acm->throttle) - return; - -next_buffer: - spin_lock(&acm->read_lock); - if (list_empty(&acm->filled_read_bufs)) { - spin_unlock(&acm->read_lock); - goto urbs; + if (urb->actual_length > 0 && !acm->throttle) { + for (i = 0; i < urb->actual_length && !acm->throttle; i++) { + /* if we insert more than TTY_FLIPBUF_SIZE characters, + * we drop them. */ + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + tty_insert_flip_char(tty, data[i], 0); + } + dbg("Handed %d bytes to tty layer", i+1); + tty_flip_buffer_push(tty); } - buf = list_entry(acm->filled_read_bufs.next, - struct acm_rb, list); - list_del(&buf->list); - spin_unlock(&acm->read_lock); - - dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size); - - for (i = 0; i < buf->size && !acm->throttle; i++) { - /* if we insert more than TTY_FLIPBUF_SIZE characters, - we drop them. */ - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(tty); - } - tty_insert_flip_char(tty, buf->base[i], 0); - } - tty_flip_buffer_push(tty); spin_lock(&acm->throttle_lock); if (acm->throttle) { dbg("Throtteling noticed"); - memmove(buf->base, buf->base + i, buf->size - i); - buf->size -= i; + memmove(data, data + i, urb->actual_length - i); + urb->actual_length -= i; + acm->resubmit_to_unthrottle = 1; spin_unlock(&acm->throttle_lock); - spin_lock(&acm->read_lock); - list_add(&buf->list, &acm->filled_read_bufs); - spin_unlock(&acm->read_lock); return; } spin_unlock(&acm->throttle_lock); - spin_lock(&acm->read_lock); - list_add(&buf->list, &acm->spare_read_bufs); - spin_unlock(&acm->read_lock); - goto next_buffer; - -urbs: - while (!list_empty(&acm->spare_read_bufs)) { - spin_lock(&acm->read_lock); - if (list_empty(&acm->spare_read_urbs)) { - spin_unlock(&acm->read_lock); - return; - } - rcv = list_entry(acm->spare_read_urbs.next, - struct acm_ru, list); - list_del(&rcv->list); - spin_unlock(&acm->read_lock); - - buf = list_entry(acm->spare_read_bufs.next, - struct acm_rb, list); - list_del(&buf->list); - - rcv->buffer = buf; - - usb_fill_bulk_urb(rcv->urb, acm->dev, - acm->rx_endpoint, - buf->base, - acm->readsize, - acm_read_bulk, rcv); - rcv->urb->transfer_dma = buf->dma; - rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf); - - /* This shouldn't kill the driver as unsuccessful URBs are returned to the - free-urbs-pool and resubmited ASAP */ - if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { - list_add(&buf->list, &acm->spare_read_bufs); - spin_lock(&acm->read_lock); - list_add(&rcv->list, &acm->spare_read_urbs); - spin_unlock(&acm->read_lock); - return; - } - } + urb->actual_length = 0; + urb->dev = acm->dev; + + i = usb_submit_urb(urb, GFP_ATOMIC); + if (i) + dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i); } /* data interface wrote those outgoing bytes */ @@ -434,7 +369,6 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) { struct acm *acm; int rv = -EINVAL; - int i; dbg("Entering acm_tty_open.\n"); down(&open_sem); @@ -448,9 +382,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) tty->driver_data = acm; acm->tty = tty; - /* force low_latency on so that our tty_push actually forces the data through, - otherwise it is scheduled, and with high data rates data can get lost. */ - tty->low_latency = 1; + if (acm->used++) { goto done; @@ -462,20 +394,18 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) goto bail_out; } + acm->readurb->dev = acm->dev; + if (usb_submit_urb(acm->readurb, GFP_KERNEL)) { + dbg("usb_submit_urb(read bulk) failed"); + goto bail_out_and_unlink; + } + if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS)) goto full_bailout; - INIT_LIST_HEAD(&acm->spare_read_urbs); - INIT_LIST_HEAD(&acm->spare_read_bufs); - INIT_LIST_HEAD(&acm->filled_read_bufs); - for (i = 0; i < ACM_NRU; i++) { - list_add(&(acm->ru[i].list), &acm->spare_read_urbs); - } - for (i = 0; i < ACM_NRB; i++) { - list_add(&(acm->rb[i].list), &acm->spare_read_bufs); - } - - tasklet_schedule(&acm->urb_task); + /* force low_latency on so that our tty_push actually forces the data through, + otherwise it is scheduled, and with high data rates data can get lost. */ + tty->low_latency = 1; done: err_out: @@ -483,6 +413,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) return rv; full_bailout: + usb_kill_urb(acm->readurb); +bail_out_and_unlink: usb_kill_urb(acm->ctrlurb); bail_out: acm->used--; @@ -492,22 +424,18 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) static void acm_tty_unregister(struct acm *acm) { - int i; - tty_unregister_device(acm_tty_driver, acm->minor); usb_put_intf(acm->control); acm_table[acm->minor] = NULL; usb_free_urb(acm->ctrlurb); + usb_free_urb(acm->readurb); usb_free_urb(acm->writeurb); - for (i = 0; i < ACM_NRU; i++) - usb_free_urb(acm->ru[i].urb); kfree(acm); } static void acm_tty_close(struct tty_struct *tty, struct file *filp) { struct acm *acm = tty->driver_data; - int i; if (!acm || !acm->used) return; @@ -518,8 +446,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) acm_set_control(acm, acm->ctrlout = 0); usb_kill_urb(acm->ctrlurb); usb_kill_urb(acm->writeurb); - for (i = 0; i < ACM_NRU; i++) - usb_kill_urb(acm->ru[i].urb); + usb_kill_urb(acm->readurb); } else acm_tty_unregister(acm); } @@ -601,7 +528,10 @@ static void acm_tty_unthrottle(struct tty_struct *tty) spin_lock_bh(&acm->throttle_lock); acm->throttle = 0; spin_unlock_bh(&acm->throttle_lock); - tasklet_schedule(&acm->urb_task); + if (acm->resubmit_to_unthrottle) { + acm->resubmit_to_unthrottle = 0; + acm_read_bulk(acm->readurb, NULL); + } } static void acm_tty_break_ctl(struct tty_struct *tty, int state) @@ -658,7 +588,7 @@ static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int return -ENOIOCTLCMD; } -static const __u32 acm_tty_speed[] = { +static __u32 acm_tty_speed[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, @@ -666,7 +596,7 @@ static const __u32 acm_tty_speed[] = { 2500000, 3000000, 3500000, 4000000 }; -static const __u8 acm_tty_size[] = { +static __u8 acm_tty_size[] = { 5, 6, 7, 8 }; @@ -764,7 +694,6 @@ static int acm_probe (struct usb_interface *intf, int call_interface_num = -1; int data_interface_num; unsigned long quirks; - int i; /* handle quirks deadly to normal probing*/ quirks = (unsigned long)id->driver_info; @@ -904,7 +833,7 @@ static int acm_probe (struct usb_interface *intf, } ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); - readsize = le16_to_cpu(epread->wMaxPacketSize)*2; + readsize = le16_to_cpu(epread->wMaxPacketSize); acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize); acm->control = control_interface; acm->data = data_interface; @@ -913,14 +842,12 @@ static int acm_probe (struct usb_interface *intf, acm->ctrl_caps = ac_management_function; acm->ctrlsize = ctrlsize; acm->readsize = readsize; - acm->urb_task.func = acm_rx_tasklet; - acm->urb_task.data = (unsigned long) acm; + acm->bh.func = acm_rx_tasklet; + acm->bh.data = (unsigned long) acm; INIT_WORK(&acm->work, acm_softint, acm); spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); - spin_lock_init(&acm->read_lock); acm->write_ready = 1; - acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress); buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); if (!buf) { @@ -929,6 +856,13 @@ static int acm_probe (struct usb_interface *intf, } acm->ctrl_buffer = buf; + buf = usb_buffer_alloc(usb_dev, readsize, GFP_KERNEL, &acm->read_dma); + if (!buf) { + dev_dbg(&intf->dev, "out of memory (read buffer alloc)\n"); + goto alloc_fail3; + } + acm->read_buffer = buf; + if (acm_write_buffers_alloc(acm) < 0) { dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n"); goto alloc_fail4; @@ -939,25 +873,10 @@ static int acm_probe (struct usb_interface *intf, dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); goto alloc_fail5; } - for (i = 0; i < ACM_NRU; i++) { - struct acm_ru *rcv = &(acm->ru[i]); - - if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { - dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n"); - goto alloc_fail7; - } - - rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - rcv->instance = acm; - } - for (i = 0; i < ACM_NRB; i++) { - struct acm_rb *buf = &(acm->rb[i]); - - // Using usb_buffer_alloc instead of kmalloc as Oliver suggested - if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) { - dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n"); - goto alloc_fail7; - } + acm->readurb = usb_alloc_urb(0, GFP_KERNEL); + if (!acm->readurb) { + dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n"); + goto alloc_fail6; } acm->writeurb = usb_alloc_urb(0, GFP_KERNEL); if (!acm->writeurb) { @@ -970,9 +889,15 @@ static int acm_probe (struct usb_interface *intf, acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; acm->ctrlurb->transfer_dma = acm->ctrl_dma; + usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress), + acm->read_buffer, readsize, acm_read_bulk, acm); + acm->readurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP; + acm->readurb->transfer_dma = acm->read_dma; + usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), NULL, acm->writesize, acm_write_bulk, acm); acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP; + /* acm->writeurb->transfer_dma = 0; */ dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); @@ -992,14 +917,14 @@ static int acm_probe (struct usb_interface *intf, return 0; alloc_fail7: - for (i = 0; i < ACM_NRB; i++) - usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); - for (i = 0; i < ACM_NRU; i++) - usb_free_urb(acm->ru[i].urb); + usb_free_urb(acm->readurb); +alloc_fail6: usb_free_urb(acm->ctrlurb); alloc_fail5: acm_write_buffers_free(acm); alloc_fail4: + usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma); +alloc_fail3: usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); alloc_fail2: kfree(acm); @@ -1011,7 +936,6 @@ static void acm_disconnect(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata (intf); struct usb_device *usb_dev = interface_to_usbdev(intf); - int i; if (!acm || !acm->dev) { dbg("disconnect on nonexisting interface"); @@ -1022,24 +946,15 @@ static void acm_disconnect(struct usb_interface *intf) acm->dev = NULL; usb_set_intfdata (intf, NULL); - tasklet_disable(&acm->urb_task); - usb_kill_urb(acm->ctrlurb); + usb_kill_urb(acm->readurb); usb_kill_urb(acm->writeurb); - for (i = 0; i < ACM_NRU; i++) - usb_kill_urb(acm->ru[i].urb); - - INIT_LIST_HEAD(&acm->filled_read_bufs); - INIT_LIST_HEAD(&acm->spare_read_bufs); - - tasklet_enable(&acm->urb_task); flush_scheduled_work(); /* wait for acm_softint */ acm_write_buffers_free(acm); + usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma); usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); - for (i = 0; i < ACM_NRB; i++) - usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); usb_driver_release_interface(&acm_driver, acm->data); @@ -1088,6 +1003,7 @@ static struct usb_device_id acm_ids[] = { MODULE_DEVICE_TABLE (usb, acm_ids); static struct usb_driver acm_driver = { + .owner = THIS_MODULE, .name = "cdc_acm", .probe = acm_probe, .disconnect = acm_disconnect, diff --git a/trunk/drivers/usb/class/cdc-acm.h b/trunk/drivers/usb/class/cdc-acm.h index fd2aaccdcbac..963a5dfd2096 100644 --- a/trunk/drivers/usb/class/cdc-acm.h +++ b/trunk/drivers/usb/class/cdc-acm.h @@ -59,9 +59,6 @@ * when processing onlcr, so we only need 2 buffers. */ #define ACM_NWB 2 -#define ACM_NRU 16 -#define ACM_NRB 16 - struct acm_wb { unsigned char *buf; dma_addr_t dmah; @@ -69,43 +66,22 @@ struct acm_wb { int use; }; -struct acm_rb { - struct list_head list; - int size; - unsigned char *base; - dma_addr_t dma; -}; - -struct acm_ru { - struct list_head list; - struct acm_rb *buffer; - struct urb *urb; - struct acm *instance; -}; - struct acm { struct usb_device *dev; /* the corresponding usb device */ struct usb_interface *control; /* control interface */ struct usb_interface *data; /* data interface */ struct tty_struct *tty; /* the corresponding tty */ - struct urb *ctrlurb, *writeurb; /* urbs */ - u8 *ctrl_buffer; /* buffers of urbs */ - dma_addr_t ctrl_dma; /* dma handles of buffers */ + struct urb *ctrlurb, *readurb, *writeurb; /* urbs */ + u8 *ctrl_buffer, *read_buffer; /* buffers of urbs */ + dma_addr_t ctrl_dma, read_dma; /* dma handles of buffers */ struct acm_wb wb[ACM_NWB]; - struct acm_ru ru[ACM_NRU]; - struct acm_rb rb[ACM_NRB]; - int rx_endpoint; - spinlock_t read_lock; - struct list_head spare_read_urbs; - struct list_head spare_read_bufs; - struct list_head filled_read_bufs; int write_current; /* current write buffer */ int write_used; /* number of non-empty write buffers */ int write_ready; /* write urb is not running */ spinlock_t write_lock; struct usb_cdc_line_coding line; /* bits, stop, parity */ struct work_struct work; /* work queue entry for line discipline waking up */ - struct tasklet_struct urb_task; /* rx processing */ + struct tasklet_struct bh; /* rx processing */ spinlock_t throttle_lock; /* synchronize throtteling and read callback */ unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ unsigned int ctrlout; /* output control lines (DTR, RTS) */ @@ -115,6 +91,7 @@ struct acm { unsigned int minor; /* acm minor number */ unsigned char throttle; /* throttled by tty layer */ unsigned char clocal; /* termios CLOCAL */ + unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */ unsigned int ctrl_caps; /* control capabilities from the class specific header */ }; diff --git a/trunk/drivers/usb/class/usb-midi.c b/trunk/drivers/usb/class/usb-midi.c index f13f004d311f..5f8af35e7633 100644 --- a/trunk/drivers/usb/class/usb-midi.c +++ b/trunk/drivers/usb/class/usb-midi.c @@ -2027,6 +2027,7 @@ static struct usb_device_id id_table[] = { }; static struct usb_driver usb_midi_driver = { + .owner = THIS_MODULE, .name = "midi", .probe = usb_midi_probe, .disconnect = usb_midi_disconnect, diff --git a/trunk/drivers/usb/class/usblp.c b/trunk/drivers/usb/class/usblp.c index 27e9404547f3..357e75335f17 100644 --- a/trunk/drivers/usb/class/usblp.c +++ b/trunk/drivers/usb/class/usblp.c @@ -199,7 +199,7 @@ struct quirk_printer_struct { #define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */ #define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */ -static const struct quirk_printer_struct quirk_printers[] = { +static struct quirk_printer_struct quirk_printers[] = { { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */ { 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */ { 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */ @@ -301,7 +301,7 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs) * Get and print printer errors. */ -static const char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" }; +static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" }; static int usblp_check_status(struct usblp *usblp, int err) { @@ -438,7 +438,7 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM); } -static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct usblp *usblp = file->private_data; int length, err, i; @@ -838,8 +838,7 @@ static struct file_operations usblp_fops = { .read = usblp_read, .write = usblp_write, .poll = usblp_poll, - .unlocked_ioctl = usblp_ioctl, - .compat_ioctl = usblp_ioctl, + .ioctl = usblp_ioctl, .open = usblp_open, .release = usblp_release, }; @@ -850,20 +849,6 @@ static struct usb_class_driver usblp_class = { .minor_base = USBLP_MINOR_BASE, }; -static ssize_t usblp_show_ieee1284_id(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct usblp *usblp = usb_get_intfdata (intf); - - if (usblp->device_id_string[0] == 0 && - usblp->device_id_string[1] == 0) - return 0; - - return sprintf(buf, "%s", usblp->device_id_string+2); -} - -static DEVICE_ATTR(ieee1284_id, S_IRUGO, usblp_show_ieee1284_id, NULL); - static int usblp_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -948,12 +933,20 @@ static int usblp_probe(struct usb_interface *intf, /* Retrieve and store the device ID string. */ usblp_cache_device_id_string(usblp); - device_create_file(&intf->dev, &dev_attr_ieee1284_id); #ifdef DEBUG usblp_check_status(usblp, 0); #endif + info("usblp%d: USB %sdirectional printer dev %d " + "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X", + usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, + usblp->ifnum, + usblp->protocol[usblp->current_protocol].alt_setting, + usblp->current_protocol, + le16_to_cpu(usblp->dev->descriptor.idVendor), + le16_to_cpu(usblp->dev->descriptor.idProduct)); + usb_set_intfdata (intf, usblp); usblp->present = 1; @@ -964,20 +957,11 @@ static int usblp_probe(struct usb_interface *intf, goto abort_intfdata; } usblp->minor = intf->minor; - info("usblp%d: USB %sdirectional printer dev %d " - "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X", - usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, - usblp->ifnum, - usblp->protocol[usblp->current_protocol].alt_setting, - usblp->current_protocol, - le16_to_cpu(usblp->dev->descriptor.idVendor), - le16_to_cpu(usblp->dev->descriptor.idProduct)); return 0; abort_intfdata: usb_set_intfdata (intf, NULL); - device_remove_file(&intf->dev, &dev_attr_ieee1284_id); abort: if (usblp) { if (usblp->writebuf) @@ -1172,8 +1156,6 @@ static void usblp_disconnect(struct usb_interface *intf) BUG (); } - device_remove_file(&intf->dev, &dev_attr_ieee1284_id); - down (&usblp_sem); down (&usblp->sem); usblp->present = 0; @@ -1204,6 +1186,7 @@ static struct usb_device_id usblp_ids [] = { MODULE_DEVICE_TABLE (usb, usblp_ids); static struct usb_driver usblp_driver = { + .owner = THIS_MODULE, .name = "usblp", .probe = usblp_probe, .disconnect = usblp_disconnect, diff --git a/trunk/drivers/usb/core/Makefile b/trunk/drivers/usb/core/Makefile index 28329ddf187c..86d5c380892d 100644 --- a/trunk/drivers/usb/core/Makefile +++ b/trunk/drivers/usb/core/Makefile @@ -2,7 +2,7 @@ # Makefile for USB Core files and filesystem # -usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ +usbcore-objs := usb.o hub.o hcd.o urb.o message.o \ config.o file.o buffer.o sysfs.o devio.o notify.o ifeq ($(CONFIG_PCI),y) diff --git a/trunk/drivers/usb/core/buffer.c b/trunk/drivers/usb/core/buffer.c index ad742cec94fa..419c9943a7cb 100644 --- a/trunk/drivers/usb/core/buffer.c +++ b/trunk/drivers/usb/core/buffer.c @@ -55,9 +55,6 @@ int hcd_buffer_create (struct usb_hcd *hcd) char name [16]; int i, size; - if (!hcd->self.controller->dma_mask) - return 0; - for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (!(size = pool_max [i])) continue; diff --git a/trunk/drivers/usb/core/devices.c b/trunk/drivers/usb/core/devices.c index 2684e15b813b..83e815d3cd52 100644 --- a/trunk/drivers/usb/core/devices.c +++ b/trunk/drivers/usb/core/devices.c @@ -67,45 +67,45 @@ /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */ #define ALLOW_SERIAL_NUMBER -static const char *format_topo = +static char *format_topo = /* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */ "\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n"; -static const char *format_string_manufacturer = +static char *format_string_manufacturer = /* S: Manufacturer=xxxx */ "S: Manufacturer=%.100s\n"; -static const char *format_string_product = +static char *format_string_product = /* S: Product=xxxx */ "S: Product=%.100s\n"; #ifdef ALLOW_SERIAL_NUMBER -static const char *format_string_serialnumber = +static char *format_string_serialnumber = /* S: SerialNumber=xxxx */ "S: SerialNumber=%.100s\n"; #endif -static const char *format_bandwidth = +static char *format_bandwidth = /* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */ "B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n"; -static const char *format_device1 = +static char *format_device1 = /* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */ "D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n"; -static const char *format_device2 = +static char *format_device2 = /* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */ "P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n"; -static const char *format_config = +static char *format_config = /* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */ "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n"; -static const char *format_iface = +static char *format_iface = /* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/ "I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n"; -static const char *format_endpt = +static char *format_endpt = /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */ "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n"; @@ -545,10 +545,10 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski struct usb_device *childdev = usbdev->children[chix]; if (childdev) { - usb_lock_device(childdev); + down(&childdev->serialize); ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev, bus, level + 1, chix, ++cnt); - usb_unlock_device(childdev); + up(&childdev->serialize); if (ret == -EFAULT) return total_written; total_written += ret; diff --git a/trunk/drivers/usb/core/devio.c b/trunk/drivers/usb/core/devio.c index 2b68998fe4b3..b1d6e9af732d 100644 --- a/trunk/drivers/usb/core/devio.c +++ b/trunk/drivers/usb/core/devio.c @@ -402,6 +402,7 @@ static void driver_disconnect(struct usb_interface *intf) } struct usb_driver usbfs_driver = { + .owner = THIS_MODULE, .name = "usbfs", .probe = driver_probe, .disconnect = driver_disconnect, @@ -1349,7 +1350,9 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) /* let kernel drivers try to (re)bind to the interface */ case USBDEVFS_CONNECT: usb_unlock_device(ps->dev); + usb_lock_all_devices(); bus_rescan_devices(intf->dev.bus); + usb_unlock_all_devices(); usb_lock_device(ps->dev); break; diff --git a/trunk/drivers/usb/core/driver.c b/trunk/drivers/usb/core/driver.c deleted file mode 100644 index 076462c8ba2a..000000000000 --- a/trunk/drivers/usb/core/driver.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - * drivers/usb/driver.c - most of the driver model stuff for usb - * - * (C) Copyright 2005 Greg Kroah-Hartman - * - * based on drivers/usb/usb.c which had the following copyrights: - * (C) Copyright Linus Torvalds 1999 - * (C) Copyright Johannes Erdfelt 1999-2001 - * (C) Copyright Andreas Gal 1999 - * (C) Copyright Gregory P. Smith 1999 - * (C) Copyright Deti Fliegl 1999 (new USB architecture) - * (C) Copyright Randy Dunlap 2000 - * (C) Copyright David Brownell 2000-2004 - * (C) Copyright Yggdrasil Computing, Inc. 2000 - * (usb_device_id matching changes by Adam J. Richter) - * (C) Copyright Greg Kroah-Hartman 2002-2003 - * - * NOTE! This is not actually a driver at all, rather this is - * just a collection of helper routines that implement the - * generic USB things that the real drivers can use.. - * - */ - -#include -#include -#include -#include "hcd.h" -#include "usb.h" - -static int usb_match_one_id(struct usb_interface *interface, - const struct usb_device_id *id); - -struct usb_dynid { - struct list_head node; - struct usb_device_id id; -}; - - -static int generic_probe(struct device *dev) -{ - return 0; -} -static int generic_remove(struct device *dev) -{ - struct usb_device *udev = to_usb_device(dev); - - /* if this is only an unbind, not a physical disconnect, then - * unconfigure the device */ - if (udev->state == USB_STATE_CONFIGURED) - usb_set_configuration(udev, 0); - - /* in case the call failed or the device was suspended */ - if (udev->state >= USB_STATE_CONFIGURED) - usb_disable_device(udev, 0); - return 0; -} - -struct device_driver usb_generic_driver = { - .owner = THIS_MODULE, - .name = "usb", - .bus = &usb_bus_type, - .probe = generic_probe, - .remove = generic_remove, -}; - -/* Fun hack to determine if the struct device is a - * usb device or a usb interface. */ -int usb_generic_driver_data; - -#ifdef CONFIG_HOTPLUG - -/* - * Adds a new dynamic USBdevice ID to this driver, - * and cause the driver to probe for all devices again. - */ -static ssize_t store_new_id(struct device_driver *driver, - const char *buf, size_t count) -{ - struct usb_driver *usb_drv = to_usb_driver(driver); - struct usb_dynid *dynid; - u32 idVendor = 0; - u32 idProduct = 0; - int fields = 0; - - fields = sscanf(buf, "%x %x", &idVendor, &idProduct); - if (fields < 2) - return -EINVAL; - - dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); - if (!dynid) - return -ENOMEM; - - INIT_LIST_HEAD(&dynid->node); - dynid->id.idVendor = idVendor; - dynid->id.idProduct = idProduct; - dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE; - - spin_lock(&usb_drv->dynids.lock); - list_add_tail(&usb_drv->dynids.list, &dynid->node); - spin_unlock(&usb_drv->dynids.lock); - - if (get_driver(driver)) { - driver_attach(driver); - put_driver(driver); - } - - return count; -} -static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); - -static int usb_create_newid_file(struct usb_driver *usb_drv) -{ - int error = 0; - - if (usb_drv->no_dynamic_id) - goto exit; - - if (usb_drv->probe != NULL) - error = sysfs_create_file(&usb_drv->driver.kobj, - &driver_attr_new_id.attr); -exit: - return error; -} - -static void usb_remove_newid_file(struct usb_driver *usb_drv) -{ - if (usb_drv->no_dynamic_id) - return; - - if (usb_drv->probe != NULL) - sysfs_remove_file(&usb_drv->driver.kobj, - &driver_attr_new_id.attr); -} - -static void usb_free_dynids(struct usb_driver *usb_drv) -{ - struct usb_dynid *dynid, *n; - - spin_lock(&usb_drv->dynids.lock); - list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) { - list_del(&dynid->node); - kfree(dynid); - } - spin_unlock(&usb_drv->dynids.lock); -} -#else -static inline int usb_create_newid_file(struct usb_driver *usb_drv) -{ - return 0; -} - -static void usb_remove_newid_file(struct usb_driver *usb_drv) -{ -} - -static inline void usb_free_dynids(struct usb_driver *usb_drv) -{ -} -#endif - -static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf, - struct usb_driver *drv) -{ - struct usb_dynid *dynid; - - spin_lock(&drv->dynids.lock); - list_for_each_entry(dynid, &drv->dynids.list, node) { - if (usb_match_one_id(intf, &dynid->id)) { - spin_unlock(&drv->dynids.lock); - return &dynid->id; - } - } - spin_unlock(&drv->dynids.lock); - return NULL; -} - - -/* called from driver core with usb_bus_type.subsys writelock */ -static int usb_probe_interface(struct device *dev) -{ - struct usb_interface * intf = to_usb_interface(dev); - struct usb_driver * driver = to_usb_driver(dev->driver); - const struct usb_device_id *id; - int error = -ENODEV; - - dev_dbg(dev, "%s\n", __FUNCTION__); - - if (!driver->probe) - return error; - /* FIXME we'd much prefer to just resume it ... */ - if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) - return -EHOSTUNREACH; - - id = usb_match_id(intf, driver->id_table); - if (!id) - id = usb_match_dynamic_id(intf, driver); - if (id) { - dev_dbg(dev, "%s - got id\n", __FUNCTION__); - - /* Interface "power state" doesn't correspond to any hardware - * state whatsoever. We use it to record when it's bound to - * a driver that may start I/0: it's not frozen/quiesced. - */ - mark_active(intf); - intf->condition = USB_INTERFACE_BINDING; - error = driver->probe(intf, id); - if (error) { - mark_quiesced(intf); - intf->condition = USB_INTERFACE_UNBOUND; - } else - intf->condition = USB_INTERFACE_BOUND; - } - - return error; -} - -/* called from driver core with usb_bus_type.subsys writelock */ -static int usb_unbind_interface(struct device *dev) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct usb_driver *driver = to_usb_driver(intf->dev.driver); - - intf->condition = USB_INTERFACE_UNBINDING; - - /* release all urbs for this interface */ - usb_disable_interface(interface_to_usbdev(intf), intf); - - if (driver && driver->disconnect) - driver->disconnect(intf); - - /* reset other interface state */ - usb_set_interface(interface_to_usbdev(intf), - intf->altsetting[0].desc.bInterfaceNumber, - 0); - usb_set_intfdata(intf, NULL); - intf->condition = USB_INTERFACE_UNBOUND; - mark_quiesced(intf); - - return 0; -} - -/* returns 0 if no match, 1 if match */ -static int usb_match_one_id(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_host_interface *intf; - struct usb_device *dev; - - /* proc_connectinfo in devio.c may call us with id == NULL. */ - if (id == NULL) - return 0; - - intf = interface->cur_altsetting; - dev = interface_to_usbdev(interface); - - if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && - id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) - return 0; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && - id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) - return 0; - - /* No need to test id->bcdDevice_lo != 0, since 0 is never - greater than any unsigned number. */ - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && - (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) - return 0; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && - (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) - return 0; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && - (id->bDeviceClass != dev->descriptor.bDeviceClass)) - return 0; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && - (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)) - return 0; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && - (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) - return 0; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && - (id->bInterfaceClass != intf->desc.bInterfaceClass)) - return 0; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && - (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) - return 0; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && - (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) - return 0; - - return 1; -} -/** - * usb_match_id - find first usb_device_id matching device or interface - * @interface: the interface of interest - * @id: array of usb_device_id structures, terminated by zero entry - * - * usb_match_id searches an array of usb_device_id's and returns - * the first one matching the device or interface, or null. - * This is used when binding (or rebinding) a driver to an interface. - * Most USB device drivers will use this indirectly, through the usb core, - * but some layered driver frameworks use it directly. - * These device tables are exported with MODULE_DEVICE_TABLE, through - * modutils, to support the driver loading functionality of USB hotplugging. - * - * What Matches: - * - * The "match_flags" element in a usb_device_id controls which - * members are used. If the corresponding bit is set, the - * value in the device_id must match its corresponding member - * in the device or interface descriptor, or else the device_id - * does not match. - * - * "driver_info" is normally used only by device drivers, - * but you can create a wildcard "matches anything" usb_device_id - * as a driver's "modules.usbmap" entry if you provide an id with - * only a nonzero "driver_info" field. If you do this, the USB device - * driver's probe() routine should use additional intelligence to - * decide whether to bind to the specified interface. - * - * What Makes Good usb_device_id Tables: - * - * The match algorithm is very simple, so that intelligence in - * driver selection must come from smart driver id records. - * Unless you have good reasons to use another selection policy, - * provide match elements only in related groups, and order match - * specifiers from specific to general. Use the macros provided - * for that purpose if you can. - * - * The most specific match specifiers use device descriptor - * data. These are commonly used with product-specific matches; - * the USB_DEVICE macro lets you provide vendor and product IDs, - * and you can also match against ranges of product revisions. - * These are widely used for devices with application or vendor - * specific bDeviceClass values. - * - * Matches based on device class/subclass/protocol specifications - * are slightly more general; use the USB_DEVICE_INFO macro, or - * its siblings. These are used with single-function devices - * where bDeviceClass doesn't specify that each interface has - * its own class. - * - * Matches based on interface class/subclass/protocol are the - * most general; they let drivers bind to any interface on a - * multiple-function device. Use the USB_INTERFACE_INFO - * macro, or its siblings, to match class-per-interface style - * devices (as recorded in bDeviceClass). - * - * Within those groups, remember that not all combinations are - * meaningful. For example, don't give a product version range - * without vendor and product IDs; or specify a protocol without - * its associated class and subclass. - */ -const struct usb_device_id *usb_match_id(struct usb_interface *interface, - const struct usb_device_id *id) -{ - /* proc_connectinfo in devio.c may call us with id == NULL. */ - if (id == NULL) - return NULL; - - /* It is important to check that id->driver_info is nonzero, - since an entry that is all zeroes except for a nonzero - id->driver_info is the way to create an entry that - indicates that the driver want to examine every - device and interface. */ - for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || - id->driver_info; id++) { - if (usb_match_one_id(interface, id)) - return id; - } - - return NULL; -} -EXPORT_SYMBOL_GPL(usb_match_id); - -int usb_device_match(struct device *dev, struct device_driver *drv) -{ - struct usb_interface *intf; - struct usb_driver *usb_drv; - const struct usb_device_id *id; - - /* check for generic driver, which we don't match any device with */ - if (drv == &usb_generic_driver) - return 0; - - intf = to_usb_interface(dev); - usb_drv = to_usb_driver(drv); - - id = usb_match_id(intf, usb_drv->id_table); - if (id) - return 1; - - id = usb_match_dynamic_id(intf, usb_drv); - if (id) - return 1; - return 0; -} - -/** - * usb_register_driver - register a USB driver - * @new_driver: USB operations for the driver - * @owner: module owner of this driver. - * - * Registers a USB driver with the USB core. The list of unattached - * interfaces will be rescanned whenever a new driver is added, allowing - * the new driver to attach to any recognized devices. - * Returns a negative error code on failure and 0 on success. - * - * NOTE: if you want your driver to use the USB major number, you must call - * usb_register_dev() to enable that functionality. This function no longer - * takes care of that. - */ -int usb_register_driver(struct usb_driver *new_driver, struct module *owner) -{ - int retval = 0; - - if (usb_disabled()) - return -ENODEV; - - new_driver->driver.name = (char *)new_driver->name; - new_driver->driver.bus = &usb_bus_type; - new_driver->driver.probe = usb_probe_interface; - new_driver->driver.remove = usb_unbind_interface; - new_driver->driver.owner = owner; - spin_lock_init(&new_driver->dynids.lock); - INIT_LIST_HEAD(&new_driver->dynids.list); - - retval = driver_register(&new_driver->driver); - - if (!retval) { - pr_info("%s: registered new driver %s\n", - usbcore_name, new_driver->name); - usbfs_update_special(); - usb_create_newid_file(new_driver); - } else { - printk(KERN_ERR "%s: error %d registering driver %s\n", - usbcore_name, retval, new_driver->name); - } - - return retval; -} -EXPORT_SYMBOL_GPL(usb_register_driver); - -/** - * usb_deregister - unregister a USB driver - * @driver: USB operations of the driver to unregister - * Context: must be able to sleep - * - * Unlinks the specified driver from the internal USB driver list. - * - * NOTE: If you called usb_register_dev(), you still need to call - * usb_deregister_dev() to clean up your driver's allocated minor numbers, - * this * call will no longer do it for you. - */ -void usb_deregister(struct usb_driver *driver) -{ - pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); - - usb_remove_newid_file(driver); - usb_free_dynids(driver); - driver_unregister(&driver->driver); - - usbfs_update_special(); -} -EXPORT_SYMBOL_GPL(usb_deregister); diff --git a/trunk/drivers/usb/core/hcd.c b/trunk/drivers/usb/core/hcd.c index 0018bbc4de34..da24c31ee00d 100644 --- a/trunk/drivers/usb/core/hcd.c +++ b/trunk/drivers/usb/core/hcd.c @@ -857,7 +857,9 @@ static int register_root_hub (struct usb_device *usb_dev, return (retval < 0) ? retval : -EMSGSIZE; } + usb_lock_device (usb_dev); retval = usb_new_device (usb_dev); + usb_unlock_device (usb_dev); if (retval) { usb_dev->bus->root_hub = NULL; dev_err (parent_dev, "can't register root hub for %s, %d\n", @@ -1825,6 +1827,8 @@ int usb_add_hcd(struct usb_hcd *hcd, retval = -ENOMEM; goto err_allocate_root_hub; } + rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : + USB_SPEED_FULL; /* Although in principle hcd->driver->start() might need to use rhdev, * none of the current drivers do. @@ -1842,9 +1846,6 @@ int usb_add_hcd(struct usb_hcd *hcd, dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); hcd->remote_wakeup = hcd->can_wakeup; - rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : - USB_SPEED_FULL; - rhdev->bus_mA = min(500u, hcd->power_budget); if ((retval = register_root_hub(rhdev, hcd)) != 0) goto err_register_root_hub; @@ -1890,10 +1891,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) spin_lock_irq (&hcd_root_hub_lock); hcd->rh_registered = 0; spin_unlock_irq (&hcd_root_hub_lock); - - down(&usb_bus_list_lock); usb_disconnect(&hcd->self.root_hub); - up(&usb_bus_list_lock); hcd->poll_rh = 0; del_timer_sync(&hcd->rh_timer); diff --git a/trunk/drivers/usb/core/hcd.h b/trunk/drivers/usb/core/hcd.h index 591b5aad1a18..c8a1b350e2cf 100644 --- a/trunk/drivers/usb/core/hcd.h +++ b/trunk/drivers/usb/core/hcd.h @@ -380,7 +380,6 @@ extern int usb_find_interface_driver (struct usb_device *dev, #ifdef CONFIG_PM extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd); extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); -extern void usb_root_hub_lost_power (struct usb_device *rhdev); extern int hcd_bus_suspend (struct usb_bus *bus); extern int hcd_bus_resume (struct usb_bus *bus); #else diff --git a/trunk/drivers/usb/core/hub.c b/trunk/drivers/usb/core/hub.c index 650d5ee5871b..f78bd124d290 100644 --- a/trunk/drivers/usb/core/hub.c +++ b/trunk/drivers/usb/core/hub.c @@ -32,7 +32,7 @@ #include "hub.h" /* Protect struct usb_device->state and ->children members - * Note: Both are also protected by ->dev.sem, except that ->state can + * Note: Both are also protected by ->serialize, except that ->state can * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ static DEFINE_SPINLOCK(device_state_lock); @@ -515,31 +515,6 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) return ret; } - -/* caller has locked the hub device */ -static void hub_pre_reset(struct usb_hub *hub, int disable_ports) -{ - struct usb_device *hdev = hub->hdev; - int port1; - - for (port1 = 1; port1 <= hdev->maxchild; ++port1) { - if (hdev->children[port1 - 1]) { - usb_disconnect(&hdev->children[port1 - 1]); - if (disable_ports) - hub_port_disable(hub, port1, 0); - } - } - hub_quiesce(hub); -} - -/* caller has locked the hub device */ -static void hub_post_reset(struct usb_hub *hub) -{ - hub_activate(hub); - hub_power_on(hub); -} - - static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { @@ -702,40 +677,26 @@ static int hub_configure(struct usb_hub *hub, * and battery-powered root hubs (may provide just 8 mA). */ ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus); - if (ret < 2) { + if (ret < 0) { message = "can't get hub status"; goto fail; } le16_to_cpus(&hubstatus); if (hdev == hdev->bus->root_hub) { - if (hdev->bus_mA == 0 || hdev->bus_mA >= 500) - hub->mA_per_port = 500; - else { - hub->mA_per_port = hdev->bus_mA; - hub->limited_power = 1; - } + struct usb_hcd *hcd = + container_of(hdev->bus, struct usb_hcd, self); + + hub->power_budget = min(500u, hcd->power_budget) / 2; } else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", hub->descriptor->bHubContrCurrent); - hub->limited_power = 1; - if (hdev->maxchild > 0) { - int remaining = hdev->bus_mA - - hub->descriptor->bHubContrCurrent; - - if (remaining < hdev->maxchild * 100) - dev_warn(hub_dev, - "insufficient power available " - "to use all downstream ports\n"); - hub->mA_per_port = 100; /* 7.2.1.1 */ - } - } else { /* Self-powered external hub */ - /* FIXME: What about battery-powered external hubs that - * provide less current per port? */ - hub->mA_per_port = 500; + hub->power_budget = (501 - hub->descriptor->bHubContrCurrent) + / 2; } - if (hub->mA_per_port < 500) - dev_dbg(hub_dev, "%umA bus power budget for each child\n", - hub->mA_per_port); + if (hub->power_budget) + dev_dbg(hub_dev, "%dmA bus power budget for children\n", + hub->power_budget * 2); + ret = hub_hub_status(hub, &hubstatus, &hubchange); if (ret < 0) { @@ -789,10 +750,29 @@ static int hub_configure(struct usb_hub *hub, static unsigned highspeed_hubs; +/* Called after the hub driver is unbound from a hub with children */ +static void hub_remove_children_work(void *__hub) +{ + struct usb_hub *hub = __hub; + struct usb_device *hdev = hub->hdev; + int i; + + kfree(hub); + + usb_lock_device(hdev); + for (i = 0; i < hdev->maxchild; ++i) { + if (hdev->children[i]) + usb_disconnect(&hdev->children[i]); + } + usb_unlock_device(hdev); + usb_put_dev(hdev); +} + static void hub_disconnect(struct usb_interface *intf) { struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev; + int n, port1; usb_set_intfdata (intf, NULL); hdev = hub->hdev; @@ -800,9 +780,7 @@ static void hub_disconnect(struct usb_interface *intf) if (hdev->speed == USB_SPEED_HIGH) highspeed_hubs--; - /* Disconnect all children and quiesce the hub */ - hub_pre_reset(hub, 1); - + hub_quiesce(hub); usb_free_urb(hub->urb); hub->urb = NULL; @@ -822,7 +800,27 @@ static void hub_disconnect(struct usb_interface *intf) hub->buffer = NULL; } - kfree(hub); + /* If there are any children then this is an unbind only, not a + * physical disconnection. The active ports must be disabled + * and later on we must call usb_disconnect(). We can't call + * it now because we may not hold the hub's device lock. + */ + n = 0; + for (port1 = 1; port1 <= hdev->maxchild; ++port1) { + if (hdev->children[port1 - 1]) { + ++n; + hub_port_disable(hub, port1, 1); + } + } + + if (n == 0) + kfree(hub); + else { + /* Reuse the hub->leds work_struct for our own purposes */ + INIT_WORK(&hub->leds, hub_remove_children_work, hub); + schedule_work(&hub->leds); + usb_get_dev(hdev); + } } static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -919,6 +917,26 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) } } +/* caller has locked the hub device */ +static void hub_pre_reset(struct usb_hub *hub) +{ + struct usb_device *hdev = hub->hdev; + int i; + + for (i = 0; i < hdev->maxchild; ++i) { + if (hdev->children[i]) + usb_disconnect(&hdev->children[i]); + } + hub_quiesce(hub); +} + +/* caller has locked the hub device */ +static void hub_post_reset(struct usb_hub *hub) +{ + hub_activate(hub); + hub_power_on(hub); +} + /* grab device/port lock, returning index of that port (zero based). * protects the upstream link used by this device from concurrent @@ -946,21 +964,24 @@ static int locktree(struct usb_device *udev) t = locktree(hdev); if (t < 0) return t; + for (t = 0; t < hdev->maxchild; t++) { + if (hdev->children[t] == udev) { + /* everything is fail-fast once disconnect + * processing starts + */ + if (udev->state == USB_STATE_NOTATTACHED) + break; - /* everything is fail-fast once disconnect - * processing starts - */ - if (udev->state == USB_STATE_NOTATTACHED) { - usb_unlock_device(hdev); - return -ENODEV; + /* when everyone grabs locks top->bottom, + * non-overlapping work may be concurrent + */ + down(&udev->serialize); + up(&hdev->serialize); + return t + 1; + } } - - /* when everyone grabs locks top->bottom, - * non-overlapping work may be concurrent - */ - usb_lock_device(udev); usb_unlock_device(hdev); - return udev->portnum; + return -ENODEV; } static void recursively_mark_NOTATTACHED(struct usb_device *udev) @@ -1018,39 +1039,6 @@ void usb_set_device_state(struct usb_device *udev, EXPORT_SYMBOL(usb_set_device_state); -#ifdef CONFIG_PM - -/** - * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power - * @rhdev: struct usb_device for the root hub - * - * The USB host controller driver calls this function when its root hub - * is resumed and Vbus power has been interrupted or the controller - * has been reset. The routine marks all the children of the root hub - * as NOTATTACHED and marks logical connect-change events on their ports. - */ -void usb_root_hub_lost_power(struct usb_device *rhdev) -{ - struct usb_hub *hub; - int port1; - unsigned long flags; - - dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); - spin_lock_irqsave(&device_state_lock, flags); - hub = hdev_to_hub(rhdev); - for (port1 = 1; port1 <= rhdev->maxchild; ++port1) { - if (rhdev->children[port1 - 1]) { - recursively_mark_NOTATTACHED( - rhdev->children[port1 - 1]); - set_bit(port1, hub->change_bits); - } - } - spin_unlock_irqrestore(&device_state_lock, flags); -} -EXPORT_SYMBOL_GPL(usb_root_hub_lost_power); - -#endif - static void choose_address(struct usb_device *udev) { int devnum; @@ -1111,9 +1099,15 @@ void usb_disconnect(struct usb_device **pdev) * this quiesces everyting except pending urbs. */ usb_set_device_state(udev, USB_STATE_NOTATTACHED); - dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); - usb_lock_device(udev); + /* lock the bus list on behalf of HCDs unregistering their root hubs */ + if (!udev->parent) { + down(&usb_bus_list_lock); + usb_lock_device(udev); + } else + down(&udev->serialize); + + dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); /* Free up all the children before we remove this device */ for (i = 0; i < USB_MAXCHILDREN; i++) { @@ -1142,112 +1136,54 @@ void usb_disconnect(struct usb_device **pdev) *pdev = NULL; spin_unlock_irq(&device_state_lock); - usb_unlock_device(udev); + if (!udev->parent) { + usb_unlock_device(udev); + up(&usb_bus_list_lock); + } else + up(&udev->serialize); device_unregister(&udev->dev); } -static inline const char *plural(int n) -{ - return (n == 1 ? "" : "s"); -} - static int choose_configuration(struct usb_device *udev) { - int i; - u16 devstatus; - int bus_powered; - int num_configs; - struct usb_host_config *c, *best; - - /* If this fails, assume the device is bus-powered */ - devstatus = 0; - usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); - le16_to_cpus(&devstatus); - bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0); - dev_dbg(&udev->dev, "device is %s-powered\n", - bus_powered ? "bus" : "self"); - - best = NULL; - c = udev->config; - num_configs = udev->descriptor.bNumConfigurations; - for (i = 0; i < num_configs; (i++, c++)) { - struct usb_interface_descriptor *desc = - &c->intf_cache[0]->altsetting->desc; - - /* - * HP's USB bus-powered keyboard has only one configuration - * and it claims to be self-powered; other devices may have - * similar errors in their descriptors. If the next test - * were allowed to execute, such configurations would always - * be rejected and the devices would not work as expected. - */ -#if 0 - /* Rule out self-powered configs for a bus-powered device */ - if (bus_powered && (c->desc.bmAttributes & - USB_CONFIG_ATT_SELFPOWER)) - continue; -#endif + int c, i; - /* - * The next test may not be as effective as it should be. - * Some hubs have errors in their descriptor, claiming - * to be self-powered when they are really bus-powered. - * We will overestimate the amount of current such hubs - * make available for each port. - * - * This is a fairly benign sort of failure. It won't - * cause us to reject configurations that we should have - * accepted. - */ + /* NOTE: this should interact with hub power budgeting */ - /* Rule out configs that draw too much bus current */ - if (c->desc.bMaxPower * 2 > udev->bus_mA) - continue; + c = udev->config[0].desc.bConfigurationValue; + if (udev->descriptor.bNumConfigurations != 1) { + for (i = 0; i < udev->descriptor.bNumConfigurations; i++) { + struct usb_interface_descriptor *desc; - /* If the first config's first interface is COMM/2/0xff - * (MSFT RNDIS), rule it out unless Linux has host-side - * RNDIS support. */ - if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM - && desc->bInterfaceSubClass == 2 - && desc->bInterfaceProtocol == 0xff) { -#ifndef CONFIG_USB_NET_RNDIS - continue; -#else - best = c; -#endif - } - - /* From the remaining configs, choose the first one whose - * first interface is for a non-vendor-specific class. - * Reason: Linux is more likely to have a class driver - * than a vendor-specific driver. */ - else if (udev->descriptor.bDeviceClass != - USB_CLASS_VENDOR_SPEC && - desc->bInterfaceClass != - USB_CLASS_VENDOR_SPEC) { - best = c; + /* heuristic: Linux is more likely to have class + * drivers, so avoid vendor-specific interfaces. + */ + desc = &udev->config[i].intf_cache[0] + ->altsetting->desc; + if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) + continue; + /* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS. + * MSFT needs this to be the first config; never use + * it as the default unless Linux has host-side RNDIS. + * A second config would ideally be CDC-Ethernet, but + * may instead be the "vendor specific" CDC subset + * long used by ARM Linux for sa1100 or pxa255. + */ + if (desc->bInterfaceClass == USB_CLASS_COMM + && desc->bInterfaceSubClass == 2 + && desc->bInterfaceProtocol == 0xff) { + c = udev->config[1].desc.bConfigurationValue; + continue; + } + c = udev->config[i].desc.bConfigurationValue; break; } - - /* If all the remaining configs are vendor-specific, - * choose the first one. */ - else if (!best) - best = c; - } - - if (best) { - i = best->desc.bConfigurationValue; dev_info(&udev->dev, - "configuration #%d chosen from %d choice%s\n", - i, num_configs, plural(num_configs)); - } else { - i = -1; - dev_warn(&udev->dev, - "no configuration chosen from %d choice%s\n", - num_configs, plural(num_configs)); + "configuration #%d chosen from %d choices\n", + c, udev->descriptor.bNumConfigurations); } - return i; + return c; } #ifdef DEBUG @@ -1274,8 +1210,8 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) * * This is called with devices which have been enumerated, but not yet * configured. The device descriptor is available, but not descriptors - * for any device configuration. The caller must have locked either - * the parent hub (if udev is a normal device) or else the + * for any device configuration. The caller must have locked udev and + * either the parent hub (if udev is a normal device) or else the * usb_bus_list_lock (if udev is a root hub). The parent's pointer to * udev has already been installed, but udev is not yet visible through * sysfs or other filesystem code. @@ -1285,7 +1221,8 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) * * This call is synchronous, and may not be used in an interrupt context. * - * Only the hub driver or root-hub registrar should ever call this. + * Only the hub driver should ever call this; root hub registration + * uses it indirectly. */ int usb_new_device(struct usb_device *udev) { @@ -1332,9 +1269,15 @@ int usb_new_device(struct usb_device *udev) le16_to_cpu(udev->config[0].desc.wTotalLength), USB_DT_OTG, (void **) &desc) == 0) { if (desc->bmAttributes & USB_OTG_HNP) { - unsigned port1 = udev->portnum; + unsigned port1; struct usb_device *root = udev->parent; + for (port1 = 1; port1 <= root->maxchild; + port1++) { + if (root->children[port1-1] == udev) + break; + } + dev_info(&udev->dev, "Dual-Role OTG device on %sHNP port\n", (port1 == bus->otg_port) @@ -1388,27 +1331,27 @@ int usb_new_device(struct usb_device *udev) } usb_create_sysfs_dev_files (udev); - usb_lock_device(udev); - /* choose and set the configuration. that registers the interfaces * with the driver core, and lets usb device drivers bind to them. */ c = choose_configuration(udev); - if (c >= 0) { + if (c < 0) + dev_warn(&udev->dev, + "can't choose an initial configuration\n"); + else { err = usb_set_configuration(udev, c); if (err) { dev_err(&udev->dev, "can't set config #%d, error %d\n", c, err); - /* This need not be fatal. The user can try to - * set other configurations. */ + usb_remove_sysfs_dev_files(udev); + device_del(&udev->dev); + goto fail; } } /* USB device state == configured ... usable */ usb_notify_add_device(udev); - usb_unlock_device(udev); - return 0; fail: @@ -1711,9 +1654,15 @@ static int __usb_suspend_device (struct usb_device *udev, int port1) int usb_suspend_device(struct usb_device *udev) { #ifdef CONFIG_USB_SUSPEND - if (udev->state == USB_STATE_NOTATTACHED) - return -ENODEV; - return __usb_suspend_device(udev, udev->portnum); + int port1, status; + + port1 = locktree(udev); + if (port1 < 0) + return port1; + + status = __usb_suspend_device(udev, port1); + usb_unlock_device(udev); + return status; #else /* NOTE: udev->state unchanged, it's not lying ... */ udev->dev.power.power_state = PMSG_SUSPEND; @@ -1745,14 +1694,13 @@ static int finish_device_resume(struct usb_device *udev) usb_set_device_state(udev, udev->actconfig ? USB_STATE_CONFIGURED : USB_STATE_ADDRESS); - udev->dev.power.power_state = PMSG_ON; /* 10.5.4.5 says be sure devices in the tree are still there. * For now let's assume the device didn't go crazy on resume, * and device drivers will know about any resume quirks. */ status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); - if (status < 2) + if (status < 0) dev_dbg(&udev->dev, "gone after usb resume? status %d\n", status); @@ -1761,7 +1709,7 @@ static int finish_device_resume(struct usb_device *udev) int (*resume)(struct device *); le16_to_cpus(&devstatus); - if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) + if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP) && udev->parent) { status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), @@ -1781,14 +1729,8 @@ static int finish_device_resume(struct usb_device *udev) * may have a child resume event to deal with soon */ resume = udev->dev.bus->resume; - for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { - struct device *dev = - &udev->actconfig->interface[i]->dev; - - down(&dev->sem); - (void) resume(dev); - up(&dev->sem); - } + for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) + (void) resume(&udev->actconfig->interface[i]->dev); status = 0; } else if (udev->devnum <= 0) { @@ -1871,10 +1813,11 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) */ int usb_resume_device(struct usb_device *udev) { - int status; + int port1, status; - if (udev->state == USB_STATE_NOTATTACHED) - return -ENODEV; + port1 = locktree(udev); + if (port1 < 0) + return port1; #ifdef CONFIG_USB_SUSPEND /* selective resume of one downstream hub-to-device port */ @@ -1883,7 +1826,7 @@ int usb_resume_device(struct usb_device *udev) // NOTE swsusp may bork us, device state being wrong... // NOTE this fails if parent is also suspended... status = hub_port_resume(hdev_to_hub(udev->parent), - udev->portnum, udev); + port1, udev); } else status = 0; } else @@ -1893,11 +1836,13 @@ int usb_resume_device(struct usb_device *udev) dev_dbg(&udev->dev, "can't resume, status %d\n", status); + usb_unlock_device(udev); + /* rebind drivers that had no suspend() */ if (status == 0) { - usb_unlock_device(udev); + usb_lock_all_devices(); bus_rescan_devices(&usb_bus_type); - usb_lock_device(udev); + usb_unlock_all_devices(); } return status; } @@ -1911,14 +1856,14 @@ static int remote_wakeup(struct usb_device *udev) /* don't repeat RESUME sequence if this device * was already woken up by some other task */ - usb_lock_device(udev); + down(&udev->serialize); if (udev->state == USB_STATE_SUSPENDED) { dev_dbg(&udev->dev, "RESUME (wakeup)\n"); /* TRSMRCY = 10 msec */ msleep(10); status = finish_device_resume(udev); } - usb_unlock_device(udev); + up(&udev->serialize); #endif return status; } @@ -2019,7 +1964,7 @@ static int hub_resume(struct usb_interface *intf) if (!udev || status < 0) continue; - usb_lock_device(udev); + down (&udev->serialize); if (portstat & USB_PORT_STAT_SUSPEND) status = hub_port_resume(hub, port1, udev); else { @@ -2030,7 +1975,7 @@ static int hub_resume(struct usb_interface *intf) hub_port_logical_disconnect(hub, port1); } } - usb_unlock_device(udev); + up(&udev->serialize); } } #endif @@ -2414,36 +2359,39 @@ hub_power_remaining (struct usb_hub *hub) { struct usb_device *hdev = hub->hdev; int remaining; - int port1; + unsigned i; - if (!hub->limited_power) + remaining = hub->power_budget; + if (!remaining) /* self-powered */ return 0; - remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent; - for (port1 = 1; port1 <= hdev->maxchild; ++port1) { - struct usb_device *udev = hdev->children[port1 - 1]; - int delta; + for (i = 0; i < hdev->maxchild; i++) { + struct usb_device *udev = hdev->children[i]; + int delta, ceiling; if (!udev) continue; - /* Unconfigured devices may not use more than 100mA, - * or 8mA for OTG ports */ + /* 100mA per-port ceiling, or 8mA for OTG ports */ + if (i != (udev->bus->otg_port - 1) || hdev->parent) + ceiling = 50; + else + ceiling = 4; + if (udev->actconfig) - delta = udev->actconfig->desc.bMaxPower * 2; - else if (port1 != udev->bus->otg_port || hdev->parent) - delta = 100; + delta = udev->actconfig->desc.bMaxPower; else - delta = 8; - if (delta > hub->mA_per_port) - dev_warn(&udev->dev, "%dmA is over %umA budget " - "for port %d!\n", - delta, hub->mA_per_port, port1); + delta = ceiling; + // dev_dbg(&udev->dev, "budgeted %dmA\n", 2 * delta); + if (delta > ceiling) + dev_warn(&udev->dev, "%dmA over %dmA budget!\n", + 2 * (delta - ceiling), 2 * ceiling); remaining -= delta; } if (remaining < 0) { - dev_warn(hub->intfdev, "%dmA over power budget!\n", - - remaining); + dev_warn(hub->intfdev, + "%dmA over power budget!\n", + -2 * remaining); remaining = 0; } return remaining; @@ -2538,8 +2486,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, usb_set_device_state(udev, USB_STATE_POWERED); udev->speed = USB_SPEED_UNKNOWN; - udev->bus_mA = hub->mA_per_port; - + /* set the address */ choose_address(udev); if (udev->devnum <= 0) { @@ -2559,16 +2506,16 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, * on the parent. */ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB - && udev->bus_mA <= 100) { + && hub->power_budget) { u16 devstat; status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstat); - if (status < 2) { + if (status < 0) { dev_dbg(&udev->dev, "get status %d ?\n", status); goto loop_disable; } - le16_to_cpus(&devstat); + cpu_to_le16s(&devstat); if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) { dev_err(&udev->dev, "can't connect bus-powered hub " @@ -2593,6 +2540,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, * udev becomes globally accessible, although presumably * no one will look at it until hdev is unlocked. */ + down (&udev->serialize); status = 0; /* We mustn't add new devices if the parent hub has @@ -2616,12 +2564,15 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, } } + up (&udev->serialize); if (status) goto loop_disable; status = hub_power_remaining(hub); if (status) - dev_dbg(hub_dev, "%dmA power budget left\n", status); + dev_dbg(hub_dev, + "%dmA power budget left\n", + 2 * status); return; @@ -2697,8 +2648,6 @@ static void hub_events(void) if (i) { dpm_runtime_resume(&hdev->dev); dpm_runtime_resume(&intf->dev); - usb_put_intf(intf); - continue; } /* Lock the device, then check to see if we were @@ -2712,7 +2661,7 @@ static void hub_events(void) /* If the hub has died, clean up after it */ if (hdev->state == USB_STATE_NOTATTACHED) { - hub_pre_reset(hub, 0); + hub_pre_reset(hub); goto loop; } @@ -2835,11 +2784,6 @@ static void hub_events(void) if (hubchange & HUB_CHANGE_LOCAL_POWER) { dev_dbg (hub_dev, "power change\n"); clear_hub_feature(hdev, C_HUB_LOCAL_POWER); - if (hubstatus & HUB_STATUS_LOCAL_POWER) - /* FIXME: Is this always true? */ - hub->limited_power = 0; - else - hub->limited_power = 1; } if (hubchange & HUB_CHANGE_OVERCURRENT) { dev_dbg (hub_dev, "overcurrent change\n"); @@ -2888,6 +2832,7 @@ static struct usb_device_id hub_id_table [] = { MODULE_DEVICE_TABLE (usb, hub_id_table); static struct usb_driver hub_driver = { + .owner = THIS_MODULE, .name = "hub", .probe = hub_probe, .disconnect = hub_disconnect, @@ -2999,8 +2944,7 @@ int usb_reset_device(struct usb_device *udev) struct usb_hub *parent_hub; struct usb_device_descriptor descriptor = udev->descriptor; struct usb_hub *hub = NULL; - int i, ret = 0; - int port1 = udev->portnum; + int i, ret = 0, port1 = -1; if (udev->state == USB_STATE_NOTATTACHED || udev->state == USB_STATE_SUSPENDED) { @@ -3014,6 +2958,18 @@ int usb_reset_device(struct usb_device *udev) dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__); return -EISDIR; } + + for (i = 0; i < parent_hdev->maxchild; i++) + if (parent_hdev->children[i] == udev) { + port1 = i + 1; + break; + } + + if (port1 < 0) { + /* If this ever happens, it's very bad */ + dev_err(&udev->dev, "Can't locate device's port!\n"); + return -ENOENT; + } parent_hub = hdev_to_hub(parent_hdev); /* If we're resetting an active hub, take some special actions */ @@ -3021,7 +2977,7 @@ int usb_reset_device(struct usb_device *udev) udev->actconfig->interface[0]->dev.driver == &hub_driver.driver && (hub = hdev_to_hub(udev)) != NULL) { - hub_pre_reset(hub, 0); + hub_pre_reset(hub); } set_bit(port1, parent_hub->busy_bits); diff --git a/trunk/drivers/usb/core/hub.h b/trunk/drivers/usb/core/hub.h index 29d5f45a8456..bf23f8978024 100644 --- a/trunk/drivers/usb/core/hub.h +++ b/trunk/drivers/usb/core/hub.h @@ -220,9 +220,8 @@ struct usb_hub { struct usb_hub_descriptor *descriptor; /* class descriptor */ struct usb_tt tt; /* Transaction Translator */ - unsigned mA_per_port; /* current for each child */ + u8 power_budget; /* in 2mA units; or zero */ - unsigned limited_power:1; unsigned quiescing:1; unsigned activating:1; unsigned resume_root_hub:1; diff --git a/trunk/drivers/usb/core/message.c b/trunk/drivers/usb/core/message.c index 319de03944e7..fe74f99ca5f4 100644 --- a/trunk/drivers/usb/core/message.c +++ b/trunk/drivers/usb/core/message.c @@ -1387,12 +1387,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (dev->state != USB_STATE_ADDRESS) usb_disable_device (dev, 1); // Skip ep0 - i = dev->bus_mA - cp->desc.bMaxPower * 2; - if (i < 0) - dev_warn(&dev->dev, "new config #%d exceeds power " - "limit by %dmA\n", - configuration, -i); - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) diff --git a/trunk/drivers/usb/core/usb.c b/trunk/drivers/usb/core/usb.c index 56a3520863a9..e80ef9467825 100644 --- a/trunk/drivers/usb/core/usb.c +++ b/trunk/drivers/usb/core/usb.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -46,7 +47,165 @@ const char *usbcore_name = "usbcore"; static int nousb; /* Disable USB when built into kernel image */ + /* Not honored on modular build */ +static DECLARE_RWSEM(usb_all_devices_rwsem); + + +static int generic_probe (struct device *dev) +{ + return 0; +} +static int generic_remove (struct device *dev) +{ + struct usb_device *udev = to_usb_device(dev); + + /* if this is only an unbind, not a physical disconnect, then + * unconfigure the device */ + if (udev->state == USB_STATE_CONFIGURED) + usb_set_configuration(udev, 0); + + /* in case the call failed or the device was suspended */ + if (udev->state >= USB_STATE_CONFIGURED) + usb_disable_device(udev, 0); + return 0; +} + +static struct device_driver usb_generic_driver = { + .owner = THIS_MODULE, + .name = "usb", + .bus = &usb_bus_type, + .probe = generic_probe, + .remove = generic_remove, +}; + +static int usb_generic_driver_data; + +/* called from driver core with usb_bus_type.subsys writelock */ +static int usb_probe_interface(struct device *dev) +{ + struct usb_interface * intf = to_usb_interface(dev); + struct usb_driver * driver = to_usb_driver(dev->driver); + const struct usb_device_id *id; + int error = -ENODEV; + + dev_dbg(dev, "%s\n", __FUNCTION__); + + if (!driver->probe) + return error; + /* FIXME we'd much prefer to just resume it ... */ + if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + + id = usb_match_id (intf, driver->id_table); + if (id) { + dev_dbg (dev, "%s - got id\n", __FUNCTION__); + + /* Interface "power state" doesn't correspond to any hardware + * state whatsoever. We use it to record when it's bound to + * a driver that may start I/0: it's not frozen/quiesced. + */ + mark_active(intf); + intf->condition = USB_INTERFACE_BINDING; + error = driver->probe (intf, id); + if (error) { + mark_quiesced(intf); + intf->condition = USB_INTERFACE_UNBOUND; + } else + intf->condition = USB_INTERFACE_BOUND; + } + + return error; +} + +/* called from driver core with usb_bus_type.subsys writelock */ +static int usb_unbind_interface(struct device *dev) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_driver *driver = to_usb_driver(intf->dev.driver); + + intf->condition = USB_INTERFACE_UNBINDING; + + /* release all urbs for this interface */ + usb_disable_interface(interface_to_usbdev(intf), intf); + + if (driver && driver->disconnect) + driver->disconnect(intf); + + /* reset other interface state */ + usb_set_interface(interface_to_usbdev(intf), + intf->altsetting[0].desc.bInterfaceNumber, + 0); + usb_set_intfdata(intf, NULL); + intf->condition = USB_INTERFACE_UNBOUND; + mark_quiesced(intf); + + return 0; +} + +/** + * usb_register - register a USB driver + * @new_driver: USB operations for the driver + * + * Registers a USB driver with the USB core. The list of unattached + * interfaces will be rescanned whenever a new driver is added, allowing + * the new driver to attach to any recognized devices. + * Returns a negative error code on failure and 0 on success. + * + * NOTE: if you want your driver to use the USB major number, you must call + * usb_register_dev() to enable that functionality. This function no longer + * takes care of that. + */ +int usb_register(struct usb_driver *new_driver) +{ + int retval = 0; + + if (nousb) + return -ENODEV; + + new_driver->driver.name = (char *)new_driver->name; + new_driver->driver.bus = &usb_bus_type; + new_driver->driver.probe = usb_probe_interface; + new_driver->driver.remove = usb_unbind_interface; + new_driver->driver.owner = new_driver->owner; + + usb_lock_all_devices(); + retval = driver_register(&new_driver->driver); + usb_unlock_all_devices(); + + if (!retval) { + pr_info("%s: registered new driver %s\n", + usbcore_name, new_driver->name); + usbfs_update_special(); + } else { + printk(KERN_ERR "%s: error %d registering driver %s\n", + usbcore_name, retval, new_driver->name); + } + + return retval; +} + +/** + * usb_deregister - unregister a USB driver + * @driver: USB operations of the driver to unregister + * Context: must be able to sleep + * + * Unlinks the specified driver from the internal USB driver list. + * + * NOTE: If you called usb_register_dev(), you still need to call + * usb_deregister_dev() to clean up your driver's allocated minor numbers, + * this * call will no longer do it for you. + */ +void usb_deregister(struct usb_driver *driver) +{ + pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); + + usb_lock_all_devices(); + driver_unregister (&driver->driver); + usb_unlock_all_devices(); + + usbfs_update_special(); +} /** * usb_ifnum_to_if - get the interface object with a given interface number @@ -192,23 +351,152 @@ void usb_driver_release_interface(struct usb_driver *driver, iface->condition = USB_INTERFACE_UNBOUND; mark_quiesced(iface); } -struct find_interface_arg { - int minor; - struct usb_interface *interface; -}; + +/** + * usb_match_id - find first usb_device_id matching device or interface + * @interface: the interface of interest + * @id: array of usb_device_id structures, terminated by zero entry + * + * usb_match_id searches an array of usb_device_id's and returns + * the first one matching the device or interface, or null. + * This is used when binding (or rebinding) a driver to an interface. + * Most USB device drivers will use this indirectly, through the usb core, + * but some layered driver frameworks use it directly. + * These device tables are exported with MODULE_DEVICE_TABLE, through + * modutils and "modules.usbmap", to support the driver loading + * functionality of USB hotplugging. + * + * What Matches: + * + * The "match_flags" element in a usb_device_id controls which + * members are used. If the corresponding bit is set, the + * value in the device_id must match its corresponding member + * in the device or interface descriptor, or else the device_id + * does not match. + * + * "driver_info" is normally used only by device drivers, + * but you can create a wildcard "matches anything" usb_device_id + * as a driver's "modules.usbmap" entry if you provide an id with + * only a nonzero "driver_info" field. If you do this, the USB device + * driver's probe() routine should use additional intelligence to + * decide whether to bind to the specified interface. + * + * What Makes Good usb_device_id Tables: + * + * The match algorithm is very simple, so that intelligence in + * driver selection must come from smart driver id records. + * Unless you have good reasons to use another selection policy, + * provide match elements only in related groups, and order match + * specifiers from specific to general. Use the macros provided + * for that purpose if you can. + * + * The most specific match specifiers use device descriptor + * data. These are commonly used with product-specific matches; + * the USB_DEVICE macro lets you provide vendor and product IDs, + * and you can also match against ranges of product revisions. + * These are widely used for devices with application or vendor + * specific bDeviceClass values. + * + * Matches based on device class/subclass/protocol specifications + * are slightly more general; use the USB_DEVICE_INFO macro, or + * its siblings. These are used with single-function devices + * where bDeviceClass doesn't specify that each interface has + * its own class. + * + * Matches based on interface class/subclass/protocol are the + * most general; they let drivers bind to any interface on a + * multiple-function device. Use the USB_INTERFACE_INFO + * macro, or its siblings, to match class-per-interface style + * devices (as recorded in bDeviceClass). + * + * Within those groups, remember that not all combinations are + * meaningful. For example, don't give a product version range + * without vendor and product IDs; or specify a protocol without + * its associated class and subclass. + */ +const struct usb_device_id * +usb_match_id(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_host_interface *intf; + struct usb_device *dev; + + /* proc_connectinfo in devio.c may call us with id == NULL. */ + if (id == NULL) + return NULL; + + intf = interface->cur_altsetting; + dev = interface_to_usbdev(interface); + + /* It is important to check that id->driver_info is nonzero, + since an entry that is all zeroes except for a nonzero + id->driver_info is the way to create an entry that + indicates that the driver want to examine every + device and interface. */ + for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || + id->driver_info; id++) { + + if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && + id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && + id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) + continue; + + /* No need to test id->bcdDevice_lo != 0, since 0 is never + greater than any unsigned number. */ + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && + (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && + (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && + (id->bDeviceClass != dev->descriptor.bDeviceClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && + (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && + (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && + (id->bInterfaceClass != intf->desc.bInterfaceClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && + (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && + (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) + continue; + + return id; + } + + return NULL; +} + static int __find_interface(struct device * dev, void * data) { - struct find_interface_arg *arg = data; - struct usb_interface *intf; + struct usb_interface ** ret = (struct usb_interface **)data; + struct usb_interface * intf = *ret; + int *minor = (int *)data; /* can't look at usb devices, only interfaces */ if (dev->driver == &usb_generic_driver) return 0; intf = to_usb_interface(dev); - if (intf->minor != -1 && intf->minor == arg->minor) { - arg->interface = intf; + if (intf->minor != -1 && intf->minor == *minor) { + *ret = intf; return 1; } return 0; @@ -225,14 +513,35 @@ static int __find_interface(struct device * dev, void * data) */ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { - struct find_interface_arg argb; + struct usb_interface *intf = (struct usb_interface *)(long)minor; + int ret; + + ret = driver_for_each_device(&drv->driver, NULL, &intf, __find_interface); + + return ret ? intf : NULL; +} + +static int usb_device_match (struct device *dev, struct device_driver *drv) +{ + struct usb_interface *intf; + struct usb_driver *usb_drv; + const struct usb_device_id *id; + + /* check for generic driver, which we don't match any device with */ + if (drv == &usb_generic_driver) + return 0; + + intf = to_usb_interface(dev); + usb_drv = to_usb_driver(drv); + + id = usb_match_id (intf, usb_drv->id_table); + if (id) + return 1; - argb.minor = minor; - argb.interface = NULL; - driver_for_each_device(&drv->driver, NULL, &argb, __find_interface); - return argb.interface; + return 0; } + #ifdef CONFIG_HOTPLUG /* @@ -441,11 +750,12 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) /* hub driver sets up TT records */ } - dev->portnum = port1; dev->bus = bus; dev->parent = parent; INIT_LIST_HEAD(&dev->filelist); + init_MUTEX(&dev->serialize); + return dev; } @@ -518,20 +828,75 @@ void usb_put_intf(struct usb_interface *intf) /* USB device locking * - * USB devices and interfaces are locked using the semaphore in their - * embedded struct device. The hub driver guarantees that whenever a - * device is connected or disconnected, drivers are called with the - * USB device locked as well as their particular interface. + * Although locking USB devices should be straightforward, it is + * complicated by the way the driver-model core works. When a new USB + * driver is registered or unregistered, the core will automatically + * probe or disconnect all matching interfaces on all USB devices while + * holding the USB subsystem writelock. There's no good way for us to + * tell which devices will be used or to lock them beforehand; our only + * option is to effectively lock all the USB devices. + * + * We do that by using a private rw-semaphore, usb_all_devices_rwsem. + * When locking an individual device you must first acquire the rwsem's + * readlock. When a driver is registered or unregistered the writelock + * must be held. These actions are encapsulated in the subroutines + * below, so all a driver needs to do is call usb_lock_device() and + * usb_unlock_device(). * * Complications arise when several devices are to be locked at the same * time. Only hub-aware drivers that are part of usbcore ever have to - * do this; nobody else needs to worry about it. The rule for locking - * is simple: + * do this; nobody else needs to worry about it. The problem is that + * usb_lock_device() must not be called to lock a second device since it + * would acquire the rwsem's readlock reentrantly, leading to deadlock if + * another thread was waiting for the writelock. The solution is simple: + * + * When locking more than one device, call usb_lock_device() + * to lock the first one. Lock the others by calling + * down(&udev->serialize) directly. + * + * When unlocking multiple devices, use up(&udev->serialize) + * to unlock all but the last one. Unlock the last one by + * calling usb_unlock_device(). * * When locking both a device and its parent, always lock the * the parent first. */ +/** + * usb_lock_device - acquire the lock for a usb device structure + * @udev: device that's being locked + * + * Use this routine when you don't hold any other device locks; + * to acquire nested inner locks call down(&udev->serialize) directly. + * This is necessary for proper interaction with usb_lock_all_devices(). + */ +void usb_lock_device(struct usb_device *udev) +{ + down_read(&usb_all_devices_rwsem); + down(&udev->serialize); +} + +/** + * usb_trylock_device - attempt to acquire the lock for a usb device structure + * @udev: device that's being locked + * + * Don't use this routine if you already hold a device lock; + * use down_trylock(&udev->serialize) instead. + * This is necessary for proper interaction with usb_lock_all_devices(). + * + * Returns 1 if successful, 0 if contention. + */ +int usb_trylock_device(struct usb_device *udev) +{ + if (!down_read_trylock(&usb_all_devices_rwsem)) + return 0; + if (down_trylock(&udev->serialize)) { + up_read(&usb_all_devices_rwsem); + return 0; + } + return 1; +} + /** * usb_lock_device_for_reset - cautiously acquire the lock for a * usb device structure @@ -570,7 +935,7 @@ int usb_lock_device_for_reset(struct usb_device *udev, } } - while (usb_trylock_device(udev) != 0) { + while (!usb_trylock_device(udev)) { /* If we can't acquire the lock after waiting one second, * we're probably deadlocked */ @@ -588,6 +953,39 @@ int usb_lock_device_for_reset(struct usb_device *udev, return 1; } +/** + * usb_unlock_device - release the lock for a usb device structure + * @udev: device that's being unlocked + * + * Use this routine when releasing the only device lock you hold; + * to release inner nested locks call up(&udev->serialize) directly. + * This is necessary for proper interaction with usb_lock_all_devices(). + */ +void usb_unlock_device(struct usb_device *udev) +{ + up(&udev->serialize); + up_read(&usb_all_devices_rwsem); +} + +/** + * usb_lock_all_devices - acquire the lock for all usb device structures + * + * This is necessary when registering a new driver or probing a bus, + * since the driver-model core may try to use any usb_device. + */ +void usb_lock_all_devices(void) +{ + down_write(&usb_all_devices_rwsem); +} + +/** + * usb_unlock_all_devices - release the lock for all usb device structures + */ +void usb_unlock_all_devices(void) +{ + up_write(&usb_all_devices_rwsem); +} + static struct usb_device *match_device(struct usb_device *dev, u16 vendor_id, u16 product_id) @@ -610,10 +1008,10 @@ static struct usb_device *match_device(struct usb_device *dev, /* look through all of the children of this device */ for (child = 0; child < dev->maxchild; ++child) { if (dev->children[child]) { - usb_lock_device(dev->children[child]); + down(&dev->children[child]->serialize); ret_dev = match_device(dev->children[child], vendor_id, product_id); - usb_unlock_device(dev->children[child]); + up(&dev->children[child]->serialize); if (ret_dev) goto exit; } @@ -1098,8 +1496,18 @@ struct bus_type usb_bus_type = { .resume = usb_generic_resume, }; +#ifndef MODULE + +static int __init usb_setup_disable(char *str) +{ + nousb = 1; + return 1; +} + /* format to disable USB on kernel command line is: nousb */ -__module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444); +__setup("nousb", usb_setup_disable); + +#endif /* * for external read access to @@ -1190,6 +1598,8 @@ module_exit(usb_exit); * driver modules to use. */ +EXPORT_SYMBOL(usb_register); +EXPORT_SYMBOL(usb_deregister); EXPORT_SYMBOL(usb_disabled); EXPORT_SYMBOL_GPL(usb_get_intf); @@ -1200,10 +1610,14 @@ EXPORT_SYMBOL(usb_put_dev); EXPORT_SYMBOL(usb_get_dev); EXPORT_SYMBOL(usb_hub_tt_clear_buffer); +EXPORT_SYMBOL(usb_lock_device); +EXPORT_SYMBOL(usb_trylock_device); EXPORT_SYMBOL(usb_lock_device_for_reset); +EXPORT_SYMBOL(usb_unlock_device); EXPORT_SYMBOL(usb_driver_claim_interface); EXPORT_SYMBOL(usb_driver_release_interface); +EXPORT_SYMBOL(usb_match_id); EXPORT_SYMBOL(usb_find_interface); EXPORT_SYMBOL(usb_ifnum_to_if); EXPORT_SYMBOL(usb_altnum_to_altsetting); diff --git a/trunk/drivers/usb/core/usb.h b/trunk/drivers/usb/core/usb.h index 4647e1ebc68d..1c4a68499dce 100644 --- a/trunk/drivers/usb/core/usb.h +++ b/trunk/drivers/usb/core/usb.h @@ -16,6 +16,9 @@ extern int usb_get_device_descriptor(struct usb_device *dev, extern char *usb_cache_string(struct usb_device *udev, int index); extern int usb_set_configuration(struct usb_device *dev, int configuration); +extern void usb_lock_all_devices(void); +extern void usb_unlock_all_devices(void); + extern void usb_kick_khubd(struct usb_device *dev); extern void usb_suspend_root_hub(struct usb_device *hdev); extern void usb_resume_root_hub(struct usb_device *dev); @@ -30,9 +33,6 @@ extern void usb_host_cleanup(void); extern int usb_suspend_device(struct usb_device *dev); extern int usb_resume_device(struct usb_device *dev); -extern struct device_driver usb_generic_driver; -extern int usb_generic_driver_data; -extern int usb_device_match(struct device *dev, struct device_driver *drv); /* Interfaces and their "power state" are owned by usbcore */ diff --git a/trunk/drivers/usb/gadget/dummy_hcd.c b/trunk/drivers/usb/gadget/dummy_hcd.c index 9734cb76dd6c..c655d46c8aed 100644 --- a/trunk/drivers/usb/gadget/dummy_hcd.c +++ b/trunk/drivers/usb/gadget/dummy_hcd.c @@ -138,7 +138,7 @@ static const char *const ep_name [] = { /* or like sa1100: two fixed function endpoints */ "ep1out-bulk", "ep2in-bulk", }; -#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) +#define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *)) /*-------------------------------------------------------------------------*/ @@ -896,7 +896,7 @@ dummy_gadget_release (struct device *dev) #endif } -static int dummy_udc_probe (struct platform_device *pdev) +static int dummy_udc_probe (struct platform_device *dev) { struct dummy *dum = the_controller; int rc; @@ -909,7 +909,7 @@ static int dummy_udc_probe (struct platform_device *pdev) dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0); strcpy (dum->gadget.dev.bus_id, "gadget"); - dum->gadget.dev.parent = &pdev->dev; + dum->gadget.dev.parent = &dev->dev; dum->gadget.dev.release = dummy_gadget_release; rc = device_register (&dum->gadget.dev); if (rc < 0) @@ -919,47 +919,47 @@ static int dummy_udc_probe (struct platform_device *pdev) usb_bus_get (&dummy_to_hcd (dum)->self); #endif - platform_set_drvdata (pdev, dum); + platform_set_drvdata (dev, dum); device_create_file (&dum->gadget.dev, &dev_attr_function); return rc; } -static int dummy_udc_remove (struct platform_device *pdev) +static int dummy_udc_remove (struct platform_device *dev) { - struct dummy *dum = platform_get_drvdata (pdev); + struct dummy *dum = platform_get_drvdata (dev); - platform_set_drvdata (pdev, NULL); + platform_set_drvdata (dev, NULL); device_remove_file (&dum->gadget.dev, &dev_attr_function); device_unregister (&dum->gadget.dev); return 0; } -static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state) +static int dummy_udc_suspend (struct platform_device *dev, pm_message_t state) { - struct dummy *dum = platform_get_drvdata(pdev); + struct dummy *dum = platform_get_drvdata(dev); - dev_dbg (&pdev->dev, "%s\n", __FUNCTION__); + dev_dbg (&dev->dev, "%s\n", __FUNCTION__); spin_lock_irq (&dum->lock); dum->udc_suspended = 1; set_link_state (dum); spin_unlock_irq (&dum->lock); - pdev->dev.power.power_state = state; + dev->dev.power.power_state = state; usb_hcd_poll_rh_status (dummy_to_hcd (dum)); return 0; } -static int dummy_udc_resume (struct platform_device *pdev) +static int dummy_udc_resume (struct platform_device *dev) { - struct dummy *dum = platform_get_drvdata(pdev); + struct dummy *dum = platform_get_drvdata(dev); - dev_dbg (&pdev->dev, "%s\n", __FUNCTION__); + dev_dbg (&dev->dev, "%s\n", __FUNCTION__); spin_lock_irq (&dum->lock); dum->udc_suspended = 0; set_link_state (dum); spin_unlock_irq (&dum->lock); - pdev->dev.power.power_state = PMSG_ON; + dev->dev.power.power_state = PMSG_ON; usb_hcd_poll_rh_status (dummy_to_hcd (dum)); return 0; } @@ -1576,7 +1576,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf) dum = hcd_to_dummy (hcd); spin_lock_irqsave (&dum->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + if (hcd->state != HC_STATE_RUNNING) goto done; if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) { @@ -1623,7 +1623,7 @@ static int dummy_hub_control ( int retval = 0; unsigned long flags; - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + if (hcd->state != HC_STATE_RUNNING) return -ETIMEDOUT; dum = hcd_to_dummy (hcd); @@ -1756,12 +1756,9 @@ static int dummy_bus_suspend (struct usb_hcd *hcd) { struct dummy *dum = hcd_to_dummy (hcd); - dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__); - spin_lock_irq (&dum->lock); dum->rh_state = DUMMY_RH_SUSPENDED; set_link_state (dum); - hcd->state = HC_STATE_SUSPENDED; spin_unlock_irq (&dum->lock); return 0; } @@ -1769,23 +1766,14 @@ static int dummy_bus_suspend (struct usb_hcd *hcd) static int dummy_bus_resume (struct usb_hcd *hcd) { struct dummy *dum = hcd_to_dummy (hcd); - int rc = 0; - - dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__); spin_lock_irq (&dum->lock); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n"); - rc = -ENODEV; - } else { - dum->rh_state = DUMMY_RH_RUNNING; - set_link_state (dum); - if (!list_empty(&dum->urbp_list)) - mod_timer (&dum->timer, jiffies); - hcd->state = HC_STATE_RUNNING; - } + dum->rh_state = DUMMY_RH_RUNNING; + set_link_state (dum); + if (!list_empty(&dum->urbp_list)) + mod_timer (&dum->timer, jiffies); spin_unlock_irq (&dum->lock); - return rc; + return 0; } /*-------------------------------------------------------------------------*/ @@ -1911,14 +1899,14 @@ static const struct hc_driver dummy_hcd = { .bus_resume = dummy_bus_resume, }; -static int dummy_hcd_probe(struct platform_device *pdev) +static int dummy_hcd_probe (struct platform_device *dev) { struct usb_hcd *hcd; int retval; - dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); + dev_info(&dev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); - hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id); + hcd = usb_create_hcd (&dummy_hcd, &dev->dev, dev->dev.bus_id); if (!hcd) return -ENOMEM; the_controller = hcd_to_dummy (hcd); @@ -1931,43 +1919,36 @@ static int dummy_hcd_probe(struct platform_device *pdev) return retval; } -static int dummy_hcd_remove (struct platform_device *pdev) +static int dummy_hcd_remove (struct platform_device *dev) { struct usb_hcd *hcd; - hcd = platform_get_drvdata (pdev); + hcd = platform_get_drvdata (dev); usb_remove_hcd (hcd); usb_put_hcd (hcd); the_controller = NULL; return 0; } -static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state) +static int dummy_hcd_suspend (struct platform_device *dev, pm_message_t state) { struct usb_hcd *hcd; - struct dummy *dum; - int rc = 0; - dev_dbg (&pdev->dev, "%s\n", __FUNCTION__); + dev_dbg (&dev->dev, "%s\n", __FUNCTION__); + hcd = platform_get_drvdata (dev); - hcd = platform_get_drvdata (pdev); - dum = hcd_to_dummy (hcd); - if (dum->rh_state == DUMMY_RH_RUNNING) { - dev_warn(&pdev->dev, "Root hub isn't suspended!\n"); - rc = -EBUSY; - } else - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - return rc; + hcd->state = HC_STATE_SUSPENDED; + return 0; } -static int dummy_hcd_resume (struct platform_device *pdev) +static int dummy_hcd_resume (struct platform_device *dev) { struct usb_hcd *hcd; - dev_dbg (&pdev->dev, "%s\n", __FUNCTION__); + dev_dbg (&dev->dev, "%s\n", __FUNCTION__); + hcd = platform_get_drvdata (dev); + hcd->state = HC_STATE_RUNNING; - hcd = platform_get_drvdata (pdev); - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); usb_hcd_poll_rh_status (hcd); return 0; } diff --git a/trunk/drivers/usb/gadget/file_storage.c b/trunk/drivers/usb/gadget/file_storage.c index 0cea9782d7d4..ea09aaa3cab6 100644 --- a/trunk/drivers/usb/gadget/file_storage.c +++ b/trunk/drivers/usb/gadget/file_storage.c @@ -224,7 +224,6 @@ #include #include #include -#include #include #include #include @@ -239,6 +238,7 @@ #include #include #include +#include #include #include @@ -250,7 +250,7 @@ #define DRIVER_DESC "File-backed Storage Gadget" #define DRIVER_NAME "g_file_storage" -#define DRIVER_VERSION "28 November 2005" +#define DRIVER_VERSION "20 October 2004" static const char longname[] = DRIVER_DESC; static const char shortname[] = DRIVER_NAME; @@ -335,8 +335,8 @@ MODULE_LICENSE("Dual BSD/GPL"); #define MAX_LUNS 8 /* Arggh! There should be a module_param_array_named macro! */ -static char *file[MAX_LUNS]; -static int ro[MAX_LUNS]; +static char *file[MAX_LUNS] = {NULL, }; +static int ro[MAX_LUNS] = {0, }; static struct { int num_filenames; @@ -587,7 +587,7 @@ enum fsg_buffer_state { struct fsg_buffhd { void *buf; dma_addr_t dma; - enum fsg_buffer_state state; + volatile enum fsg_buffer_state state; struct fsg_buffhd *next; /* The NetChip 2280 is faster, and handles some protocol faults @@ -596,9 +596,9 @@ struct fsg_buffhd { unsigned int bulk_out_intended_length; struct usb_request *inreq; - int inreq_busy; + volatile int inreq_busy; struct usb_request *outreq; - int outreq_busy; + volatile int outreq_busy; }; enum fsg_state { @@ -631,16 +631,13 @@ struct fsg_dev { /* filesem protects: backing files in use */ struct rw_semaphore filesem; - /* reference counting: wait until all LUNs are released */ - struct kref ref; - struct usb_ep *ep0; // Handy copy of gadget->ep0 struct usb_request *ep0req; // For control responses - unsigned int ep0_req_tag; + volatile unsigned int ep0_req_tag; const char *ep0req_name; struct usb_request *intreq; // For interrupt responses - int intreq_busy; + volatile int intreq_busy; struct fsg_buffhd *intr_buffhd; unsigned int bulk_out_maxpacket; @@ -670,6 +667,7 @@ struct fsg_dev { struct fsg_buffhd *next_buffhd_to_drain; struct fsg_buffhd buffhds[NUM_BUFFERS]; + wait_queue_head_t thread_wqh; int thread_wakeup_needed; struct completion thread_notifier; struct task_struct *thread_task; @@ -696,6 +694,7 @@ struct fsg_dev { unsigned int nluns; struct lun *luns; struct lun *curlun; + struct completion lun_released; }; typedef void (*fsg_routine_t)(struct fsg_dev *); @@ -1074,13 +1073,11 @@ static int populate_config_buf(struct usb_gadget *gadget, /* These routines may be called in process context or in_irq */ -/* Caller must hold fsg->lock */ static void wakeup_thread(struct fsg_dev *fsg) { /* Tell the main thread that something has happened */ fsg->thread_wakeup_needed = 1; - if (fsg->thread_task) - wake_up_process(fsg->thread_task); + wake_up_all(&fsg->thread_wqh); } @@ -1167,12 +1164,11 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) usb_ep_fifo_flush(ep); /* Hold the lock while we update the request and buffer states */ - smp_wmb(); spin_lock(&fsg->lock); bh->inreq_busy = 0; bh->state = BUF_STATE_EMPTY; - wakeup_thread(fsg); spin_unlock(&fsg->lock); + wakeup_thread(fsg); } static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) @@ -1189,12 +1185,11 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) usb_ep_fifo_flush(ep); /* Hold the lock while we update the request and buffer states */ - smp_wmb(); spin_lock(&fsg->lock); bh->outreq_busy = 0; bh->state = BUF_STATE_FULL; - wakeup_thread(fsg); spin_unlock(&fsg->lock); + wakeup_thread(fsg); } @@ -1211,12 +1206,11 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) usb_ep_fifo_flush(ep); /* Hold the lock while we update the request and buffer states */ - smp_wmb(); spin_lock(&fsg->lock); fsg->intreq_busy = 0; bh->state = BUF_STATE_EMPTY; - wakeup_thread(fsg); spin_unlock(&fsg->lock); + wakeup_thread(fsg); } #else @@ -1267,8 +1261,8 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) fsg->cbbuf_cmnd_size = req->actual; memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size); - wakeup_thread(fsg); spin_unlock(&fsg->lock); + wakeup_thread(fsg); } #else @@ -1520,8 +1514,8 @@ static int fsg_setup(struct usb_gadget *gadget, /* Use this for bulk or interrupt transfers, not ep0 */ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, - struct usb_request *req, int *pbusy, - enum fsg_buffer_state *state) + struct usb_request *req, volatile int *pbusy, + volatile enum fsg_buffer_state *state) { int rc; @@ -1529,11 +1523,8 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, dump_msg(fsg, "bulk-in", req->buf, req->length); else if (ep == fsg->intr_in) dump_msg(fsg, "intr-in", req->buf, req->length); - - spin_lock_irq(&fsg->lock); *pbusy = 1; *state = BUF_STATE_BUSY; - spin_unlock_irq(&fsg->lock); rc = usb_ep_queue(ep, req, GFP_KERNEL); if (rc != 0) { *pbusy = 0; @@ -1553,23 +1544,14 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, static int sleep_thread(struct fsg_dev *fsg) { - int rc = 0; + int rc; /* Wait until a signal arrives or we are woken up */ - for (;;) { - try_to_freeze(); - set_current_state(TASK_INTERRUPTIBLE); - if (signal_pending(current)) { - rc = -EINTR; - break; - } - if (fsg->thread_wakeup_needed) - break; - schedule(); - } - __set_current_state(TASK_RUNNING); + rc = wait_event_interruptible(fsg->thread_wqh, + fsg->thread_wakeup_needed); fsg->thread_wakeup_needed = 0; - return rc; + try_to_freeze(); + return (rc ? -EINTR : 0); } @@ -1806,7 +1788,6 @@ static int do_write(struct fsg_dev *fsg) if (bh->state == BUF_STATE_EMPTY && !get_some_more) break; // We stopped early if (bh->state == BUF_STATE_FULL) { - smp_rmb(); fsg->next_buffhd_to_drain = bh->next; bh->state = BUF_STATE_EMPTY; @@ -2375,7 +2356,6 @@ static int throw_away_data(struct fsg_dev *fsg) /* Throw away the data in a filled buffer */ if (bh->state == BUF_STATE_FULL) { - smp_rmb(); bh->state = BUF_STATE_EMPTY; fsg->next_buffhd_to_drain = bh->next; @@ -3041,7 +3021,6 @@ static int get_next_command(struct fsg_dev *fsg) if ((rc = sleep_thread(fsg)) != 0) return rc; } - smp_rmb(); rc = received_cbw(fsg, bh); bh->state = BUF_STATE_EMPTY; @@ -3663,19 +3642,11 @@ static DEVICE_ATTR(file, 0444, show_file, NULL); /*-------------------------------------------------------------------------*/ -static void fsg_release(struct kref *ref) -{ - struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref); - - kfree(fsg->luns); - kfree(fsg); -} - static void lun_release(struct device *dev) { struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); - kref_put(&fsg->ref, fsg_release); + complete(&fsg->lun_released); } static void fsg_unbind(struct usb_gadget *gadget) @@ -3689,12 +3660,14 @@ static void fsg_unbind(struct usb_gadget *gadget) clear_bit(REGISTERED, &fsg->atomic_bitflags); /* Unregister the sysfs attribute files and the LUNs */ + init_completion(&fsg->lun_released); for (i = 0; i < fsg->nluns; ++i) { curlun = &fsg->luns[i]; if (curlun->registered) { device_remove_file(&curlun->dev, &dev_attr_ro); device_remove_file(&curlun->dev, &dev_attr_file); device_unregister(&curlun->dev); + wait_for_completion(&fsg->lun_released); curlun->registered = 0; } } @@ -3873,7 +3846,6 @@ static int __init fsg_bind(struct usb_gadget *gadget) curlun->dev.release = lun_release; device_create_file(&curlun->dev, &dev_attr_ro); device_create_file(&curlun->dev, &dev_attr_file); - kref_get(&fsg->ref); } if (file[i] && *file[i]) { @@ -4089,7 +4061,7 @@ static int __init fsg_alloc(void) return -ENOMEM; spin_lock_init(&fsg->lock); init_rwsem(&fsg->filesem); - kref_init(&fsg->ref); + init_waitqueue_head(&fsg->thread_wqh); init_completion(&fsg->thread_notifier); the_fsg = fsg; @@ -4097,6 +4069,13 @@ static int __init fsg_alloc(void) } +static void fsg_free(struct fsg_dev *fsg) +{ + kfree(fsg->luns); + kfree(fsg); +} + + static int __init fsg_init(void) { int rc; @@ -4106,7 +4085,7 @@ static int __init fsg_init(void) return rc; fsg = the_fsg; if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) - kref_put(&fsg->ref, fsg_release); + fsg_free(fsg); return rc; } module_init(fsg_init); @@ -4124,6 +4103,6 @@ static void __exit fsg_cleanup(void) wait_for_completion(&fsg->thread_notifier); close_all_backing_files(fsg); - kref_put(&fsg->ref, fsg_release); + fsg_free(fsg); } module_exit(fsg_cleanup); diff --git a/trunk/drivers/usb/gadget/serial.c b/trunk/drivers/usb/gadget/serial.c index 65e084a2c87e..b35ac6d334f8 100644 --- a/trunk/drivers/usb/gadget/serial.c +++ b/trunk/drivers/usb/gadget/serial.c @@ -890,12 +890,10 @@ static void gs_close(struct tty_struct *tty, struct file *file) /* wait for write buffer to drain, or */ /* at most GS_CLOSE_TIMEOUT seconds */ if (gs_buf_data_avail(port->port_write_buf) > 0) { - spin_unlock_irqrestore(&port->port_lock, flags); wait_cond_interruptible_timeout(port->port_write_wait, port->port_dev == NULL || gs_buf_data_avail(port->port_write_buf) == 0, &port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ); - spin_lock_irqsave(&port->port_lock, flags); } /* free disconnected port on final close */ diff --git a/trunk/drivers/usb/host/Makefile b/trunk/drivers/usb/host/Makefile index e3020f4b17be..58321d3f314c 100644 --- a/trunk/drivers/usb/host/Makefile +++ b/trunk/drivers/usb/host/Makefile @@ -2,10 +2,6 @@ # Makefile for USB Host Controller Drivers # -ifeq ($(CONFIG_USB_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG -endif - obj-$(CONFIG_PCI) += pci-quirks.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o diff --git a/trunk/drivers/usb/host/ehci-hcd.c b/trunk/drivers/usb/host/ehci-hcd.c index 9dd3d14c64f3..29f52a44b928 100644 --- a/trunk/drivers/usb/host/ehci-hcd.c +++ b/trunk/drivers/usb/host/ehci-hcd.c @@ -17,6 +17,13 @@ */ #include + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif + #include #include #include @@ -617,7 +624,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) } /* remote wakeup [4.3.1] */ - if (status & STS_PCD) { + if ((status & STS_PCD) && hcd->remote_wakeup) { unsigned i = HCS_N_PORTS (ehci->hcs_params); /* resume root hub? */ diff --git a/trunk/drivers/usb/host/ehci-hub.c b/trunk/drivers/usb/host/ehci-hub.c index 69b0b9be7a64..82caf336e9b6 100644 --- a/trunk/drivers/usb/host/ehci-hub.c +++ b/trunk/drivers/usb/host/ehci-hub.c @@ -59,7 +59,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) t2 |= PORT_SUSPEND; - if (device_may_wakeup(&hcd->self.root_hub->dev)) + if (hcd->remote_wakeup) t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; else t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); @@ -517,7 +517,7 @@ static int ehci_hub_control ( if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) goto error; - if (device_may_wakeup(&hcd->self.root_hub->dev)) + if (hcd->remote_wakeup) temp |= PORT_WAKE_BITS; writel (temp | PORT_SUSPEND, &ehci->regs->port_status [wIndex]); diff --git a/trunk/drivers/usb/host/ehci-pci.c b/trunk/drivers/usb/host/ehci-pci.c index 08ca0f849dab..13f73a836e45 100644 --- a/trunk/drivers/usb/host/ehci-pci.c +++ b/trunk/drivers/usb/host/ehci-pci.c @@ -210,16 +210,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* Serial Bus Release Number is at PCI 0x60 offset */ pci_read_config_byte(pdev, 0x60, &ehci->sbrn); - /* Workaround current PCI init glitch: wakeup bits aren't - * being set from PCI PM capability. - */ - if (!device_can_wakeup(&pdev->dev)) { - u16 port_wake; - - pci_read_config_word(pdev, 0x62, &port_wake); - if (port_wake & 0x0001) - device_init_wakeup(&pdev->dev, 1); - } + /* REVISIT: per-port wake capability (PCI 0x62) currently unused */ retval = ehci_pci_reinit(ehci, pdev); done: @@ -278,6 +269,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); unsigned port; + struct usb_device *root = hcd->self.root_hub; struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int retval = -EINVAL; @@ -311,7 +303,13 @@ static int ehci_pci_resume(struct usb_hcd *hcd) restart: ehci_dbg(ehci, "lost power, restarting\n"); - usb_root_hub_lost_power(hcd->self.root_hub); + for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) { + port--; + if (!root->children [port]) + continue; + usb_set_device_state(root->children[port], + USB_STATE_NOTATTACHED); + } /* Else reset, to cope with power loss or flush-to-storage * style "resume" having let BIOS kick in during reboot. diff --git a/trunk/drivers/usb/host/ehci-q.c b/trunk/drivers/usb/host/ehci-q.c index 9b13bf2fa98d..bf03ec0d8ee2 100644 --- a/trunk/drivers/usb/host/ehci-q.c +++ b/trunk/drivers/usb/host/ehci-q.c @@ -514,18 +514,18 @@ qh_urb_transaction ( qtd->urb = urb; qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); list_add_tail (&qtd->qtd_list, head); - - /* for zero length DATA stages, STATUS is always IN */ - if (len == 0) - token |= (1 /* "in" */ << 8); } /* * data transfer stage: buffer setup */ - buf = urb->transfer_dma; + if (likely (len > 0)) + buf = urb->transfer_dma; + else + buf = 0; - if (is_input) + /* for zero length DATA stages, STATUS is always IN */ + if (!buf || is_input) token |= (1 /* "in" */ << 8); /* else it's already initted to "out" pid (0 << 8) */ @@ -572,7 +572,7 @@ qh_urb_transaction ( * control requests may need a terminating data "status" ack; * bulk ones may need a terminating short packet (zero length). */ - if (likely (urb->transfer_buffer_length != 0)) { + if (likely (buf != 0)) { int one_more = 0; if (usb_pipecontrol (urb->pipe)) { diff --git a/trunk/drivers/usb/host/isp116x-hcd.c b/trunk/drivers/usb/host/isp116x-hcd.c index 584b8dc65119..82f64986bc22 100644 --- a/trunk/drivers/usb/host/isp116x-hcd.c +++ b/trunk/drivers/usb/host/isp116x-hcd.c @@ -55,13 +55,19 @@ /* enqueuing/finishing log of urbs */ //#define URB_TRACE +#include #include +#include +#include #include -#include -#include +#include +#include +#include +#include #include #include #include +#include #include #include #include @@ -71,10 +77,14 @@ #include #include +#ifndef DEBUG +# define STUB_DEBUG_FILE +#endif + #include "../core/hcd.h" #include "isp116x.h" -#define DRIVER_VERSION "03 Nov 2005" +#define DRIVER_VERSION "05 Aug 2005" #define DRIVER_DESC "ISP116x USB Host Controller Driver" MODULE_DESCRIPTION(DRIVER_DESC); @@ -154,11 +164,13 @@ static void pack_fifo(struct isp116x *isp116x) struct ptd *ptd; int buflen = isp116x->atl_last_dir == PTD_DIR_IN ? isp116x->atl_bufshrt : isp116x->atl_buflen; + int ptd_count = 0; isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); isp116x_write_reg16(isp116x, HCXFERCTR, buflen); isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET); for (ep = isp116x->atl_active; ep; ep = ep->active) { + ++ptd_count; ptd = &ep->ptd; dump_ptd(ptd); dump_ptd_out_data(ptd, ep->data); @@ -293,8 +305,9 @@ static void postproc_atl_queue(struct isp116x *isp116x) udev = urb->dev; ptd = &ep->ptd; cc = PTD_GET_CC(ptd); - short_not_ok = 1; + spin_lock(&urb->lock); + short_not_ok = 1; /* Data underrun is special. For allowed underrun we clear the error and continue as normal. For @@ -407,7 +420,7 @@ static void postproc_atl_queue(struct isp116x *isp116x) ep->nextpid = 0; break; default: - BUG(); + BUG_ON(1); } spin_unlock(&urb->lock); } @@ -615,12 +628,8 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT); isp116x_write_reg32(isp116x, HCINTSTAT, intstat); if (intstat & HCINT_UE) { - ERR("Unrecoverable error, HC is dead!\n"); - /* IRQ's are off, we do no DMA, - perfectly ready to die ... */ - hcd->state = HC_STATE_HALT; - ret = IRQ_HANDLED; - goto done; + ERR("Unrecoverable error\n"); + /* What should we do here? Reset? */ } if (intstat & HCINT_RHSC) /* When root hub or any of its ports is going @@ -631,6 +640,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) if (intstat & HCINT_RD) { DBG("---- remote wakeup\n"); usb_hcd_resume_root_hub(hcd); + ret = IRQ_HANDLED; } irqstat &= ~HCuPINT_OPR; ret = IRQ_HANDLED; @@ -641,7 +651,6 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) } isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); - done: spin_unlock(&isp116x->lock); return ret; } @@ -715,7 +724,6 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, spin_lock_irqsave(&isp116x->lock, flags); if (!HC_IS_RUNNING(hcd->state)) { - kfree(ep); ret = -ENODEV; goto fail; } @@ -880,7 +888,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) { int i; - struct isp116x_ep *ep = hep->hcpriv; + struct isp116x_ep *ep = hep->hcpriv;; if (!ep) return; @@ -908,6 +916,8 @@ static int isp116x_get_frame(struct usb_hcd *hcd) return (int)fmnum; } +/*----------------------------------------------------------------*/ + /* Adapted from ohci-hub.c. Currently we don't support autosuspend. */ @@ -958,10 +968,11 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x, desc->bHubContrCurrent = 0; desc->bNbrPorts = (u8) (reg & 0x3); /* Power switching, device type, overcurrent. */ - desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f)); + desc->wHubCharacteristics = + (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f)); desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff); /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ - desc->bitmap[0] = 0; + desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; desc->bitmap[1] = ~0; } @@ -1148,9 +1159,135 @@ static int isp116x_hub_control(struct usb_hcd *hcd, return ret; } +#ifdef CONFIG_PM + +static int isp116x_bus_suspend(struct usb_hcd *hcd) +{ + struct isp116x *isp116x = hcd_to_isp116x(hcd); + unsigned long flags; + u32 val; + int ret = 0; + + spin_lock_irqsave(&isp116x->lock, flags); + + val = isp116x_read_reg32(isp116x, HCCONTROL); + switch (val & HCCONTROL_HCFS) { + case HCCONTROL_USB_OPER: + hcd->state = HC_STATE_QUIESCING; + val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); + val |= HCCONTROL_USB_SUSPEND; + if (hcd->remote_wakeup) + val |= HCCONTROL_RWE; + /* Wait for usb transfers to finish */ + mdelay(2); + isp116x_write_reg32(isp116x, HCCONTROL, val); + hcd->state = HC_STATE_SUSPENDED; + /* Wait for devices to suspend */ + mdelay(5); + case HCCONTROL_USB_SUSPEND: + break; + case HCCONTROL_USB_RESUME: + isp116x_write_reg32(isp116x, HCCONTROL, + (val & ~HCCONTROL_HCFS) | + HCCONTROL_USB_RESET); + case HCCONTROL_USB_RESET: + ret = -EBUSY; + break; + default: + ret = -EINVAL; + } + + spin_unlock_irqrestore(&isp116x->lock, flags); + return ret; +} + +static int isp116x_bus_resume(struct usb_hcd *hcd) +{ + struct isp116x *isp116x = hcd_to_isp116x(hcd); + u32 val; + int ret = -EINPROGRESS; + + msleep(5); + spin_lock_irq(&isp116x->lock); + + val = isp116x_read_reg32(isp116x, HCCONTROL); + switch (val & HCCONTROL_HCFS) { + case HCCONTROL_USB_SUSPEND: + val &= ~HCCONTROL_HCFS; + val |= HCCONTROL_USB_RESUME; + isp116x_write_reg32(isp116x, HCCONTROL, val); + case HCCONTROL_USB_RESUME: + break; + case HCCONTROL_USB_OPER: + /* Without setting power_state here the + SUSPENDED state won't be removed from + sysfs/usbN/power.state as a response to remote + wakeup. Maybe in the future. */ + hcd->self.root_hub->dev.power.power_state = PMSG_ON; + ret = 0; + break; + default: + ret = -EBUSY; + } + + if (ret != -EINPROGRESS) { + spin_unlock_irq(&isp116x->lock); + return ret; + } + + val = isp116x->rhdesca & RH_A_NDP; + while (val--) { + u32 stat = + isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1); + /* force global, not selective, resume */ + if (!(stat & RH_PS_PSS)) + continue; + DBG("%s: Resuming port %d\n", __func__, val); + isp116x_write_reg32(isp116x, RH_PS_POCI, val + ? HCRHPORT2 : HCRHPORT1); + } + spin_unlock_irq(&isp116x->lock); + + hcd->state = HC_STATE_RESUMING; + mdelay(20); + + /* Go operational */ + spin_lock_irq(&isp116x->lock); + val = isp116x_read_reg32(isp116x, HCCONTROL); + isp116x_write_reg32(isp116x, HCCONTROL, + (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER); + spin_unlock_irq(&isp116x->lock); + /* see analogous comment above */ + hcd->self.root_hub->dev.power.power_state = PMSG_ON; + hcd->state = HC_STATE_RUNNING; + + return 0; +} + + +#else + +#define isp116x_bus_suspend NULL +#define isp116x_bus_resume NULL + +#endif + /*-----------------------------------------------------------------*/ -#ifdef CONFIG_DEBUG_FS +#ifdef STUB_DEBUG_FILE + +static inline void create_debug_file(struct isp116x *isp116x) +{ +} + +static inline void remove_debug_file(struct isp116x *isp116x) +{ +} + +#else + +#include +#include static void dump_irq(struct seq_file *s, char *label, u16 mask) { @@ -1174,9 +1311,13 @@ static void dump_int(struct seq_file *s, char *label, u32 mask) mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : ""); } -static int isp116x_show_dbg(struct seq_file *s, void *unused) +static int proc_isp116x_show(struct seq_file *s, void *unused) { struct isp116x *isp116x = s->private; + struct isp116x_ep *ep; + struct urb *urb; + unsigned i; + char *str; seq_printf(s, "%s\n%s version %s\n", isp116x_to_hcd(isp116x)->product_desc, hcd_name, @@ -1192,50 +1333,105 @@ static int isp116x_show_dbg(struct seq_file *s, void *unused) } spin_lock_irq(&isp116x->lock); + dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB)); dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT)); dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB)); dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT)); - isp116x_show_regs_seq(isp116x, s); + + list_for_each_entry(ep, &isp116x->async, schedule) { + + switch (ep->nextpid) { + case USB_PID_IN: + str = "in"; + break; + case USB_PID_OUT: + str = "out"; + break; + case USB_PID_SETUP: + str = "setup"; + break; + case USB_PID_ACK: + str = "status"; + break; + default: + str = "?"; + break; + }; + seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep, + ep->epnum, str, ep->maxpacket); + list_for_each_entry(urb, &ep->hep->urb_list, urb_list) { + seq_printf(s, " urb%p, %d/%d\n", urb, + urb->actual_length, + urb->transfer_buffer_length); + } + } + if (!list_empty(&isp116x->async)) + seq_printf(s, "\n"); + + seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE); + + for (i = 0; i < PERIODIC_SIZE; i++) { + ep = isp116x->periodic[i]; + if (!ep) + continue; + seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]); + + /* DUMB: prints shared entries multiple times */ + do { + seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n", + ep->period, ep, + (ep->udev->speed == + USB_SPEED_FULL) ? "" : "ls ", + ep->udev->devnum, ep->epnum, + (ep->epnum == + 0) ? "" : ((ep->nextpid == + USB_PID_IN) ? "in" : "out"), + ep->maxpacket); + ep = ep->next; + } while (ep); + } spin_unlock_irq(&isp116x->lock); seq_printf(s, "\n"); return 0; } -static int isp116x_open_seq(struct inode *inode, struct file *file) +static int proc_isp116x_open(struct inode *inode, struct file *file) { - return single_open(file, isp116x_show_dbg, inode->u.generic_ip); + return single_open(file, proc_isp116x_show, PDE(inode)->data); } -static struct file_operations isp116x_debug_fops = { - .open = isp116x_open_seq, +static struct file_operations proc_ops = { + .open = proc_isp116x_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static int create_debug_file(struct isp116x *isp116x) +/* expect just one isp116x per system */ +static const char proc_filename[] = "driver/isp116x"; + +static void create_debug_file(struct isp116x *isp116x) { - isp116x->dentry = debugfs_create_file(hcd_name, - S_IRUGO, NULL, isp116x, - &isp116x_debug_fops); - if (!isp116x->dentry) - return -ENOMEM; - return 0; + struct proc_dir_entry *pde; + + pde = create_proc_entry(proc_filename, 0, NULL); + if (pde == NULL) + return; + + pde->proc_fops = &proc_ops; + pde->data = isp116x; + isp116x->pde = pde; } static void remove_debug_file(struct isp116x *isp116x) { - debugfs_remove(isp116x->dentry); + if (isp116x->pde) + remove_proc_entry(proc_filename, NULL); } -#else - -#define create_debug_file(d) 0 -#define remove_debug_file(d) do{}while(0) - -#endif /* CONFIG_DEBUG_FS */ +#endif /*-----------------------------------------------------------------*/ @@ -1270,7 +1466,7 @@ static int isp116x_reset(struct usb_hcd *hcd) struct isp116x *isp116x = hcd_to_isp116x(hcd); unsigned long t; u16 clkrdy = 0; - int ret, timeout = 15 /* ms */ ; + int ret = 0, timeout = 15 /* ms */ ; ret = isp116x_sw_reset(isp116x); if (ret) @@ -1286,7 +1482,7 @@ static int isp116x_reset(struct usb_hcd *hcd) break; } if (!clkrdy) { - ERR("Clock not ready after %dms\n", timeout); + ERR("Clock not ready after 20ms\n"); /* After sw_reset the clock won't report to be ready, if H_WAKEUP pin is high. */ ERR("Please make sure that the H_WAKEUP pin is pulled low!\n"); @@ -1376,8 +1572,7 @@ static int isp116x_start(struct usb_hcd *hcd) val = 0; if (board->remote_wakeup_enable) { - if (!device_can_wakeup(hcd->self.controller)) - device_init_wakeup(hcd->self.controller, 1); + hcd->can_wakeup = 1; val |= RH_HS_DRWE; } isp116x_write_reg32(isp116x, HCRHSTATUS, val); @@ -1405,126 +1600,12 @@ static int isp116x_start(struct usb_hcd *hcd) isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); - isp116x_show_regs_log(isp116x); + isp116x_show_regs(isp116x); spin_unlock_irqrestore(&isp116x->lock, flags); return 0; } -#ifdef CONFIG_PM - -static int isp116x_bus_suspend(struct usb_hcd *hcd) -{ - struct isp116x *isp116x = hcd_to_isp116x(hcd); - unsigned long flags; - u32 val; - int ret = 0; - - spin_lock_irqsave(&isp116x->lock, flags); - - val = isp116x_read_reg32(isp116x, HCCONTROL); - switch (val & HCCONTROL_HCFS) { - case HCCONTROL_USB_OPER: - val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); - val |= HCCONTROL_USB_SUSPEND; - if (device_may_wakeup(&hcd->self.root_hub->dev)) - val |= HCCONTROL_RWE; - /* Wait for usb transfers to finish */ - mdelay(2); - isp116x_write_reg32(isp116x, HCCONTROL, val); - /* Wait for devices to suspend */ - mdelay(5); - case HCCONTROL_USB_SUSPEND: - break; - case HCCONTROL_USB_RESUME: - isp116x_write_reg32(isp116x, HCCONTROL, - (val & ~HCCONTROL_HCFS) | - HCCONTROL_USB_RESET); - case HCCONTROL_USB_RESET: - ret = -EBUSY; - break; - default: - ret = -EINVAL; - } - - spin_unlock_irqrestore(&isp116x->lock, flags); - return ret; -} - -static int isp116x_bus_resume(struct usb_hcd *hcd) -{ - struct isp116x *isp116x = hcd_to_isp116x(hcd); - u32 val; - - msleep(5); - spin_lock_irq(&isp116x->lock); - - val = isp116x_read_reg32(isp116x, HCCONTROL); - switch (val & HCCONTROL_HCFS) { - case HCCONTROL_USB_SUSPEND: - val &= ~HCCONTROL_HCFS; - val |= HCCONTROL_USB_RESUME; - isp116x_write_reg32(isp116x, HCCONTROL, val); - case HCCONTROL_USB_RESUME: - break; - case HCCONTROL_USB_OPER: - spin_unlock_irq(&isp116x->lock); - /* Without setting power_state here the - SUSPENDED state won't be removed from - sysfs/usbN/power.state as a response to remote - wakeup. Maybe in the future. */ - hcd->self.root_hub->dev.power.power_state = PMSG_ON; - return 0; - default: - /* HCCONTROL_USB_RESET: this may happen, when during - suspension the HC lost power. Reinitialize completely */ - spin_unlock_irq(&isp116x->lock); - DBG("Chip has been reset while suspended. Reinit from scratch.\n"); - isp116x_reset(hcd); - isp116x_start(hcd); - isp116x_hub_control(hcd, SetPortFeature, - USB_PORT_FEAT_POWER, 1, NULL, 0); - if ((isp116x->rhdesca & RH_A_NDP) == 2) - isp116x_hub_control(hcd, SetPortFeature, - USB_PORT_FEAT_POWER, 2, NULL, 0); - hcd->self.root_hub->dev.power.power_state = PMSG_ON; - return 0; - } - - val = isp116x->rhdesca & RH_A_NDP; - while (val--) { - u32 stat = - isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1); - /* force global, not selective, resume */ - if (!(stat & RH_PS_PSS)) - continue; - DBG("%s: Resuming port %d\n", __func__, val); - isp116x_write_reg32(isp116x, RH_PS_POCI, val - ? HCRHPORT2 : HCRHPORT1); - } - spin_unlock_irq(&isp116x->lock); - - hcd->state = HC_STATE_RESUMING; - msleep(20); - - /* Go operational */ - spin_lock_irq(&isp116x->lock); - val = isp116x_read_reg32(isp116x, HCCONTROL); - isp116x_write_reg32(isp116x, HCCONTROL, - (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER); - spin_unlock_irq(&isp116x->lock); - /* see analogous comment above */ - hcd->self.root_hub->dev.power.power_state = PMSG_ON; - hcd->state = HC_STATE_RUNNING; - - return 0; -} - -#else - -#define isp116x_bus_suspend NULL -#define isp116x_bus_resume NULL - -#endif +/*-----------------------------------------------------------------*/ static struct hc_driver isp116x_hc_driver = { .description = hcd_name, @@ -1654,19 +1735,12 @@ static int __init isp116x_probe(struct platform_device *pdev) } ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); - if (ret) + if (ret != 0) goto err6; - ret = create_debug_file(isp116x); - if (ret) { - ERR("Couldn't create debugfs entry\n"); - goto err7; - } - + create_debug_file(isp116x); return 0; - err7: - usb_remove_hcd(hcd); err6: usb_put_hcd(hcd); err5: @@ -1688,9 +1762,13 @@ static int __init isp116x_probe(struct platform_device *pdev) */ static int isp116x_suspend(struct platform_device *dev, pm_message_t state) { - VDBG("%s: state %x\n", __func__, state.event); + int ret = 0; + + VDBG("%s: state %x\n", __func__, state); + dev->dev.power.power_state = state; - return 0; + + return ret; } /* @@ -1698,9 +1776,13 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state) */ static int isp116x_resume(struct platform_device *dev) { - VDBG("%s: state %x\n", __func__, dev->power.power_state.event); + int ret = 0; + + VDBG("%s: state %x\n", __func__, dev->dev.power.power_state); + dev->dev.power.power_state = PMSG_ON; - return 0; + + return ret; } #else diff --git a/trunk/drivers/usb/host/isp116x.h b/trunk/drivers/usb/host/isp116x.h index a1b7c3813d3a..c6fec96785fe 100644 --- a/trunk/drivers/usb/host/isp116x.h +++ b/trunk/drivers/usb/host/isp116x.h @@ -259,7 +259,7 @@ struct isp116x { struct isp116x_platform_data *board; - struct dentry *dentry; + struct proc_dir_entry *pde; unsigned long stat1, stat2, stat4, stat8, stat16; /* HC registers */ @@ -450,7 +450,7 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg, isp116x_write_data32(isp116x, (u32) val); } -#define isp116x_show_reg_log(d,r,s) { \ +#define isp116x_show_reg(d,r) { \ if ((r) < 0x20) { \ DBG("%-12s[%02x]: %08x\n", #r, \ r, isp116x_read_reg32(d, r)); \ @@ -459,60 +459,35 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg, r, isp116x_read_reg16(d, r)); \ } \ } -#define isp116x_show_reg_seq(d,r,s) { \ - if ((r) < 0x20) { \ - seq_printf(s, "%-12s[%02x]: %08x\n", #r, \ - r, isp116x_read_reg32(d, r)); \ - } else { \ - seq_printf(s, "%-12s[%02x]: %04x\n", #r, \ - r, isp116x_read_reg16(d, r)); \ - } \ -} -#define isp116x_show_regs(d,type,s) { \ - isp116x_show_reg_##type(d, HCREVISION, s); \ - isp116x_show_reg_##type(d, HCCONTROL, s); \ - isp116x_show_reg_##type(d, HCCMDSTAT, s); \ - isp116x_show_reg_##type(d, HCINTSTAT, s); \ - isp116x_show_reg_##type(d, HCINTENB, s); \ - isp116x_show_reg_##type(d, HCFMINTVL, s); \ - isp116x_show_reg_##type(d, HCFMREM, s); \ - isp116x_show_reg_##type(d, HCFMNUM, s); \ - isp116x_show_reg_##type(d, HCLSTHRESH, s); \ - isp116x_show_reg_##type(d, HCRHDESCA, s); \ - isp116x_show_reg_##type(d, HCRHDESCB, s); \ - isp116x_show_reg_##type(d, HCRHSTATUS, s); \ - isp116x_show_reg_##type(d, HCRHPORT1, s); \ - isp116x_show_reg_##type(d, HCRHPORT2, s); \ - isp116x_show_reg_##type(d, HCHWCFG, s); \ - isp116x_show_reg_##type(d, HCDMACFG, s); \ - isp116x_show_reg_##type(d, HCXFERCTR, s); \ - isp116x_show_reg_##type(d, HCuPINT, s); \ - isp116x_show_reg_##type(d, HCuPINTENB, s); \ - isp116x_show_reg_##type(d, HCCHIPID, s); \ - isp116x_show_reg_##type(d, HCSCRATCH, s); \ - isp116x_show_reg_##type(d, HCITLBUFLEN, s); \ - isp116x_show_reg_##type(d, HCATLBUFLEN, s); \ - isp116x_show_reg_##type(d, HCBUFSTAT, s); \ - isp116x_show_reg_##type(d, HCRDITL0LEN, s); \ - isp116x_show_reg_##type(d, HCRDITL1LEN, s); \ -} - -/* - Dump registers for debugfs. -*/ -static inline void isp116x_show_regs_seq(struct isp116x *isp116x, - struct seq_file *s) -{ - isp116x_show_regs(isp116x, seq, s); -} - -/* - Dump registers to syslog. -*/ -static inline void isp116x_show_regs_log(struct isp116x *isp116x) +static inline void isp116x_show_regs(struct isp116x *isp116x) { - isp116x_show_regs(isp116x, log, NULL); + isp116x_show_reg(isp116x, HCREVISION); + isp116x_show_reg(isp116x, HCCONTROL); + isp116x_show_reg(isp116x, HCCMDSTAT); + isp116x_show_reg(isp116x, HCINTSTAT); + isp116x_show_reg(isp116x, HCINTENB); + isp116x_show_reg(isp116x, HCFMINTVL); + isp116x_show_reg(isp116x, HCFMREM); + isp116x_show_reg(isp116x, HCFMNUM); + isp116x_show_reg(isp116x, HCLSTHRESH); + isp116x_show_reg(isp116x, HCRHDESCA); + isp116x_show_reg(isp116x, HCRHDESCB); + isp116x_show_reg(isp116x, HCRHSTATUS); + isp116x_show_reg(isp116x, HCRHPORT1); + isp116x_show_reg(isp116x, HCRHPORT2); + isp116x_show_reg(isp116x, HCHWCFG); + isp116x_show_reg(isp116x, HCDMACFG); + isp116x_show_reg(isp116x, HCXFERCTR); + isp116x_show_reg(isp116x, HCuPINT); + isp116x_show_reg(isp116x, HCuPINTENB); + isp116x_show_reg(isp116x, HCCHIPID); + isp116x_show_reg(isp116x, HCSCRATCH); + isp116x_show_reg(isp116x, HCITLBUFLEN); + isp116x_show_reg(isp116x, HCATLBUFLEN); + isp116x_show_reg(isp116x, HCBUFSTAT); + isp116x_show_reg(isp116x, HCRDITL0LEN); + isp116x_show_reg(isp116x, HCRDITL1LEN); } #if defined(URB_TRACE) diff --git a/trunk/drivers/usb/host/ohci-hcd.c b/trunk/drivers/usb/host/ohci-hcd.c index a4b12404ae08..bf1d9abc07ac 100644 --- a/trunk/drivers/usb/host/ohci-hcd.c +++ b/trunk/drivers/usb/host/ohci-hcd.c @@ -75,6 +75,13 @@ */ #include + +#ifdef CONFIG_USB_DEBUG +# define DEBUG +#else +# undef DEBUG +#endif + #include #include #include @@ -795,6 +802,7 @@ static int ohci_restart (struct ohci_hcd *ohci) int temp; int i; struct urb_priv *priv; + struct usb_device *root = ohci_to_hcd(ohci)->self.root_hub; /* mark any devices gone, so they do nothing till khubd disconnects. * recycle any "live" eds/tds (and urbs) right away. @@ -803,7 +811,11 @@ static int ohci_restart (struct ohci_hcd *ohci) */ spin_lock_irq(&ohci->lock); disable (ohci); - usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub); + for (i = 0; i < root->maxchild; i++) { + if (root->children [i]) + usb_set_device_state (root->children[i], + USB_STATE_NOTATTACHED); + } if (!list_empty (&ohci->pending)) ohci_dbg(ohci, "abort schedule...\n"); list_for_each_entry (priv, &ohci->pending, pending) { diff --git a/trunk/drivers/usb/host/ohci-hub.c b/trunk/drivers/usb/host/ohci-hub.c index 4b2226d77b34..72e3b12a1926 100644 --- a/trunk/drivers/usb/host/ohci-hub.c +++ b/trunk/drivers/usb/host/ohci-hub.c @@ -372,7 +372,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) & ohci->hc_control) == OHCI_USB_OPER && time_after (jiffies, ohci->next_statechange) - && usb_trylock_device (hcd->self.root_hub) == 0 + && usb_trylock_device (hcd->self.root_hub) ) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_bus_suspend (hcd); diff --git a/trunk/drivers/usb/host/ohci-pxa27x.c b/trunk/drivers/usb/host/ohci-pxa27x.c index acde8868da21..9d65ec307990 100644 --- a/trunk/drivers/usb/host/ohci-pxa27x.c +++ b/trunk/drivers/usb/host/ohci-pxa27x.c @@ -26,12 +26,18 @@ #include #include #include -#include + + +#define PMM_NPS_MODE 1 +#define PMM_GLOBAL_MODE 2 +#define PMM_PERPORT_MODE 3 #define PXA_UHC_MAX_PORTNUM 3 #define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 ) +static int pxa27x_ohci_pmm_state; + /* PMM_NPS_MODE -- PMM Non-power switching mode Ports are powered continuously. @@ -44,6 +50,8 @@ */ static int pxa27x_ohci_select_pmm( int mode ) { + pxa27x_ohci_pmm_state = mode; + switch ( mode ) { case PMM_NPS_MODE: UHCRHDA |= RH_A_NPS; @@ -63,6 +71,7 @@ static int pxa27x_ohci_select_pmm( int mode ) "Invalid mode %d, set to non-power switch mode.\n", mode ); + pxa27x_ohci_pmm_state = PMM_NPS_MODE; UHCRHDA |= RH_A_NPS; } @@ -73,13 +82,8 @@ extern int usb_disabled(void); /*-------------------------------------------------------------------------*/ -static int pxa27x_start_hc(struct device *dev) +static void pxa27x_start_hc(struct platform_device *dev) { - int retval = 0; - struct pxaohci_platform_data *inf; - - inf = dev->platform_data; - pxa_set_cken(CKEN10_USBHOST, 1); UHCHR |= UHCHR_FHR; @@ -90,11 +94,21 @@ static int pxa27x_start_hc(struct device *dev) while (UHCHR & UHCHR_FSBIR) cpu_relax(); - if (inf->init) - retval = inf->init(dev); + /* This could be properly abstracted away through the + device data the day more machines are supported and + their differences can be figured out correctly. */ + if (machine_is_mainstone()) { + /* setup Port1 GPIO pin. */ + pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */ + pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */ - if (retval < 0) - return retval; + /* Set the Power Control Polarity Low and Power Sense + Polarity Low to active low. Supply power to USB ports. */ + UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & + ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); + + pxa27x_ohci_pmm_state = PMM_PERPORT_MODE; + } UHCHR &= ~UHCHR_SSE; @@ -103,19 +117,10 @@ static int pxa27x_start_hc(struct device *dev) /* Clear any OTG Pin Hold */ if (PSSR & PSSR_OTGPH) PSSR |= PSSR_OTGPH; - - return 0; } -static void pxa27x_stop_hc(struct device *dev) +static void pxa27x_stop_hc(struct platform_device *dev) { - struct pxaohci_platform_data *inf; - - inf = dev->platform_data; - - if (inf->exit) - inf->exit(dev); - UHCHR |= UHCHR_FHR; udelay(11); UHCHR &= ~UHCHR_FHR; @@ -142,27 +147,22 @@ static void pxa27x_stop_hc(struct device *dev) * through the hotplug entry's driver_data. * */ -int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev) +int usb_hcd_pxa27x_probe (const struct hc_driver *driver, + struct platform_device *dev) { int retval; struct usb_hcd *hcd; - struct pxaohci_platform_data *inf; - inf = pdev->dev.platform_data; - - if (!inf) - return -ENODEV; - - if (pdev->resource[1].flags != IORESOURCE_IRQ) { + if (dev->resource[1].flags != IORESOURCE_IRQ) { pr_debug ("resource[1] is not IORESOURCE_IRQ"); return -ENOMEM; } - hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x"); + hcd = usb_create_hcd (driver, &dev->dev, "pxa27x"); if (!hcd) return -ENOMEM; - hcd->rsrc_start = pdev->resource[0].start; - hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; + hcd->rsrc_start = dev->resource[0].start; + hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { pr_debug("request_mem_region failed"); @@ -177,22 +177,18 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device goto err2; } - if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) { - pr_debug("pxa27x_start_hc failed"); - goto err3; - } + pxa27x_start_hc(dev); /* Select Power Management Mode */ - pxa27x_ohci_select_pmm(inf->port_mode); + pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state); ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT); + retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); if (retval == 0) return retval; - pxa27x_stop_hc(&pdev->dev); - err3: + pxa27x_stop_hc(dev); iounmap(hcd->regs); err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); @@ -215,10 +211,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device * context, normally "rmmod", "apmd", or something similar. * */ -void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev) +void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev) { usb_remove_hcd(hcd); - pxa27x_stop_hc(&pdev->dev); + pxa27x_stop_hc(dev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); @@ -296,12 +292,15 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev) { + int ret; + pr_debug ("In ohci_hcd_pxa27x_drv_probe"); if (usb_disabled()) return -ENODEV; - return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev); + ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev); + return ret; } static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) @@ -309,55 +308,31 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_hcd_pxa27x_remove(hcd, pdev); - platform_set_drvdata(pdev, NULL); return 0; } -#ifdef CONFIG_PM -static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state) +static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *dev, pm_message_t state) { - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - - if (time_before(jiffies, ohci->next_statechange)) - msleep(5); - ohci->next_statechange = jiffies; - - pxa27x_stop_hc(&pdev->dev); - hcd->state = HC_STATE_SUSPENDED; - pdev->dev.power.power_state = PMSG_SUSPEND; +// struct usb_hcd *hcd = platform_get_drvdata(dev); + printk("%s: not implemented yet\n", __FUNCTION__); return 0; } -static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev) +static int ohci_hcd_pxa27x_drv_resume(struct platform_device *dev) { - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int status; - - if (time_before(jiffies, ohci->next_statechange)) - msleep(5); - ohci->next_statechange = jiffies; - - if ((status = pxa27x_start_hc(&pdev->dev)) < 0) - return status; - - pdev->dev.power.power_state = PMSG_ON; - usb_hcd_resume_root_hub(hcd); +// struct usb_hcd *hcd = platform_get_drvdata(dev); + printk("%s: not implemented yet\n", __FUNCTION__); return 0; } -#endif static struct platform_driver ohci_hcd_pxa27x_driver = { .probe = ohci_hcd_pxa27x_drv_probe, .remove = ohci_hcd_pxa27x_drv_remove, -#ifdef CONFIG_PM .suspend = ohci_hcd_pxa27x_drv_suspend, .resume = ohci_hcd_pxa27x_drv_resume, -#endif .driver = { .name = "pxa27x-ohci", }, diff --git a/trunk/drivers/usb/host/pci-quirks.c b/trunk/drivers/usb/host/pci-quirks.c index 3ef2c0cdf1db..e46528c825bf 100644 --- a/trunk/drivers/usb/host/pci-quirks.c +++ b/trunk/drivers/usb/host/pci-quirks.c @@ -9,6 +9,12 @@ */ #include +#ifdef CONFIG_USB_DEBUG +#define DEBUG +#else +#undef DEBUG +#endif + #include #include #include diff --git a/trunk/drivers/usb/host/sl811-hcd.c b/trunk/drivers/usb/host/sl811-hcd.c index 517360b77d8e..a7722a6a5a5b 100644 --- a/trunk/drivers/usb/host/sl811-hcd.c +++ b/trunk/drivers/usb/host/sl811-hcd.c @@ -32,6 +32,13 @@ #undef PACKET_TRACE #include + +#ifdef CONFIG_USB_DEBUG +# define DEBUG +#else +# undef DEBUG +#endif + #include #include #include @@ -1574,9 +1581,7 @@ sl811h_start(struct usb_hcd *hcd) hcd->state = HC_STATE_RUNNING; if (sl811->board) { - if (!device_can_wakeup(hcd->self.controller)) - device_init_wakeup(hcd->self.controller, - sl811->board->can_wakeup); + hcd->can_wakeup = sl811->board->can_wakeup; hcd->power_budget = sl811->board->power * 2; } @@ -1800,10 +1805,9 @@ sl811h_resume(struct platform_device *dev) * let's assume it'd only be powered to enable remote wakeup. */ if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND - || !device_can_wakeup(&hcd->self.root_hub->dev)) { + || !hcd->can_wakeup) { sl811->port1 = 0; port_power(sl811, 1); - usb_root_hub_lost_power(hcd->self.root_hub); return 0; } diff --git a/trunk/drivers/usb/host/sl811_cs.c b/trunk/drivers/usb/host/sl811_cs.c index 5056b7459994..e73faf831b24 100644 --- a/trunk/drivers/usb/host/sl811_cs.c +++ b/trunk/drivers/usb/host/sl811_cs.c @@ -38,7 +38,7 @@ MODULE_LICENSE("GPL"); /* MACROS */ /*====================================================================*/ -#if defined(DEBUG) || defined(PCMCIA_DEBUG) +#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG) static int pc_debug = 0; module_param(pc_debug, int, 0644); @@ -129,8 +129,7 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq) resources[2].end = base_addr + 1; /* The driver core will probe for us. We know sl811-hcd has been - * initialized already because of the link order dependency created - * by referencing "sl811h_driver". + * initialized already because of the link order dependency. */ platform_dev.name = sl811h_driver.name; return platform_device_register(&platform_dev); diff --git a/trunk/drivers/usb/host/uhci-debug.c b/trunk/drivers/usb/host/uhci-debug.c index 5832953086f8..151154df37fa 100644 --- a/trunk/drivers/usb/host/uhci-debug.c +++ b/trunk/drivers/usb/host/uhci-debug.c @@ -2,8 +2,8 @@ * UHCI-specific debugging code. Invaluable when something * goes wrong, but don't get in my face. * - * Kernel visible pointers are surrounded in []s and bus - * visible pointers are surrounded in ()s + * Kernel visible pointers are surrounded in []'s and bus + * visible pointers are surrounded in ()'s * * (C) Copyright 1999 Linus Torvalds * (C) Copyright 1999-2001 Johannes Erdfelt @@ -19,7 +19,7 @@ static struct dentry *uhci_debugfs_root = NULL; -/* Handle REALLY large printks so we don't overflow buffers */ +/* Handle REALLY large printk's so we don't overflow buffers */ static inline void lprintk(char *buf) { char *p; @@ -160,7 +160,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) } if (active && ni > i) { - out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i); + out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i); tmp = ntmp; td = ntd; i = ni; @@ -173,7 +173,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) if (list_empty(&urbp->queue_list) || urbp->queued) goto out; - out += sprintf(out, "%*sQueued QHs:\n", -space, "--"); + out += sprintf(out, "%*sQueued QH's:\n", -space, "--"); head = &urbp->queue_list; tmp = head->next; @@ -197,7 +197,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) } #ifdef CONFIG_PROC_FS -static const char * const qh_names[] = { +static const char *qh_names[] = { "skel_int128_qh", "skel_int64_qh", "skel_int32_qh", "skel_int16_qh", "skel_int8_qh", "skel_int4_qh", @@ -464,7 +464,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) } while (tmp != head); } - out += sprintf(out, "Skeleton QHs\n"); + out += sprintf(out, "Skeleton QH's\n"); for (i = 0; i < UHCI_NUM_SKELQH; ++i) { int shown = 0; diff --git a/trunk/drivers/usb/host/uhci-hcd.c b/trunk/drivers/usb/host/uhci-hcd.c index dfe121d35887..79efaf7d86a3 100644 --- a/trunk/drivers/usb/host/uhci-hcd.c +++ b/trunk/drivers/usb/host/uhci-hcd.c @@ -23,6 +23,11 @@ */ #include +#ifdef CONFIG_USB_DEBUG +#define DEBUG +#else +#undef DEBUG +#endif #include #include #include @@ -62,10 +67,10 @@ Alan Stern" /* * debug = 0, no debugging messages - * debug = 1, dump failed URBs except for stalls - * debug = 2, dump all failed URBs (including stalls) + * debug = 1, dump failed URB's except for stalls + * debug = 2, dump all failed URB's (including stalls) * show all queues in /debug/uhci/[pci_addr] - * debug = 3, show all TDs in URBs when dumping + * debug = 3, show all TD's in URB's when dumping */ #ifdef DEBUG static int debug = 1; @@ -88,7 +93,7 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci); #define FSBR_DELAY msecs_to_jiffies(50) /* When we timeout an idle transfer for FSBR, we'll switch it over to */ -/* depth first traversal. We'll do it in groups of this number of TDs */ +/* depth first traversal. We'll do it in groups of this number of TD's */ /* to make sure it doesn't hog all of the bandwidth */ #define DEPTH_INTERVAL 5 @@ -473,6 +478,8 @@ static int uhci_start(struct usb_hcd *hcd) struct dentry *dentry; hcd->uses_new_polling = 1; + if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM)) + hcd->can_wakeup = 1; /* Assume it supports PME# */ dentry = debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, @@ -566,7 +573,7 @@ static int uhci_start(struct usb_hcd *hcd) uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH; /* This dummy TD is to work around a bug in Intel PIIX controllers */ - uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | + uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0); uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle); @@ -728,9 +735,8 @@ static int uhci_resume(struct usb_hcd *hcd) dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); - /* Since we aren't in D3 any more, it's safe to set this flag - * even if the controller was dead. It might not even be dead - * any more, if the firmware or quirks code has reset it. + /* We aren't in D3 state anymore, we do that even if dead as I + * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0 */ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); mb(); @@ -749,12 +755,8 @@ static int uhci_resume(struct usb_hcd *hcd) check_and_reset_hc(uhci); configure_hc(uhci); - if (uhci->rh_state == UHCI_RH_RESET) { - - /* The controller had to be reset */ - usb_root_hub_lost_power(hcd->self.root_hub); + if (uhci->rh_state == UHCI_RH_RESET) suspend_rh(uhci, UHCI_RH_SUSPENDED); - } spin_unlock_irq(&uhci->lock); @@ -880,7 +882,7 @@ static int __init uhci_hcd_init(void) init_failed: if (kmem_cache_destroy(uhci_up_cachep)) - warn("not all urb_privs were freed!"); + warn("not all urb_priv's were freed!"); up_failed: debugfs_remove(uhci_debugfs_root); @@ -898,7 +900,7 @@ static void __exit uhci_hcd_cleanup(void) pci_unregister_driver(&uhci_pci_driver); if (kmem_cache_destroy(uhci_up_cachep)) - warn("not all urb_privs were freed!"); + warn("not all urb_priv's were freed!"); debugfs_remove(uhci_debugfs_root); kfree(errbuf); diff --git a/trunk/drivers/usb/host/uhci-hcd.h b/trunk/drivers/usb/host/uhci-hcd.h index 8b4b887a7d41..e576db57a926 100644 --- a/trunk/drivers/usb/host/uhci-hcd.h +++ b/trunk/drivers/usb/host/uhci-hcd.h @@ -71,6 +71,8 @@ #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ +#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ + #define UHCI_PTR_BITS cpu_to_le32(0x000F) #define UHCI_PTR_TERM cpu_to_le32(0x0001) #define UHCI_PTR_QH cpu_to_le32(0x0002) @@ -166,11 +168,9 @@ static __le32 inline qh_element(struct uhci_qh *qh) { #define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */ #define TD_TOKEN_PID_MASK 0xFF -#define uhci_explen(len) ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \ - TD_TOKEN_EXPLEN_SHIFT) +#define uhci_explen(len) ((len) << TD_TOKEN_EXPLEN_SHIFT) -#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \ - 1) & TD_TOKEN_EXPLEN_MASK) +#define uhci_expected_length(token) ((((token) >> 21) + 1) & TD_TOKEN_EXPLEN_MASK) #define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1) #define uhci_endpoint(token) (((token) >> 15) & 0xf) #define uhci_devaddr(token) (((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7f) @@ -223,10 +223,10 @@ static u32 inline td_status(struct uhci_td *td) { */ /* - * The UHCI driver places Interrupt, Control and Bulk into QHs both - * to group together TDs for one transfer, and also to facilitate queuing - * of URBs. To make it easy to insert entries into the schedule, we have - * a skeleton of QHs for each predefined Interrupt latency, low-speed + * The UHCI driver places Interrupt, Control and Bulk into QH's both + * to group together TD's for one transfer, and also to faciliate queuing + * of URB's. To make it easy to insert entries into the schedule, we have + * a skeleton of QH's for each predefined Interrupt latency, low-speed * control, full-speed control and terminating QH (see explanation for * the terminating QH below). * @@ -257,8 +257,8 @@ static u32 inline td_status(struct uhci_td *td) { * reclamation. * * Isochronous transfers are stored before the start of the skeleton - * schedule and don't use QHs. While the UHCI spec doesn't forbid the - * use of QHs for Isochronous, it doesn't use them either. And the spec + * schedule and don't use QH's. While the UHCI spec doesn't forbid the + * use of QH's for Isochronous, it doesn't use them either. And the spec * says that queues never advance on an error completion status, which * makes them totally unsuitable for Isochronous transfers. */ @@ -359,7 +359,7 @@ struct uhci_hcd { struct dma_pool *td_pool; struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ - struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */ + struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ spinlock_t lock; @@ -389,22 +389,22 @@ struct uhci_hcd { unsigned long resuming_ports; unsigned long ports_timeout; /* Time to stop signalling */ - /* Main list of URBs currently controlled by this HC */ + /* Main list of URB's currently controlled by this HC */ struct list_head urb_list; - /* List of QHs that are done, but waiting to be unlinked (race) */ + /* List of QH's that are done, but waiting to be unlinked (race) */ struct list_head qh_remove_list; unsigned int qh_remove_age; /* Age in frames */ - /* List of TDs that are done, but waiting to be freed (race) */ + /* List of TD's that are done, but waiting to be freed (race) */ struct list_head td_remove_list; unsigned int td_remove_age; /* Age in frames */ - /* List of asynchronously unlinked URBs */ + /* List of asynchronously unlinked URB's */ struct list_head urb_remove_list; unsigned int urb_remove_age; /* Age in frames */ - /* List of URBs awaiting completion callback */ + /* List of URB's awaiting completion callback */ struct list_head complete_list; int rh_numports; /* Number of root-hub ports */ diff --git a/trunk/drivers/usb/host/uhci-q.c b/trunk/drivers/usb/host/uhci-q.c index b6076004a437..7e46887d9e12 100644 --- a/trunk/drivers/usb/host/uhci-q.c +++ b/trunk/drivers/usb/host/uhci-q.c @@ -80,7 +80,7 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status, } /* - * We insert Isochronous URBs directly into the frame list at the beginning + * We insert Isochronous URB's directly into the frame list at the beginning */ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum) { @@ -369,7 +369,7 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru uhci_fixup_toggle(urb, uhci_toggle(td_token(lltd)) ^ 1)); - /* All qhs in the queue need to link to the next queue */ + /* All qh's in the queue need to link to the next queue */ urbp->qh->link = eurbp->qh->link; wmb(); /* Make sure we flush everything */ @@ -502,7 +502,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) } /* Check to see if the remove list is empty. Set the IOC bit */ - /* to force an interrupt so we can remove the TDs*/ + /* to force an interrupt so we can remove the TD's*/ if (list_empty(&uhci->td_remove_list)) uhci_set_next_interrupt(uhci); @@ -596,7 +596,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur return -ENOMEM; uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(8), + uhci_fill_td(td, status, destination | uhci_explen(7), urb->setup_dma); /* @@ -612,7 +612,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur } /* - * Build the DATA TDs + * Build the DATA TD's */ while (len > 0) { int pktsze = len; @@ -628,7 +628,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur destination ^= TD_TOKEN_TOGGLE; uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(pktsze), + uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1), data); data += pktsze; @@ -658,7 +658,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur uhci_add_td_to_urb(urb, td); uhci_fill_td(td, status | TD_CTRL_IOC, - destination | uhci_explen(0), 0); + destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0); qh = uhci_alloc_qh(uhci); if (!qh) @@ -744,7 +744,7 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) urb->actual_length = 0; - /* The rest of the TDs (but the last) are data */ + /* The rest of the TD's (but the last) are data */ tmp = tmp->next; while (tmp != head && tmp->next != head) { unsigned int ctrlstat; @@ -848,7 +848,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb status |= TD_CTRL_SPD; /* - * Build the DATA TDs + * Build the DATA TD's */ do { /* Allow zero length packets */ int pktsze = maxsze; @@ -864,7 +864,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb return -ENOMEM; uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(pktsze) | + uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) | (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), data); @@ -890,7 +890,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb return -ENOMEM; uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(0) | + uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) | (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), data); @@ -1025,7 +1025,7 @@ static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsig list_for_each_entry(up, &uhci->urb_list, urb_list) { struct urb *u = up->urb; - /* look for pending URBs with identical pipe handle */ + /* look for pending URB's with identical pipe handle */ if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && (u->status == -EINPROGRESS) && (u != urb)) { if (!last_urb) @@ -1092,7 +1092,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) return -ENOMEM; uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length), + uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1), urb->transfer_dma + urb->iso_frame_desc[i].offset); if (i + 1 >= urb->number_of_packets) @@ -1355,7 +1355,7 @@ static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb) uhci_delete_queued_urb(uhci, urb); - /* The interrupt loop will reclaim the QHs */ + /* The interrupt loop will reclaim the QH's */ uhci_remove_qh(uhci, urbp->qh); urbp->qh = NULL; } @@ -1413,7 +1413,7 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb) list_for_each_entry(td, head, list) { /* * Make sure we don't do the last one (since it'll have the - * TERM bit set) as well as we skip every so many TDs to + * TERM bit set) as well as we skip every so many TD's to * make sure it doesn't hog the bandwidth */ if (td->list.next != head && (count % DEPTH_INTERVAL) == diff --git a/trunk/drivers/usb/image/mdc800.c b/trunk/drivers/usb/image/mdc800.c index 049871145d63..1d973bcf56aa 100644 --- a/trunk/drivers/usb/image/mdc800.c +++ b/trunk/drivers/usb/image/mdc800.c @@ -962,6 +962,7 @@ MODULE_DEVICE_TABLE (usb, mdc800_table); */ static struct usb_driver mdc800_usb_driver = { + .owner = THIS_MODULE, .name = "mdc800", .probe = mdc800_usb_probe, .disconnect = mdc800_usb_disconnect, diff --git a/trunk/drivers/usb/image/microtek.c b/trunk/drivers/usb/image/microtek.c index 458f2acdeb0a..950543aa5ac7 100644 --- a/trunk/drivers/usb/image/microtek.c +++ b/trunk/drivers/usb/image/microtek.c @@ -160,6 +160,7 @@ static void mts_usb_disconnect(struct usb_interface *intf); static struct usb_device_id mts_usb_ids []; static struct usb_driver mts_usb_driver = { + .owner = THIS_MODULE, .name = "microtekX6", .probe = mts_usb_probe, .disconnect = mts_usb_disconnect, diff --git a/trunk/drivers/usb/input/Kconfig b/trunk/drivers/usb/input/Kconfig index 509dd0a04c54..1e53934907c0 100644 --- a/trunk/drivers/usb/input/Kconfig +++ b/trunk/drivers/usb/input/Kconfig @@ -273,20 +273,6 @@ config USB_ATI_REMOTE To compile this driver as a module, choose M here: the module will be called ati_remote. -config USB_ATI_REMOTE2 - tristate "ATI / Philips USB RF remote control" - depends on USB && INPUT - ---help--- - Say Y here if you want to use an ATI or Philips USB RF remote control. - These are RF remotes with USB receivers. - ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards - and is also available as a separate product. - This driver provides mouse pointer, left and right mouse buttons, - and maps all the other remote buttons to keypress events. - - To compile this driver as a module, choose M here: the module will be - called ati_remote2. - config USB_KEYSPAN_REMOTE tristate "Keyspan DMR USB remote control (EXPERIMENTAL)" depends on USB && INPUT && EXPERIMENTAL diff --git a/trunk/drivers/usb/input/Makefile b/trunk/drivers/usb/input/Makefile index d512d9f488fe..07cb17db42fc 100644 --- a/trunk/drivers/usb/input/Makefile +++ b/trunk/drivers/usb/input/Makefile @@ -28,7 +28,6 @@ endif obj-$(CONFIG_USB_AIPTEK) += aiptek.o obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o -obj-$(CONFIG_USB_ATI_REMOTE2) += ati_remote2.o obj-$(CONFIG_USB_HID) += usbhid.o obj-$(CONFIG_USB_KBD) += usbkbd.o obj-$(CONFIG_USB_KBTAB) += kbtab.o diff --git a/trunk/drivers/usb/input/acecad.c b/trunk/drivers/usb/input/acecad.c index df29b8078b54..a32558b4048e 100644 --- a/trunk/drivers/usb/input/acecad.c +++ b/trunk/drivers/usb/input/acecad.c @@ -261,6 +261,7 @@ static struct usb_device_id usb_acecad_id_table [] = { 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, diff --git a/trunk/drivers/usb/input/aiptek.c b/trunk/drivers/usb/input/aiptek.c index a6693b0d1c4c..0e2505c073db 100644 --- a/trunk/drivers/usb/input/aiptek.c +++ b/trunk/drivers/usb/input/aiptek.c @@ -338,7 +338,7 @@ struct aiptek { * the bitmap which comes from the tablet. This hides the * issue that the F_keys are not sequentially numbered. */ -static const int macroKeyEvents[] = { +static int macroKeyEvents[] = { KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, @@ -2093,7 +2093,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) /* Programming the tablet macro keys needs to be done with a for loop * as the keycodes are discontiguous. */ - for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i) + for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i) set_bit(macroKeyEvents[i], inputdev->keybit); /* @@ -2135,7 +2135,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) * not an error :-) */ - for (i = 0; i < ARRAY_SIZE(speeds); ++i) { + for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) { aiptek->curSetting.programmableDelay = speeds[i]; (void)aiptek_program_tablet(aiptek); if (aiptek->inputdev->absmax[ABS_X] > 0) { @@ -2190,6 +2190,7 @@ fail1: input_free_device(inputdev); static void aiptek_disconnect(struct usb_interface *intf); static struct usb_driver aiptek_driver = { + .owner = THIS_MODULE, .name = "aiptek", .probe = aiptek_probe, .disconnect = aiptek_disconnect, diff --git a/trunk/drivers/usb/input/appletouch.c b/trunk/drivers/usb/input/appletouch.c index 1949b54f41f2..15840db092a5 100644 --- a/trunk/drivers/usb/input/appletouch.c +++ b/trunk/drivers/usb/input/appletouch.c @@ -452,6 +452,7 @@ static int atp_resume(struct usb_interface *iface) } static struct usb_driver atp_driver = { + .owner = THIS_MODULE, .name = "appletouch", .probe = atp_probe, .disconnect = atp_disconnect, diff --git a/trunk/drivers/usb/input/ati_remote.c b/trunk/drivers/usb/input/ati_remote.c index f7bdc506e613..9a2a47db9494 100644 --- a/trunk/drivers/usb/input/ati_remote.c +++ b/trunk/drivers/usb/input/ati_remote.c @@ -96,7 +96,6 @@ #include #include #include -#include /* * Module and Version Information, Module Parameters @@ -147,7 +146,7 @@ static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; /* Acceleration curve for directional control pad */ -static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; +static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; /* Duplicate event filtering time. * Sequential, identical KIND_FILTERED inputs with less than @@ -198,7 +197,7 @@ struct ati_remote { #define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/ /* Translation table from hardware messages to input events. */ -static const struct { +static struct { short kind; unsigned char data1, data2; int type; @@ -296,6 +295,7 @@ static void ati_remote_disconnect (struct usb_interface *interface); /* usb specific object to register with the usb subsystem */ static struct usb_driver ati_remote_driver = { + .owner = THIS_MODULE, .name = "ati_remote", .probe = ati_remote_probe, .disconnect = ati_remote_disconnect, @@ -472,7 +472,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) /* Filter duplicate events which happen "too close" together. */ if ((ati_remote->old_data[0] == data[1]) && (ati_remote->old_data[1] == data[2]) && - time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) { + ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { ati_remote->repeat_count++; } else { ati_remote->repeat_count = 0; @@ -507,16 +507,16 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) * pad down, so we increase acceleration, ramping up over two seconds to * a maximum speed. The acceleration curve is #defined above. */ - if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) { + if ((jiffies - ati_remote->old_jiffies) > (HZ >> 2)) { acc = 1; ati_remote->acc_jiffies = jiffies; } - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3))) acc = accel[0]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2))) acc = accel[1]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1))) acc = accel[2]; - else if (time_before(jiffies, ati_remote->acc_jiffies + HZ)) acc = accel[3]; - else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1))) acc = accel[5]; + else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 3)) acc = accel[0]; + else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 2)) acc = accel[1]; + else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 1)) acc = accel[2]; + else if ((jiffies - ati_remote->acc_jiffies) < HZ ) acc = accel[3]; + else if ((jiffies - ati_remote->acc_jiffies) < HZ+(HZ>>1)) acc = accel[4]; + else if ((jiffies - ati_remote->acc_jiffies) < (HZ << 1)) acc = accel[5]; else acc = accel[6]; input_regs(dev, regs); diff --git a/trunk/drivers/usb/input/ati_remote2.c b/trunk/drivers/usb/input/ati_remote2.c deleted file mode 100644 index ab1a1ae24be9..000000000000 --- a/trunk/drivers/usb/input/ati_remote2.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * ati_remote2 - ATI/Philips USB RF remote driver - * - * Copyright (C) 2005 Ville Syrjala - * - * 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 - -#define DRIVER_DESC "ATI/Philips USB RF remote driver" -#define DRIVER_VERSION "0.1" - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); -MODULE_AUTHOR("Ville Syrjala "); -MODULE_LICENSE("GPL"); - -static unsigned int mode_mask = 0x1F; -module_param(mode_mask, uint, 0644); -MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); - -static struct usb_device_id ati_remote2_id_table[] = { - { USB_DEVICE(0x0471, 0x0602) }, /* ATI Remote Wonder II */ - { } -}; -MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); - -static struct { - int hw_code; - int key_code; -} ati_remote2_key_table[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x0c, KEY_POWER }, - { 0x0d, KEY_MUTE }, - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x20, KEY_CHANNELUP }, - { 0x21, KEY_CHANNELDOWN }, - { 0x28, KEY_FORWARD }, - { 0x29, KEY_REWIND }, - { 0x2c, KEY_PLAY }, - { 0x30, KEY_PAUSE }, - { 0x31, KEY_STOP }, - { 0x37, KEY_RECORD }, - { 0x38, KEY_DVD }, - { 0x39, KEY_TV }, - { 0x54, KEY_MENU }, - { 0x58, KEY_UP }, - { 0x59, KEY_DOWN }, - { 0x5a, KEY_LEFT }, - { 0x5b, KEY_RIGHT }, - { 0x5c, KEY_OK }, - { 0x78, KEY_A }, - { 0x79, KEY_B }, - { 0x7a, KEY_C }, - { 0x7b, KEY_D }, - { 0x7c, KEY_E }, - { 0x7d, KEY_F }, - { 0x82, KEY_ENTER }, - { 0x8e, KEY_VENDOR }, - { 0x96, KEY_COFFEE }, - { 0xa9, BTN_LEFT }, - { 0xaa, BTN_RIGHT }, - { 0xbe, KEY_QUESTION }, - { 0xd5, KEY_FRONT }, - { 0xd0, KEY_EDIT }, - { 0xf9, KEY_INFO }, - { (0x00 << 8) | 0x3f, KEY_PROG1 }, - { (0x01 << 8) | 0x3f, KEY_PROG2 }, - { (0x02 << 8) | 0x3f, KEY_PROG3 }, - { (0x03 << 8) | 0x3f, KEY_PROG4 }, - { (0x04 << 8) | 0x3f, KEY_PC }, - { 0, KEY_RESERVED } -}; - -struct ati_remote2 { - struct input_dev *idev; - struct usb_device *udev; - - struct usb_interface *intf[2]; - struct usb_endpoint_descriptor *ep[2]; - struct urb *urb[2]; - void *buf[2]; - dma_addr_t buf_dma[2]; - - unsigned long jiffies; - int mode; - - char name[64]; - char phys[64]; -}; - -static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); -static void ati_remote2_disconnect(struct usb_interface *interface); - -static struct usb_driver ati_remote2_driver = { - .name = "ati_remote2", - .probe = ati_remote2_probe, - .disconnect = ati_remote2_disconnect, - .id_table = ati_remote2_id_table, -}; - -static int ati_remote2_open(struct input_dev *idev) -{ - struct ati_remote2 *ar2 = idev->private; - int r; - - r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); - if (r) { - dev_err(&ar2->intf[0]->dev, - "%s: usb_submit_urb() = %d\n", __FUNCTION__, r); - return r; - } - r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); - if (r) { - usb_kill_urb(ar2->urb[0]); - dev_err(&ar2->intf[1]->dev, - "%s: usb_submit_urb() = %d\n", __FUNCTION__, r); - return r; - } - - return 0; -} - -static void ati_remote2_close(struct input_dev *idev) -{ - struct ati_remote2 *ar2 = idev->private; - - usb_kill_urb(ar2->urb[0]); - usb_kill_urb(ar2->urb[1]); -} - -static void ati_remote2_input_mouse(struct ati_remote2 *ar2, struct pt_regs *regs) -{ - struct input_dev *idev = ar2->idev; - u8 *data = ar2->buf[0]; - - if (data[0] > 4) { - dev_err(&ar2->intf[0]->dev, - "Unknown mode byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - if (!((1 << data[0]) & mode_mask)) - return; - - input_regs(idev, regs); - input_event(idev, EV_REL, REL_X, (s8) data[1]); - input_event(idev, EV_REL, REL_Y, (s8) data[2]); - input_sync(idev); -} - -static int ati_remote2_lookup(unsigned int hw_code) -{ - int i; - - for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) - if (ati_remote2_key_table[i].hw_code == hw_code) - return i; - - return -1; -} - -static void ati_remote2_input_key(struct ati_remote2 *ar2, struct pt_regs *regs) -{ - struct input_dev *idev = ar2->idev; - u8 *data = ar2->buf[1]; - int hw_code, index; - - if (data[0] > 4) { - dev_err(&ar2->intf[1]->dev, - "Unknown mode byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - hw_code = data[2]; - /* - * Mode keys (AUX1-AUX4, PC) all generate the same code byte. - * Use the mode byte to figure out which one was pressed. - */ - if (hw_code == 0x3f) { - /* - * For some incomprehensible reason the mouse pad generates - * events which look identical to the events from the last - * pressed mode key. Naturally we don't want to generate key - * events for the mouse pad so we filter out any subsequent - * events from the same mode key. - */ - if (ar2->mode == data[0]) - return; - - if (data[1] == 0) - ar2->mode = data[0]; - - hw_code |= data[0] << 8; - } - - if (!((1 << data[0]) & mode_mask)) - return; - - index = ati_remote2_lookup(hw_code); - if (index < 0) { - dev_err(&ar2->intf[1]->dev, - "Unknown code byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - switch (data[1]) { - case 0: /* release */ - break; - case 1: /* press */ - ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_DELAY]); - break; - case 2: /* repeat */ - - /* No repeat for mouse buttons. */ - if (ati_remote2_key_table[index].key_code == BTN_LEFT || - ati_remote2_key_table[index].key_code == BTN_RIGHT) - return; - - if (!time_after_eq(jiffies, ar2->jiffies)) - return; - - ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_PERIOD]); - break; - default: - dev_err(&ar2->intf[1]->dev, - "Unknown state byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - input_regs(idev, regs); - input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]); - input_sync(idev); -} - -static void ati_remote2_complete_mouse(struct urb *urb, struct pt_regs *regs) -{ - struct ati_remote2 *ar2 = urb->context; - int r; - - switch (urb->status) { - case 0: - ati_remote2_input_mouse(ar2, regs); - break; - case -ENOENT: - case -EILSEQ: - case -ECONNRESET: - case -ESHUTDOWN: - dev_dbg(&ar2->intf[0]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - return; - default: - dev_err(&ar2->intf[0]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - } - - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r) - dev_err(&ar2->intf[0]->dev, - "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); -} - -static void ati_remote2_complete_key(struct urb *urb, struct pt_regs *regs) -{ - struct ati_remote2 *ar2 = urb->context; - int r; - - switch (urb->status) { - case 0: - ati_remote2_input_key(ar2, regs); - break; - case -ENOENT: - case -EILSEQ: - case -ECONNRESET: - case -ESHUTDOWN: - dev_dbg(&ar2->intf[1]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - return; - default: - dev_err(&ar2->intf[1]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - } - - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r) - dev_err(&ar2->intf[1]->dev, - "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); -} - -static int ati_remote2_input_init(struct ati_remote2 *ar2) -{ - struct input_dev *idev; - int i; - - idev = input_allocate_device(); - if (!idev) - return -ENOMEM; - - ar2->idev = idev; - idev->private = ar2; - - idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL); - idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT); - idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) - set_bit(ati_remote2_key_table[i].key_code, idev->keybit); - - idev->rep[REP_DELAY] = 250; - idev->rep[REP_PERIOD] = 33; - - idev->open = ati_remote2_open; - idev->close = ati_remote2_close; - - idev->name = ar2->name; - idev->phys = ar2->phys; - - usb_to_input_id(ar2->udev, &idev->id); - idev->cdev.dev = &ar2->udev->dev; - - i = input_register_device(idev); - if (i) - input_free_device(idev); - - return i; -} - -static int ati_remote2_urb_init(struct ati_remote2 *ar2) -{ - struct usb_device *udev = ar2->udev; - int i, pipe, maxp; - - for (i = 0; i < 2; i++) { - ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); - if (!ar2->buf[i]) - return -ENOMEM; - - ar2->urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!ar2->urb[i]) - return -ENOMEM; - - pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - maxp = maxp > 4 ? 4 : maxp; - - usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp, - i ? ati_remote2_complete_key : ati_remote2_complete_mouse, - ar2, ar2->ep[i]->bInterval); - ar2->urb[i]->transfer_dma = ar2->buf_dma[i]; - ar2->urb[i]->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - } - - return 0; -} - -static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) -{ - int i; - - for (i = 0; i < 2; i++) { - if (ar2->urb[i]) - usb_free_urb(ar2->urb[i]); - - if (ar2->buf[i]) - usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); - } -} - -static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *alt = interface->cur_altsetting; - struct ati_remote2 *ar2; - int r; - - if (alt->desc.bInterfaceNumber) - return -ENODEV; - - ar2 = kzalloc(sizeof (struct ati_remote2), GFP_KERNEL); - if (!ar2) - return -ENOMEM; - - ar2->udev = udev; - - ar2->intf[0] = interface; - ar2->ep[0] = &alt->endpoint[0].desc; - - ar2->intf[1] = usb_ifnum_to_if(udev, 1); - r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2); - if (r) - goto fail1; - alt = ar2->intf[1]->cur_altsetting; - ar2->ep[1] = &alt->endpoint[0].desc; - - r = ati_remote2_urb_init(ar2); - if (r) - goto fail2; - - usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); - strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); - - strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); - - r = ati_remote2_input_init(ar2); - if (r) - goto fail2; - - usb_set_intfdata(interface, ar2); - - return 0; - - fail2: - ati_remote2_urb_cleanup(ar2); - - usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); - fail1: - kfree(ar2); - - return r; -} - -static void ati_remote2_disconnect(struct usb_interface *interface) -{ - struct ati_remote2 *ar2; - struct usb_host_interface *alt = interface->cur_altsetting; - - if (alt->desc.bInterfaceNumber) - return; - - ar2 = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - input_unregister_device(ar2->idev); - - ati_remote2_urb_cleanup(ar2); - - usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); - - kfree(ar2); -} - -static int __init ati_remote2_init(void) -{ - int r; - - r = usb_register(&ati_remote2_driver); - if (r) - printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r); - else - printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n"); - - return r; -} - -static void __exit ati_remote2_exit(void) -{ - usb_deregister(&ati_remote2_driver); -} - -module_init(ati_remote2_init); -module_exit(ati_remote2_exit); diff --git a/trunk/drivers/usb/input/fixp-arith.h b/trunk/drivers/usb/input/fixp-arith.h index b44d398de071..26ca5b890a61 100644 --- a/trunk/drivers/usb/input/fixp-arith.h +++ b/trunk/drivers/usb/input/fixp-arith.h @@ -38,7 +38,7 @@ typedef s16 fixp_t; #define FRAC_MASK ((1< + * Copyright (C) 2004 by Daniel Ritz * Copyright (C) by Todd E. Johnson (mtouchusb.c) * * This program is free software; you can redistribute it and/or @@ -41,13 +41,15 @@ #define TOUCHKIT_MAX_YC 0x07ff #define TOUCHKIT_YC_FUZZ 0x0 #define TOUCHKIT_YC_FLAT 0x0 -#define TOUCHKIT_REPORT_DATA_SIZE 16 +#define TOUCHKIT_REPORT_DATA_SIZE 8 #define TOUCHKIT_DOWN 0x01 +#define TOUCHKIT_POINT_TOUCH 0x81 +#define TOUCHKIT_POINT_NOTOUCH 0x80 -#define TOUCHKIT_PKT_TYPE_MASK 0xFE -#define TOUCHKIT_PKT_TYPE_REPT 0x80 -#define TOUCHKIT_PKT_TYPE_DIAG 0x0A +#define TOUCHKIT_GET_TOUCHED(dat) ((((dat)[0]) & TOUCHKIT_DOWN) ? 1 : 0) +#define TOUCHKIT_GET_X(dat) (((dat)[3] << 7) | (dat)[4]) +#define TOUCHKIT_GET_Y(dat) (((dat)[1] << 7) | (dat)[2]) #define DRIVER_VERSION "v0.1" #define DRIVER_AUTHOR "Daniel Ritz " @@ -60,8 +62,6 @@ MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); struct touchkit_usb { unsigned char *data; dma_addr_t data_dma; - char buffer[TOUCHKIT_REPORT_DATA_SIZE]; - int buf_len; struct urb *irq; struct usb_device *udev; struct input_dev *input; @@ -77,128 +77,11 @@ static struct usb_device_id touchkit_devices[] = { {} }; -/* helpers to read the data */ -static inline int touchkit_get_touched(char *data) -{ - return (data[0] & TOUCHKIT_DOWN) ? 1 : 0; -} - -static inline int touchkit_get_x(char *data) -{ - return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F); -} - -static inline int touchkit_get_y(char *data) -{ - return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F); -} - - -/* processes one input packet. */ -static void touchkit_process_pkt(struct touchkit_usb *touchkit, - struct pt_regs *regs, char *pkt) -{ - int x, y; - - /* only process report packets */ - if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT) - return; - - if (swap_xy) { - y = touchkit_get_x(pkt); - x = touchkit_get_y(pkt); - } else { - x = touchkit_get_x(pkt); - y = touchkit_get_y(pkt); - } - - input_regs(touchkit->input, regs); - input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt)); - input_report_abs(touchkit->input, ABS_X, x); - input_report_abs(touchkit->input, ABS_Y, y); - input_sync(touchkit->input); -} - - -static int touchkit_get_pkt_len(char *buf) -{ - switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) { - case TOUCHKIT_PKT_TYPE_REPT: - return 5; - - case TOUCHKIT_PKT_TYPE_DIAG: - return buf[1] + 2; - } - - return 0; -} - -static void touchkit_process(struct touchkit_usb *touchkit, int len, - struct pt_regs *regs) -{ - char *buffer; - int pkt_len, buf_len, pos; - - /* if the buffer contains data, append */ - if (unlikely(touchkit->buf_len)) { - int tmp; - - /* if only 1 byte in buffer, add another one to get length */ - if (touchkit->buf_len == 1) - touchkit->buffer[1] = touchkit->data[0]; - - pkt_len = touchkit_get_pkt_len(touchkit->buffer); - - /* unknown packet: drop everything */ - if (!pkt_len) - return; - - /* append, process */ - tmp = pkt_len - touchkit->buf_len; - memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp); - touchkit_process_pkt(touchkit, regs, touchkit->buffer); - - buffer = touchkit->data + tmp; - buf_len = len - tmp; - } else { - buffer = touchkit->data; - buf_len = len; - } - - /* only one byte left in buffer */ - if (unlikely(buf_len == 1)) { - touchkit->buffer[0] = buffer[0]; - touchkit->buf_len = 1; - return; - } - - /* loop over the buffer */ - pos = 0; - while (pos < buf_len) { - /* get packet len */ - pkt_len = touchkit_get_pkt_len(buffer + pos); - - /* unknown packet: drop everything */ - if (unlikely(!pkt_len)) - return; - - /* full packet: process */ - if (likely(pkt_len <= buf_len)) { - touchkit_process_pkt(touchkit, regs, buffer + pos); - } else { - /* incomplete packet: save in buffer */ - memcpy(touchkit->buffer, buffer + pos, buf_len - pos); - touchkit->buf_len = buf_len - pos; - } - pos += pkt_len; - } -} - - static void touchkit_irq(struct urb *urb, struct pt_regs *regs) { struct touchkit_usb *touchkit = urb->context; int retval; + int x, y; switch (urb->status) { case 0: @@ -222,7 +105,20 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - touchkit_process(touchkit, urb->actual_length, regs); + if (swap_xy) { + y = TOUCHKIT_GET_X(touchkit->data); + x = TOUCHKIT_GET_Y(touchkit->data); + } else { + x = TOUCHKIT_GET_X(touchkit->data); + y = TOUCHKIT_GET_Y(touchkit->data); + } + + input_regs(touchkit->input, regs); + input_report_key(touchkit->input, BTN_TOUCH, + TOUCHKIT_GET_TOUCHED(touchkit->data)); + input_report_abs(touchkit->input, ABS_X, x); + input_report_abs(touchkit->input, ABS_Y, y); + input_sync(touchkit->input); exit: retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -371,6 +267,7 @@ static void touchkit_disconnect(struct usb_interface *intf) MODULE_DEVICE_TABLE(usb, touchkit_devices); static struct usb_driver touchkit_driver = { + .owner = THIS_MODULE, .name = "touchkitusb", .probe = touchkit_probe, .disconnect = touchkit_disconnect, diff --git a/trunk/drivers/usb/input/usbkbd.c b/trunk/drivers/usb/input/usbkbd.c index 2f3edc26cb50..226b6f90a907 100644 --- a/trunk/drivers/usb/input/usbkbd.c +++ b/trunk/drivers/usb/input/usbkbd.c @@ -345,6 +345,7 @@ static struct usb_device_id usb_kbd_id_table [] = { MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); static struct usb_driver usb_kbd_driver = { + .owner = THIS_MODULE, .name = "usbkbd", .probe = usb_kbd_probe, .disconnect = usb_kbd_disconnect, diff --git a/trunk/drivers/usb/input/usbmouse.c b/trunk/drivers/usb/input/usbmouse.c index af526135d210..230f6b1b314a 100644 --- a/trunk/drivers/usb/input/usbmouse.c +++ b/trunk/drivers/usb/input/usbmouse.c @@ -226,6 +226,7 @@ static struct usb_device_id usb_mouse_id_table [] = { MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); static struct usb_driver usb_mouse_driver = { + .owner = THIS_MODULE, .name = "usbmouse", .probe = usb_mouse_probe, .disconnect = usb_mouse_disconnect, diff --git a/trunk/drivers/usb/input/wacom.c b/trunk/drivers/usb/input/wacom.c index 48df4cfd5a42..dc099bbe12bf 100644 --- a/trunk/drivers/usb/input/wacom.c +++ b/trunk/drivers/usb/input/wacom.c @@ -945,6 +945,7 @@ static void wacom_disconnect(struct usb_interface *intf) } static struct usb_driver wacom_driver = { + .owner = THIS_MODULE, .name = "wacom", .probe = wacom_probe, .disconnect = wacom_disconnect, diff --git a/trunk/drivers/usb/input/xpad.c b/trunk/drivers/usb/input/xpad.c index e278489a80c6..43112f040b6d 100644 --- a/trunk/drivers/usb/input/xpad.c +++ b/trunk/drivers/usb/input/xpad.c @@ -70,7 +70,7 @@ #define XPAD_PKT_LEN 32 -static const struct xpad_device { +static struct xpad_device { u16 idVendor; u16 idProduct; char *name; @@ -81,13 +81,13 @@ static const struct xpad_device { { 0x0000, 0x0000, "X-Box pad" } }; -static const signed short xpad_btn[] = { +static signed short xpad_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* "analog" buttons */ BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */ -1 /* terminating entry */ }; -static const signed short xpad_abs[] = { +static signed short xpad_abs[] = { ABS_X, ABS_Y, /* left stick */ ABS_RX, ABS_RY, /* right stick */ ABS_Z, ABS_RZ, /* triggers left/right */ @@ -316,6 +316,7 @@ static void xpad_disconnect(struct usb_interface *intf) } static struct usb_driver xpad_driver = { + .owner = THIS_MODULE, .name = "xpad", .probe = xpad_probe, .disconnect = xpad_disconnect, diff --git a/trunk/drivers/usb/input/yealink.c b/trunk/drivers/usb/input/yealink.c index 1bfc105ad4d6..f526aebea502 100644 --- a/trunk/drivers/usb/input/yealink.c +++ b/trunk/drivers/usb/input/yealink.c @@ -987,6 +987,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) } static struct usb_driver yealink_driver = { + .owner = THIS_MODULE, .name = "yealink", .probe = usb_probe, .disconnect = usb_disconnect, diff --git a/trunk/drivers/usb/media/dabusb.c b/trunk/drivers/usb/media/dabusb.c index 18d8eaf408d5..27b23c55bbc7 100644 --- a/trunk/drivers/usb/media/dabusb.c +++ b/trunk/drivers/usb/media/dabusb.c @@ -812,6 +812,7 @@ static struct usb_device_id dabusb_ids [] = { MODULE_DEVICE_TABLE (usb, dabusb_ids); static struct usb_driver dabusb_driver = { + .owner = THIS_MODULE, .name = "dabusb", .probe = dabusb_probe, .disconnect = dabusb_disconnect, diff --git a/trunk/drivers/usb/media/dsbr100.c b/trunk/drivers/usb/media/dsbr100.c index 6a5700e9d428..7503f5b96f59 100644 --- a/trunk/drivers/usb/media/dsbr100.c +++ b/trunk/drivers/usb/media/dsbr100.c @@ -150,6 +150,7 @@ MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table); /* USB subsystem interface */ static struct usb_driver usb_dsbr100_driver = { + .owner = THIS_MODULE, .name = "dsbr100", .probe = usb_dsbr100_probe, .disconnect = usb_dsbr100_disconnect, diff --git a/trunk/drivers/usb/media/ibmcam.c b/trunk/drivers/usb/media/ibmcam.c index a42c22294124..ba41fc7b95c2 100644 --- a/trunk/drivers/usb/media/ibmcam.c +++ b/trunk/drivers/usb/media/ibmcam.c @@ -3457,7 +3457,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) if(init_model3_input) { if (debug > 0) info("Setting input to RCA."); - for (i=0; i < ARRAY_SIZE(initData); i++) { + for (i=0; i < (sizeof(initData)/sizeof(initData[0])); i++) { ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); } } diff --git a/trunk/drivers/usb/media/konicawc.c b/trunk/drivers/usb/media/konicawc.c index e2ede583518f..9fe2c2710d13 100644 --- a/trunk/drivers/usb/media/konicawc.c +++ b/trunk/drivers/usb/media/konicawc.c @@ -77,14 +77,14 @@ static int saturation = MAX_SATURATION/2; static int sharpness = MAX_SHARPNESS/2; static int whitebal = 3*(MAX_WHITEBAL/4); -static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 }; +static int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 }; /* These FPS speeds are from the windows config box. They are * indexed on size (0-2) and speed (0-6). Divide by 3 to get the * real fps. */ -static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 }, +static int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 }, { 24, 40, 48, 60, 72, 80, 100 }, { 18, 30, 36, 45, 54, 60, 75 }, { 6, 10, 12, 15, 18, 21, 25 } }; @@ -95,7 +95,7 @@ struct cam_size { u8 cmd; }; -static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 }, +static struct cam_size camera_sizes[] = { { 160, 120, 0x7 }, { 160, 136, 0xa }, { 176, 144, 0x4 }, { 320, 240, 0x5 } }; diff --git a/trunk/drivers/usb/media/ov511.c b/trunk/drivers/usb/media/ov511.c index 3a0e8ce67ebe..036c485d1d1e 100644 --- a/trunk/drivers/usb/media/ov511.c +++ b/trunk/drivers/usb/media/ov511.c @@ -211,7 +211,7 @@ static struct ov51x_decomp_ops *ov518_mmx_decomp_ops; /* Number of times to retry a failed I2C transaction. Increase this if you * are getting "Failed to read sensor ID..." */ -static const int i2c_detect_tries = 5; +static int i2c_detect_tries = 5; /* MMX support is present in kernel and CPU. Checked upon decomp module load. */ #if defined(__i386__) || defined(__x86_64__) @@ -6008,6 +6008,7 @@ ov51x_disconnect(struct usb_interface *intf) } static struct usb_driver ov511_driver = { + .owner = THIS_MODULE, .name = "ov511", .id_table = device_table, .probe = ov51x_probe, diff --git a/trunk/drivers/usb/media/pwc/pwc-ctrl.c b/trunk/drivers/usb/media/pwc/pwc-ctrl.c index 359c4b2df735..53099190952c 100644 --- a/trunk/drivers/usb/media/pwc/pwc-ctrl.c +++ b/trunk/drivers/usb/media/pwc/pwc-ctrl.c @@ -109,7 +109,7 @@ #define PT_RESET_CONTROL_FORMATTER 0x02 #define PT_STATUS_FORMATTER 0x03 -static const char *size2name[PSZ_MAX] = +static char *size2name[PSZ_MAX] = { "subQCIF", "QSIF", diff --git a/trunk/drivers/usb/media/pwc/pwc-if.c b/trunk/drivers/usb/media/pwc/pwc-if.c index 09ca6128ac20..5524fd70210b 100644 --- a/trunk/drivers/usb/media/pwc/pwc-if.c +++ b/trunk/drivers/usb/media/pwc/pwc-if.c @@ -111,6 +111,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id static void usb_pwc_disconnect(struct usb_interface *intf); static struct usb_driver pwc_driver = { + .owner = THIS_MODULE, .name = "Philips webcam", /* name */ .id_table = pwc_device_table, .probe = usb_pwc_probe, /* probe() */ diff --git a/trunk/drivers/usb/media/se401.c b/trunk/drivers/usb/media/se401.c index b2ae29af5940..f69e443cd1bc 100644 --- a/trunk/drivers/usb/media/se401.c +++ b/trunk/drivers/usb/media/se401.c @@ -1401,6 +1401,7 @@ static void se401_disconnect(struct usb_interface *intf) } static struct usb_driver se401_driver = { + .owner = THIS_MODULE, .name = "se401", .id_table = device_table, .probe = se401_probe, diff --git a/trunk/drivers/usb/media/sn9c102_core.c b/trunk/drivers/usb/media/sn9c102_core.c index 8d1a1c357d5a..b2e66e3b90aa 100644 --- a/trunk/drivers/usb/media/sn9c102_core.c +++ b/trunk/drivers/usb/media/sn9c102_core.c @@ -1316,7 +1316,7 @@ static int sn9c102_init(struct sn9c102_device* cam) struct v4l2_control ctrl; struct v4l2_queryctrl *qctrl; struct v4l2_rect* rect; - u8 i = 0; + u8 i = 0, n = 0; int err = 0; if (!(cam->state & DEV_INITIALIZED)) { @@ -1352,7 +1352,7 @@ static int sn9c102_init(struct sn9c102_device* cam) return err; if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) - DBG(3, "Compressed video format is active, quality %d", + DBG(3, "Compressed video format is active, quality %d", cam->compression.quality) else DBG(3, "Uncompressed video format is active") @@ -1364,8 +1364,9 @@ static int sn9c102_init(struct sn9c102_device* cam) } if (s->set_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (s->qctrl[i].id != 0 && + n = sizeof(s->qctrl) / sizeof(s->qctrl[0]); + for (i = 0; i < n; i++) + if (s->qctrl[i].id != 0 && !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { ctrl.id = s->qctrl[i].id; ctrl.value = qctrl[i].default_value; @@ -1387,7 +1388,7 @@ static int sn9c102_init(struct sn9c102_device* cam) init_waitqueue_head(&cam->wait_stream); cam->nreadbuffers = 2; memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); - memcpy(&(s->_rect), &(s->cropcap.defrect), + memcpy(&(s->_rect), &(s->cropcap.defrect), sizeof(struct v4l2_rect)); cam->state |= DEV_INITIALIZED; } @@ -1809,12 +1810,13 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, { struct sn9c102_sensor* s = cam->sensor; struct v4l2_queryctrl qc; - u8 i; + u8 i, n; if (copy_from_user(&qc, arg, sizeof(qc))) return -EFAULT; - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + n = sizeof(s->qctrl) / sizeof(s->qctrl[0]); + for (i = 0; i < n; i++) if (qc.id && qc.id == s->qctrl[i].id) { memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); if (copy_to_user(arg, &qc, sizeof(qc))) @@ -1850,7 +1852,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, { struct sn9c102_sensor* s = cam->sensor; struct v4l2_control ctrl; - u8 i; + u8 i, n; int err = 0; if (!s->set_ctrl) @@ -1859,7 +1861,8 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, if (copy_from_user(&ctrl, arg, sizeof(ctrl))) return -EFAULT; - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + n = sizeof(s->qctrl) / sizeof(s->qctrl[0]); + for (i = 0; i < n; i++) if (ctrl.id == s->qctrl[i].id) { if (ctrl.value < s->qctrl[i].minimum || ctrl.value > s->qctrl[i].maximum) @@ -2541,7 +2544,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) unsigned int i, n; int err = 0, r; - n = ARRAY_SIZE(sn9c102_id_table); + n = sizeof(sn9c102_id_table)/sizeof(sn9c102_id_table[0]); for (i = 0; i < n-1; i++) if (le16_to_cpu(udev->descriptor.idVendor) == sn9c102_id_table[i].idVendor && @@ -2708,6 +2711,7 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) static struct usb_driver sn9c102_usb_driver = { + .owner = THIS_MODULE, .name = "sn9c102", .id_table = sn9c102_id_table, .probe = sn9c102_usb_probe, diff --git a/trunk/drivers/usb/media/stv680.c b/trunk/drivers/usb/media/stv680.c index 774038b352cd..0fd0fa9fec21 100644 --- a/trunk/drivers/usb/media/stv680.c +++ b/trunk/drivers/usb/media/stv680.c @@ -1477,6 +1477,7 @@ static void stv680_disconnect (struct usb_interface *intf) } static struct usb_driver stv680_driver = { + .owner = THIS_MODULE, .name = "stv680", .probe = stv680_probe, .disconnect = stv680_disconnect, diff --git a/trunk/drivers/usb/media/stv680.h b/trunk/drivers/usb/media/stv680.h index b0551cdb280b..445940612603 100644 --- a/trunk/drivers/usb/media/stv680.h +++ b/trunk/drivers/usb/media/stv680.h @@ -151,7 +151,7 @@ struct usb_stv { }; -static const unsigned char red[256] = { +static unsigned char red[256] = { 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, 44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, @@ -176,7 +176,7 @@ static const unsigned char red[256] = { 220, 220, 221, 221 }; -static const unsigned char green[256] = { +static unsigned char green[256] = { 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, @@ -201,7 +201,7 @@ static const unsigned char green[256] = { 245, 245, 246, 246 }; -static const unsigned char blue[256] = { +static unsigned char blue[256] = { 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, 55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, diff --git a/trunk/drivers/usb/media/usbvideo.c b/trunk/drivers/usb/media/usbvideo.c index 4bd113325ef9..24efb21969c6 100644 --- a/trunk/drivers/usb/media/usbvideo.c +++ b/trunk/drivers/usb/media/usbvideo.c @@ -725,7 +725,7 @@ int usbvideo_register( /* Allocate user_data separately because of kmalloc's limits */ if (num_extra > 0) { up->user_size = num_cams * num_extra; - up->user_data = kmalloc(up->user_size, GFP_KERNEL); + up->user_data = (char *) kmalloc(up->user_size, GFP_KERNEL); if (up->user_data == NULL) { err("%s: Failed to allocate user_data (%d. bytes)", __FUNCTION__, up->user_size); @@ -955,7 +955,7 @@ static struct file_operations usbvideo_fops = { .ioctl = usbvideo_v4l_ioctl, .llseek = no_llseek, }; -static const struct video_device usbvideo_template = { +static struct video_device usbvideo_template = { .owner = THIS_MODULE, .type = VID_TYPE_CAPTURE, .hardware = VID_HARDWARE_CPIA, diff --git a/trunk/drivers/usb/media/vicam.c b/trunk/drivers/usb/media/vicam.c index 1c73155c8d77..0bc0b1247a6b 100644 --- a/trunk/drivers/usb/media/vicam.c +++ b/trunk/drivers/usb/media/vicam.c @@ -1257,6 +1257,7 @@ static struct usb_device_id vicam_table[] = { MODULE_DEVICE_TABLE(usb, vicam_table); static struct usb_driver vicam_driver = { + .owner = THIS_MODULE, .name = "vicam", .probe = vicam_probe, .disconnect = vicam_disconnect, diff --git a/trunk/drivers/usb/media/w9968cf.c b/trunk/drivers/usb/media/w9968cf.c index 04d69339c054..67612c81cb9f 100644 --- a/trunk/drivers/usb/media/w9968cf.c +++ b/trunk/drivers/usb/media/w9968cf.c @@ -2958,7 +2958,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, }; #define V4L1_IOCTL(cmd) \ - ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \ + ((_IOC_NR((cmd)) < sizeof(v4l1_ioctls)/sizeof(char*)) ? \ v4l1_ioctls[_IOC_NR((cmd))] : "?") cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); @@ -3554,7 +3554,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) /* Allocate 2 bytes of memory for camera control USB transfers */ - if (!(cam->control_buffer = kmalloc(2, GFP_KERNEL))) { + if (!(cam->control_buffer = (u16*)kmalloc(2, GFP_KERNEL))) { DBG(1,"Couldn't allocate memory for camera control transfers") err = -ENOMEM; goto fail; @@ -3562,7 +3562,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) memset(cam->control_buffer, 0, 2); /* Allocate 8 bytes of memory for USB data transfers to the FSB */ - if (!(cam->data_buffer = kmalloc(8, GFP_KERNEL))) { + if (!(cam->data_buffer = (u16*)kmalloc(8, GFP_KERNEL))) { DBG(1, "Couldn't allocate memory for data " "transfers to the FSB") err = -ENOMEM; @@ -3668,6 +3668,7 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) static struct usb_driver w9968cf_usb_driver = { + .owner = THIS_MODULE, .name = "w9968cf", .id_table = winbond_id_table, .probe = w9968cf_usb_probe, diff --git a/trunk/drivers/usb/misc/auerswald.c b/trunk/drivers/usb/misc/auerswald.c index 449b2501acf3..b293db3c28c3 100644 --- a/trunk/drivers/usb/misc/auerswald.c +++ b/trunk/drivers/usb/misc/auerswald.c @@ -767,7 +767,7 @@ static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned memset (bep, 0, sizeof (auerbuf_t)); bep->list = bcp; INIT_LIST_HEAD (&bep->buff_list); - bep->bufp = kmalloc (bufsize, GFP_KERNEL); + bep->bufp = (char *) kmalloc (bufsize, GFP_KERNEL); if (!bep->bufp) goto bl_fail; bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL); @@ -1123,7 +1123,7 @@ static int auerswald_int_open (pauerswald_t cp) } } if (!cp->intbufp) { - cp->intbufp = kmalloc (irqsize, GFP_KERNEL); + cp->intbufp = (char *) kmalloc (irqsize, GFP_KERNEL); if (!cp->intbufp) { ret = -ENOMEM; goto intoend; @@ -2103,6 +2103,7 @@ MODULE_DEVICE_TABLE (usb, auerswald_ids); /* Standard usb driver struct */ static struct usb_driver auerswald_driver = { + .owner = THIS_MODULE, .name = "auerswald", .probe = auerswald_probe, .disconnect = auerswald_disconnect, diff --git a/trunk/drivers/usb/misc/cytherm.c b/trunk/drivers/usb/misc/cytherm.c index 6671317b495f..b33044d56a1e 100644 --- a/trunk/drivers/usb/misc/cytherm.c +++ b/trunk/drivers/usb/misc/cytherm.c @@ -50,6 +50,7 @@ static void cytherm_disconnect(struct usb_interface *interface); /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver cytherm_driver = { + .owner = THIS_MODULE, .name = "cytherm", .probe = cytherm_probe, .disconnect = cytherm_disconnect, diff --git a/trunk/drivers/usb/misc/emi26.c b/trunk/drivers/usb/misc/emi26.c index 3824df33094e..c8155209bf4b 100644 --- a/trunk/drivers/usb/misc/emi26.c +++ b/trunk/drivers/usb/misc/emi26.c @@ -227,6 +227,7 @@ static void emi26_disconnect(struct usb_interface *intf) } static struct usb_driver emi26_driver = { + .owner = THIS_MODULE, .name = "emi26 - firmware loader", .probe = emi26_probe, .disconnect = emi26_disconnect, diff --git a/trunk/drivers/usb/misc/emi62.c b/trunk/drivers/usb/misc/emi62.c index 52fea2e08db8..189986af2ac7 100644 --- a/trunk/drivers/usb/misc/emi62.c +++ b/trunk/drivers/usb/misc/emi62.c @@ -266,6 +266,7 @@ static void emi62_disconnect(struct usb_interface *intf) } static struct usb_driver emi62_driver = { + .owner = THIS_MODULE, .name = "emi62 - firmware loader", .probe = emi62_probe, .disconnect = emi62_disconnect, diff --git a/trunk/drivers/usb/misc/idmouse.c b/trunk/drivers/usb/misc/idmouse.c index d8cde1017985..1dc3e0f73014 100644 --- a/trunk/drivers/usb/misc/idmouse.c +++ b/trunk/drivers/usb/misc/idmouse.c @@ -114,6 +114,7 @@ static struct usb_class_driver idmouse_class = { /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver idmouse_driver = { + .owner = THIS_MODULE, .name = DRIVER_SHORT, .probe = idmouse_probe, .disconnect = idmouse_disconnect, diff --git a/trunk/drivers/usb/misc/ldusb.c b/trunk/drivers/usb/misc/ldusb.c index 981d8a5fbfd9..7e93ac96490f 100644 --- a/trunk/drivers/usb/misc/ldusb.c +++ b/trunk/drivers/usb/misc/ldusb.c @@ -763,6 +763,7 @@ static void ld_usb_disconnect(struct usb_interface *intf) /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver ld_usb_driver = { + .owner = THIS_MODULE, .name = "ldusb", .probe = ld_usb_probe, .disconnect = ld_usb_disconnect, diff --git a/trunk/drivers/usb/misc/legousbtower.c b/trunk/drivers/usb/misc/legousbtower.c index 1336745b8f55..2703e205bc8f 100644 --- a/trunk/drivers/usb/misc/legousbtower.c +++ b/trunk/drivers/usb/misc/legousbtower.c @@ -282,6 +282,7 @@ static struct usb_class_driver tower_class = { /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver tower_driver = { + .owner = THIS_MODULE, .name = "legousbtower", .probe = tower_probe, .disconnect = tower_disconnect, diff --git a/trunk/drivers/usb/misc/phidgetkit.c b/trunk/drivers/usb/misc/phidgetkit.c index 605a3c87e05c..067a81486921 100644 --- a/trunk/drivers/usb/misc/phidgetkit.c +++ b/trunk/drivers/usb/misc/phidgetkit.c @@ -555,6 +555,7 @@ static void interfacekit_disconnect(struct usb_interface *interface) } static struct usb_driver interfacekit_driver = { + .owner = THIS_MODULE, .name = "phidgetkit", .probe = interfacekit_probe, .disconnect = interfacekit_disconnect, diff --git a/trunk/drivers/usb/misc/phidgetservo.c b/trunk/drivers/usb/misc/phidgetservo.c index b3418d2bcc69..a30d4a6ee824 100644 --- a/trunk/drivers/usb/misc/phidgetservo.c +++ b/trunk/drivers/usb/misc/phidgetservo.c @@ -306,6 +306,7 @@ servo_disconnect(struct usb_interface *interface) } static struct usb_driver servo_driver = { + .owner = THIS_MODULE, .name = "phidgetservo", .probe = servo_probe, .disconnect = servo_disconnect, diff --git a/trunk/drivers/usb/misc/rio500.c b/trunk/drivers/usb/misc/rio500.c index 384fa3769805..9590dbac5d9a 100644 --- a/trunk/drivers/usb/misc/rio500.c +++ b/trunk/drivers/usb/misc/rio500.c @@ -465,14 +465,14 @@ static int probe_rio(struct usb_interface *intf, rio->rio_dev = dev; - if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) { + if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) { err("probe_rio: Not enough memory for the output buffer"); usb_deregister_dev(intf, &usb_rio_class); return -ENOMEM; } dbg("probe_rio: obuf address:%p", rio->obuf); - if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) { + if (!(rio->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) { err("probe_rio: Not enough memory for the input buffer"); usb_deregister_dev(intf, &usb_rio_class); kfree(rio->obuf); @@ -522,6 +522,7 @@ static struct usb_device_id rio_table [] = { MODULE_DEVICE_TABLE (usb, rio_table); static struct usb_driver rio_driver = { + .owner = THIS_MODULE, .name = "rio500", .probe = probe_rio, .disconnect = disconnect_rio, diff --git a/trunk/drivers/usb/misc/sisusbvga/sisusb.c b/trunk/drivers/usb/misc/sisusbvga/sisusb.c index 3260d595441f..41ef2b606751 100644 --- a/trunk/drivers/usb/misc/sisusbvga/sisusb.c +++ b/trunk/drivers/usb/misc/sisusbvga/sisusb.c @@ -863,6 +863,9 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, switch (length) { + case 0: + return ret; + case 1: if (userbuffer) { if (get_user(swap8, (u8 __user *)userbuffer)) @@ -1218,6 +1221,9 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, switch (length) { + case 0: + return ret; + case 1: ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, @@ -2437,8 +2443,8 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) u8 *tempbuf; u16 *tempbufb; size_t written; - static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."; - static const char bootlogo[] = "(o_ //\\ V_/_"; + static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."; + static char bootlogo[] = "(o_ //\\ V_/_"; /* sisusb->lock is down */ @@ -3483,6 +3489,7 @@ static struct usb_device_id sisusb_table [] = { MODULE_DEVICE_TABLE (usb, sisusb_table); static struct usb_driver sisusb_driver = { + .owner = THIS_MODULE, .name = "sisusb", .probe = sisusb_probe, .disconnect = sisusb_disconnect, diff --git a/trunk/drivers/usb/misc/usblcd.c b/trunk/drivers/usb/misc/usblcd.c index cc3dae3f34e0..85f3725334b0 100644 --- a/trunk/drivers/usb/misc/usblcd.c +++ b/trunk/drivers/usb/misc/usblcd.c @@ -371,6 +371,7 @@ static void lcd_disconnect(struct usb_interface *interface) } static struct usb_driver lcd_driver = { + .owner = THIS_MODULE, .name = "usblcd", .probe = lcd_probe, .disconnect = lcd_disconnect, diff --git a/trunk/drivers/usb/misc/usbled.c b/trunk/drivers/usb/misc/usbled.c index 877b081a3a6e..3c93921cb6b3 100644 --- a/trunk/drivers/usb/misc/usbled.c +++ b/trunk/drivers/usb/misc/usbled.c @@ -148,6 +148,7 @@ static void led_disconnect(struct usb_interface *interface) } static struct usb_driver led_driver = { + .owner = THIS_MODULE, .name = "usbled", .probe = led_probe, .disconnect = led_disconnect, diff --git a/trunk/drivers/usb/misc/usbtest.c b/trunk/drivers/usb/misc/usbtest.c index 84fa1728f052..605a2afe34ed 100644 --- a/trunk/drivers/usb/misc/usbtest.c +++ b/trunk/drivers/usb/misc/usbtest.c @@ -2134,6 +2134,7 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver usbtest_driver = { + .owner = THIS_MODULE, .name = "usbtest", .id_table = id_table, .probe = usbtest_probe, diff --git a/trunk/drivers/usb/misc/uss720.c b/trunk/drivers/usb/misc/uss720.c index 4081990b7d1a..1cabe7ed91f5 100644 --- a/trunk/drivers/usb/misc/uss720.c +++ b/trunk/drivers/usb/misc/uss720.c @@ -780,6 +780,7 @@ MODULE_DEVICE_TABLE (usb, uss720_table); static struct usb_driver uss720_driver = { + .owner = THIS_MODULE, .name = "uss720", .probe = uss720_probe, .disconnect = uss720_disconnect, diff --git a/trunk/drivers/usb/mon/mon_text.c b/trunk/drivers/usb/mon/mon_text.c index 611612146ae9..17d0190ef64e 100644 --- a/trunk/drivers/usb/mon/mon_text.c +++ b/trunk/drivers/usb/mon/mon_text.c @@ -97,12 +97,19 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, if (len >= DATA_MAX) len = DATA_MAX; - if (usb_pipein(pipe)) { - if (ev_type == 'S') - return '<'; - } else { - if (ev_type == 'C') - return '>'; + /* + * Bulk is easy to shortcut reliably. + * XXX Other pipe types need consideration. Currently, we overdo it + * and collect garbage for them: better more than less. + */ + if (usb_pipebulk(pipe) || usb_pipecontrol(pipe)) { + if (usb_pipein(pipe)) { + if (ev_type == 'S') + return '<'; + } else { + if (ev_type == 'C') + return '>'; + } } /* diff --git a/trunk/drivers/usb/net/asix.c b/trunk/drivers/usb/net/asix.c index 541181695040..542120ef1fd2 100644 --- a/trunk/drivers/usb/net/asix.c +++ b/trunk/drivers/usb/net/asix.c @@ -912,16 +912,13 @@ static const struct usb_device_id products [] = { // ASIX AX88772 10/100 USB_DEVICE (0x0b95, 0x7720), .driver_info = (unsigned long) &ax88772_info, -}, { - // Linksys USB200M Rev 2 - USB_DEVICE (0x13b1, 0x0018), - .driver_info = (unsigned long) &ax88772_info, }, { }, // END }; MODULE_DEVICE_TABLE(usb, products); static struct usb_driver asix_driver = { + .owner = THIS_MODULE, .name = "asix", .id_table = products, .probe = usbnet_probe, diff --git a/trunk/drivers/usb/net/catc.c b/trunk/drivers/usb/net/catc.c index be5f5e142dd0..37ef365a2472 100644 --- a/trunk/drivers/usb/net/catc.c +++ b/trunk/drivers/usb/net/catc.c @@ -934,6 +934,7 @@ static struct usb_device_id catc_id_table [] = { MODULE_DEVICE_TABLE(usb, catc_id_table); static struct usb_driver catc_driver = { + .owner = THIS_MODULE, .name = driver_name, .probe = catc_probe, .disconnect = catc_disconnect, diff --git a/trunk/drivers/usb/net/cdc_ether.c b/trunk/drivers/usb/net/cdc_ether.c index 63f1f3ba8e0b..c008c981862b 100644 --- a/trunk/drivers/usb/net/cdc_ether.c +++ b/trunk/drivers/usb/net/cdc_ether.c @@ -476,6 +476,7 @@ static const struct usb_device_id products [] = { MODULE_DEVICE_TABLE(usb, products); static struct usb_driver cdc_driver = { + .owner = THIS_MODULE, .name = "cdc_ether", .id_table = products, .probe = usbnet_probe, diff --git a/trunk/drivers/usb/net/cdc_subset.c b/trunk/drivers/usb/net/cdc_subset.c index ec801e8bb1bb..f05cfb83c82d 100644 --- a/trunk/drivers/usb/net/cdc_subset.c +++ b/trunk/drivers/usb/net/cdc_subset.c @@ -306,6 +306,7 @@ MODULE_DEVICE_TABLE(usb, products); /*-------------------------------------------------------------------------*/ static struct usb_driver cdc_subset_driver = { + .owner = THIS_MODULE, .name = "cdc_subset", .probe = usbnet_probe, .suspend = usbnet_suspend, diff --git a/trunk/drivers/usb/net/gl620a.c b/trunk/drivers/usb/net/gl620a.c index faf1e86be687..2455e9a85674 100644 --- a/trunk/drivers/usb/net/gl620a.c +++ b/trunk/drivers/usb/net/gl620a.c @@ -377,6 +377,7 @@ static const struct usb_device_id products [] = { MODULE_DEVICE_TABLE(usb, products); static struct usb_driver gl620a_driver = { + .owner = THIS_MODULE, .name = "gl620a", .id_table = products, .probe = usbnet_probe, diff --git a/trunk/drivers/usb/net/kaweth.c b/trunk/drivers/usb/net/kaweth.c index def3bb8e2290..b5776518020f 100644 --- a/trunk/drivers/usb/net/kaweth.c +++ b/trunk/drivers/usb/net/kaweth.c @@ -175,6 +175,7 @@ MODULE_DEVICE_TABLE (usb, usb_klsi_table); * kaweth_driver ****************************************************************/ static struct usb_driver kaweth_driver = { + .owner = THIS_MODULE, .name = driver_name, .probe = kaweth_probe, .disconnect = kaweth_disconnect, diff --git a/trunk/drivers/usb/net/net1080.c b/trunk/drivers/usb/net/net1080.c index 78e6a43b1087..b3799b1a2b0d 100644 --- a/trunk/drivers/usb/net/net1080.c +++ b/trunk/drivers/usb/net/net1080.c @@ -593,6 +593,7 @@ static const struct usb_device_id products [] = { MODULE_DEVICE_TABLE(usb, products); static struct usb_driver net1080_driver = { + .owner = THIS_MODULE, .name = "net1080", .id_table = products, .probe = usbnet_probe, diff --git a/trunk/drivers/usb/net/pegasus.c b/trunk/drivers/usb/net/pegasus.c index 156a2f1cb39a..683e3df5d607 100644 --- a/trunk/drivers/usb/net/pegasus.c +++ b/trunk/drivers/usb/net/pegasus.c @@ -45,7 +45,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.6.13 (2005/11/13)" +#define DRIVER_VERSION "v0.6.12 (2005/01/13)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" @@ -57,14 +57,12 @@ static const char driver_name[] = "pegasus"; static int loopback = 0; static int mii_mode = 0; -static char *devid=NULL; static struct usb_eth_dev usb_dev_id[] = { #define PEGASUS_DEV(pn, vid, pid, flags) \ {.name = pn, .vendor = vid, .device = pid, .private = flags}, #include "pegasus.h" #undef PEGASUS_DEV - {NULL, 0, 0, 0}, {NULL, 0, 0, 0} }; @@ -73,7 +71,6 @@ static struct usb_device_id pegasus_ids[] = { {.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid}, #include "pegasus.h" #undef PEGASUS_DEV - {}, {} }; @@ -82,10 +79,8 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(loopback, bool, 0); module_param(mii_mode, bool, 0); -module_param(devid, charp, 0); MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)"); MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0"); -MODULE_PARM_DESC(devid, "The format is: 'DEV_name:VendorID:DeviceID:Flags'"); /* use ethtool to change the level for any given device */ static int msg_level = -1; @@ -118,7 +113,7 @@ static void ctrl_callback(struct urb *urb, struct pt_regs *regs) break; default: if (netif_msg_drv(pegasus)) - dev_dbg(&pegasus->intf->dev, "%s, status %d\n", + dev_err(&pegasus->intf->dev, "%s, status %d\n", __FUNCTION__, urb->status); } pegasus->flags &= ~ETH_REGS_CHANGED; @@ -313,9 +308,9 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) __le16 regdi; int ret; - set_register(pegasus, PhyCtrl, 0); - set_registers(pegasus, PhyAddr, sizeof (data), data); - set_register(pegasus, PhyCtrl, (indx | PHY_READ)); + ret = set_register(pegasus, PhyCtrl, 0); + ret = set_registers(pegasus, PhyAddr, sizeof (data), data); + ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ)); for (i = 0; i < REG_TIMEOUT; i++) { ret = get_registers(pegasus, PhyCtrl, 1, data); if (data[0] & PHY_DONE) @@ -324,12 +319,12 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) if (i < REG_TIMEOUT) { ret = get_registers(pegasus, PhyData, 2, ®di); *regd = le16_to_cpu(regdi); - return ret; + return 1; } if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); - return ret; + return 0; } static int mdio_read(struct net_device *dev, int phy_id, int loc) @@ -349,20 +344,20 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) data[1] = (u8) regd; data[2] = (u8) (regd >> 8); - set_register(pegasus, PhyCtrl, 0); - set_registers(pegasus, PhyAddr, sizeof(data), data); - set_register(pegasus, PhyCtrl, (indx | PHY_WRITE)); + ret = set_register(pegasus, PhyCtrl, 0); + ret = set_registers(pegasus, PhyAddr, sizeof(data), data); + ret = set_register(pegasus, PhyCtrl, (indx | PHY_WRITE)); for (i = 0; i < REG_TIMEOUT; i++) { ret = get_registers(pegasus, PhyCtrl, 1, data); if (data[0] & PHY_DONE) break; } if (i < REG_TIMEOUT) - return ret; + return 0; if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); - return -ETIMEDOUT; + return 1; } static void mdio_write(struct net_device *dev, int phy_id, int loc, int val) @@ -379,9 +374,9 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) __le16 retdatai; int ret; - set_register(pegasus, EpromCtrl, 0); - set_register(pegasus, EpromOffset, index); - set_register(pegasus, EpromCtrl, EPROM_READ); + ret = set_register(pegasus, EpromCtrl, 0); + ret = set_register(pegasus, EpromOffset, index); + ret = set_register(pegasus, EpromCtrl, EPROM_READ); for (i = 0; i < REG_TIMEOUT; i++) { ret = get_registers(pegasus, EpromCtrl, 1, &tmp); @@ -391,12 +386,12 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) if (i < REG_TIMEOUT) { ret = get_registers(pegasus, EpromData, 2, &retdatai); *retdata = le16_to_cpu(retdatai); - return ret; + return 0; } if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); - return -ETIMEDOUT; + return -1; } #ifdef PEGASUS_WRITE_EEPROM @@ -405,8 +400,8 @@ static inline void enable_eprom_write(pegasus_t * pegasus) __u8 tmp; int ret; - get_registers(pegasus, EthCtrl2, 1, &tmp); - set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE); + ret = get_registers(pegasus, EthCtrl2, 1, &tmp); + ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE); } static inline void disable_eprom_write(pegasus_t * pegasus) @@ -414,9 +409,9 @@ static inline void disable_eprom_write(pegasus_t * pegasus) __u8 tmp; int ret; - get_registers(pegasus, EthCtrl2, 1, &tmp); - set_register(pegasus, EpromCtrl, 0); - set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE); + ret = get_registers(pegasus, EthCtrl2, 1, &tmp); + ret = set_register(pegasus, EpromCtrl, 0); + ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE); } static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) @@ -425,11 +420,11 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE }; int ret; - set_registers(pegasus, EpromOffset, 4, d); + ret = set_registers(pegasus, EpromOffset, 4, d); enable_eprom_write(pegasus); - set_register(pegasus, EpromOffset, index); - set_registers(pegasus, EpromData, 2, &data); - set_register(pegasus, EpromCtrl, EPROM_WRITE); + ret = set_register(pegasus, EpromOffset, index); + ret = set_registers(pegasus, EpromData, 2, &data); + ret = set_register(pegasus, EpromCtrl, EPROM_WRITE); for (i = 0; i < REG_TIMEOUT; i++) { ret = get_registers(pegasus, EpromCtrl, 1, &tmp); @@ -438,10 +433,10 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) } disable_eprom_write(pegasus); if (i < REG_TIMEOUT) - return ret; + return 0; if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); - return -ETIMEDOUT; + return -1; } #endif /* PEGASUS_WRITE_EEPROM */ @@ -459,9 +454,10 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id) static void set_ethernet_addr(pegasus_t * pegasus) { __u8 node_id[6]; + int ret; get_node_id(pegasus, node_id); - set_registers(pegasus, EthID, sizeof (node_id), node_id); + ret = set_registers(pegasus, EthID, sizeof (node_id), node_id); memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id)); } @@ -469,29 +465,30 @@ static inline int reset_mac(pegasus_t * pegasus) { __u8 data = 0x8; int i; + int ret; - set_register(pegasus, EthCtrl1, data); + ret = set_register(pegasus, EthCtrl1, data); for (i = 0; i < REG_TIMEOUT; i++) { - get_registers(pegasus, EthCtrl1, 1, &data); + ret = get_registers(pegasus, EthCtrl1, 1, &data); if (~data & 0x08) { if (loopback & 1) break; if (mii_mode && (pegasus->features & HAS_HOME_PNA)) - set_register(pegasus, Gpio1, 0x34); + ret = set_register(pegasus, Gpio1, 0x34); else - set_register(pegasus, Gpio1, 0x26); - set_register(pegasus, Gpio0, pegasus->features); - set_register(pegasus, Gpio0, DEFAULT_GPIO_SET); + ret = set_register(pegasus, Gpio1, 0x26); + ret = set_register(pegasus, Gpio0, pegasus->features); + ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET); break; } } if (i == REG_TIMEOUT) - return -ETIMEDOUT; + return 1; if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) { - set_register(pegasus, Gpio0, 0x24); - set_register(pegasus, Gpio0, 0x26); + ret = set_register(pegasus, Gpio0, 0x24); + ret = set_register(pegasus, Gpio0, 0x26); } if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) { __u16 auxmode; @@ -530,7 +527,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) write_mii_word(pegasus, 0, 0x1b, auxmode | 4); } - return ret; + return 0; } static void fill_skb_pool(pegasus_t * pegasus) @@ -884,8 +881,9 @@ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev) static inline void disable_net_traffic(pegasus_t * pegasus) { int tmp = 0; + int ret; - set_registers(pegasus, EthCtrl0, 2, &tmp); + ret = set_registers(pegasus, EthCtrl0, 2, &tmp); } static inline void get_interrupt_interval(pegasus_t * pegasus) @@ -1208,17 +1206,18 @@ static __u8 mii_phy_probe(pegasus_t * pegasus) static inline void setup_pegasus_II(pegasus_t * pegasus) { __u8 data = 0xa5; + int ret; - set_register(pegasus, Reg1d, 0); - set_register(pegasus, Reg7b, 1); + ret = set_register(pegasus, Reg1d, 0); + ret = set_register(pegasus, Reg7b, 1); mdelay(100); if ((pegasus->features & HAS_HOME_PNA) && mii_mode) - set_register(pegasus, Reg7b, 0); + ret = set_register(pegasus, Reg7b, 0); else - set_register(pegasus, Reg7b, 2); + ret = set_register(pegasus, Reg7b, 2); - set_register(pegasus, 0x83, data); - get_registers(pegasus, 0x83, 1, &data); + ret = set_register(pegasus, 0x83, data); + ret = get_registers(pegasus, 0x83, 1, &data); if (data == 0xa5) { pegasus->chip = 0x8513; @@ -1226,14 +1225,14 @@ static inline void setup_pegasus_II(pegasus_t * pegasus) pegasus->chip = 0; } - set_register(pegasus, 0x80, 0xc0); - set_register(pegasus, 0x83, 0xff); - set_register(pegasus, 0x84, 0x01); + ret = set_register(pegasus, 0x80, 0xc0); + ret = set_register(pegasus, 0x83, 0xff); + ret = set_register(pegasus, 0x84, 0x01); if (pegasus->features & HAS_HOME_PNA && mii_mode) - set_register(pegasus, Reg81, 6); + ret = set_register(pegasus, Reg81, 6); else - set_register(pegasus, Reg81, 2); + ret = set_register(pegasus, Reg81, 2); } @@ -1415,42 +1414,9 @@ static struct usb_driver pegasus_driver = { .resume = pegasus_resume, }; -static void parse_id(char *id) -{ - unsigned int vendor_id=0, device_id=0, flags=0, i=0; - char *token, *name=NULL; - - if ((token = strsep(&id, ":")) != NULL) - name = token; - /* name now points to a null terminated string*/ - if ((token = strsep(&id, ":")) != NULL) - vendor_id = simple_strtoul(token, NULL, 16); - if ((token = strsep(&id, ":")) != NULL) - device_id = simple_strtoul(token, NULL, 16); - flags = simple_strtoul(id, NULL, 16); - pr_info("%s: new device %s, vendor ID 0x%04x, device ID 0x%04x, flags: 0x%x\n", - driver_name, name, vendor_id, device_id, flags); - - if (vendor_id > 0x10000 || vendor_id == 0) - return; - if (device_id > 0x10000 || device_id == 0) - return; - - for (i=0; usb_dev_id[i].name; i++); - usb_dev_id[i].name = name; - usb_dev_id[i].vendor = vendor_id; - usb_dev_id[i].device = device_id; - usb_dev_id[i].private = flags; - pegasus_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE; - pegasus_ids[i].idVendor = vendor_id; - pegasus_ids[i].idProduct = device_id; -} - static int __init pegasus_init(void) { pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION); - if (devid) - parse_id(devid); pegasus_workqueue = create_singlethread_workqueue("pegasus"); if (!pegasus_workqueue) return -ENOMEM; diff --git a/trunk/drivers/usb/net/plusb.c b/trunk/drivers/usb/net/plusb.c index 4fe863389cb7..89856aa0e3b8 100644 --- a/trunk/drivers/usb/net/plusb.c +++ b/trunk/drivers/usb/net/plusb.c @@ -127,6 +127,7 @@ static const struct usb_device_id products [] = { MODULE_DEVICE_TABLE(usb, products); static struct usb_driver plusb_driver = { + .owner = THIS_MODULE, .name = "plusb", .id_table = products, .probe = usbnet_probe, diff --git a/trunk/drivers/usb/net/rndis_host.c b/trunk/drivers/usb/net/rndis_host.c index 49991ac1bf3b..c0ecbab6f6ba 100644 --- a/trunk/drivers/usb/net/rndis_host.c +++ b/trunk/drivers/usb/net/rndis_host.c @@ -586,6 +586,7 @@ static const struct usb_device_id products [] = { MODULE_DEVICE_TABLE(usb, products); static struct usb_driver rndis_driver = { + .owner = THIS_MODULE, .name = "rndis_host", .id_table = products, .probe = usbnet_probe, diff --git a/trunk/drivers/usb/net/rtl8150.c b/trunk/drivers/usb/net/rtl8150.c index 8ca52be23976..787dd3591d6a 100644 --- a/trunk/drivers/usb/net/rtl8150.c +++ b/trunk/drivers/usb/net/rtl8150.c @@ -177,6 +177,7 @@ static int rtl8150_probe(struct usb_interface *intf, static const char driver_name [] = "rtl8150"; static struct usb_driver rtl8150_driver = { + .owner = THIS_MODULE, .name = driver_name, .probe = rtl8150_probe, .disconnect = rtl8150_disconnect, diff --git a/trunk/drivers/usb/net/zaurus.c b/trunk/drivers/usb/net/zaurus.c index 9c5ab251370c..680d13957af4 100644 --- a/trunk/drivers/usb/net/zaurus.c +++ b/trunk/drivers/usb/net/zaurus.c @@ -357,6 +357,7 @@ static const struct usb_device_id products [] = { MODULE_DEVICE_TABLE(usb, products); static struct usb_driver zaurus_driver = { + .owner = THIS_MODULE, .name = "zaurus", .id_table = products, .probe = usbnet_probe, diff --git a/trunk/drivers/usb/net/zd1201.c b/trunk/drivers/usb/net/zd1201.c index f3a8e2807c3b..2f52261c7cc1 100644 --- a/trunk/drivers/usb/net/zd1201.c +++ b/trunk/drivers/usb/net/zd1201.c @@ -1722,7 +1722,7 @@ static const struct iw_priv_args zd1201_private_args[] = { IW_PRIV_TYPE_NONE, "sethostauth" }, { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" }, - { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, + { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, "authstation" }, { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, "setmaxassoc" }, @@ -1731,9 +1731,9 @@ static const struct iw_priv_args zd1201_private_args[] = { }; static const struct iw_handler_def zd1201_iw_handlers = { - .num_standard = ARRAY_SIZE(zd1201_iw_handler), - .num_private = ARRAY_SIZE(zd1201_private_handler), - .num_private_args = ARRAY_SIZE(zd1201_private_args), + .num_standard = sizeof(zd1201_iw_handler)/sizeof(iw_handler), + .num_private = sizeof(zd1201_private_handler)/sizeof(iw_handler), + .num_private_args = sizeof(zd1201_private_args)/sizeof(struct iw_priv_args), .standard = (iw_handler *)zd1201_iw_handler, .private = (iw_handler *)zd1201_private_handler, .private_args = (struct iw_priv_args *) zd1201_private_args, @@ -1829,8 +1829,6 @@ static int zd1201_probe(struct usb_interface *interface, if (err) goto err_net; - SET_NETDEV_DEV(zd->dev, &usb->dev); - err = register_netdev(zd->dev); if (err) goto err_net; @@ -1925,6 +1923,7 @@ static int zd1201_resume(struct usb_interface *interface) #endif static struct usb_driver zd1201_usb = { + .owner = THIS_MODULE, .name = "zd1201", .probe = zd1201_probe, .disconnect = zd1201_disconnect, diff --git a/trunk/drivers/usb/serial/airprime.c b/trunk/drivers/usb/serial/airprime.c index dbf1f063098c..1f29d8837327 100644 --- a/trunk/drivers/usb/serial/airprime.c +++ b/trunk/drivers/usb/serial/airprime.c @@ -23,11 +23,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver airprime_driver = { + .owner = THIS_MODULE, .name = "airprime", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver airprime_device = { diff --git a/trunk/drivers/usb/serial/anydata.c b/trunk/drivers/usb/serial/anydata.c index 343f6f228220..18022a74a3dc 100644 --- a/trunk/drivers/usb/serial/anydata.c +++ b/trunk/drivers/usb/serial/anydata.c @@ -27,11 +27,11 @@ static int buffer_size; static int debug; static struct usb_driver anydata_driver = { + .owner = THIS_MODULE, .name = "anydata", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static int anydata_open(struct usb_serial_port *port, struct file *filp) diff --git a/trunk/drivers/usb/serial/belkin_sa.c b/trunk/drivers/usb/serial/belkin_sa.c index 4144777ea18b..84bc0ee4f061 100644 --- a/trunk/drivers/usb/serial/belkin_sa.c +++ b/trunk/drivers/usb/serial/belkin_sa.c @@ -113,11 +113,11 @@ static struct usb_device_id id_table_combined [] = { MODULE_DEVICE_TABLE (usb, id_table_combined); static struct usb_driver belkin_driver = { + .owner = THIS_MODULE, .name = "belkin", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* All of the device info needed for the serial converters */ diff --git a/trunk/drivers/usb/serial/cp2101.c b/trunk/drivers/usb/serial/cp2101.c index da46b351e188..c9787001cf2a 100644 --- a/trunk/drivers/usb/serial/cp2101.c +++ b/trunk/drivers/usb/serial/cp2101.c @@ -67,11 +67,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver cp2101_driver = { + .owner = THIS_MODULE, .name = "cp2101", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver cp2101_device = { diff --git a/trunk/drivers/usb/serial/cyberjack.c b/trunk/drivers/usb/serial/cyberjack.c index 6d18d4eaba35..e581e4ae8483 100644 --- a/trunk/drivers/usb/serial/cyberjack.c +++ b/trunk/drivers/usb/serial/cyberjack.c @@ -76,11 +76,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver cyberjack_driver = { + .owner = THIS_MODULE, .name = "cyberjack", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver cyberjack_device = { diff --git a/trunk/drivers/usb/serial/cypress_m8.c b/trunk/drivers/usb/serial/cypress_m8.c index af18355e94cc..af9290ed257b 100644 --- a/trunk/drivers/usb/serial/cypress_m8.c +++ b/trunk/drivers/usb/serial/cypress_m8.c @@ -112,7 +112,6 @@ static struct usb_driver cypress_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; struct cypress_private { diff --git a/trunk/drivers/usb/serial/digi_acceleport.c b/trunk/drivers/usb/serial/digi_acceleport.c index 8fc414bd5b24..dc74644a603d 100644 --- a/trunk/drivers/usb/serial/digi_acceleport.c +++ b/trunk/drivers/usb/serial/digi_acceleport.c @@ -493,11 +493,11 @@ static struct usb_device_id id_table_4 [] = { MODULE_DEVICE_TABLE (usb, id_table_combined); static struct usb_driver digi_driver = { + .owner = THIS_MODULE, .name = "digi_acceleport", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; diff --git a/trunk/drivers/usb/serial/empeg.c b/trunk/drivers/usb/serial/empeg.c index 79a766e9ca23..0b0546dcc7b9 100644 --- a/trunk/drivers/usb/serial/empeg.c +++ b/trunk/drivers/usb/serial/empeg.c @@ -105,11 +105,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver empeg_driver = { + .owner = THIS_MODULE, .name = "empeg", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver empeg_device = { diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index eb863b3f2d79..06e04b442ff1 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -471,15 +471,12 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) }, { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) }, { USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) }, { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) }, - { USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -491,10 +488,9 @@ static struct usb_driver ftdi_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; -static const char *ftdi_chip_name[] = { +static char *ftdi_chip_name[] = { [SIO] = "SIO", /* the serial part of FT8U100AX */ [FT8U232AM] = "FT8U232AM", [FT232BM] = "FT232BM", diff --git a/trunk/drivers/usb/serial/ftdi_sio.h b/trunk/drivers/usb/serial/ftdi_sio.h index f380f9eaff71..773ea3eca086 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.h +++ b/trunk/drivers/usb/serial/ftdi_sio.h @@ -342,13 +342,6 @@ #define XSENS_CONVERTER_6_PID 0xD38E #define XSENS_CONVERTER_7_PID 0xD38F -/* - * Teratronik product ids. - * Submitted by O. Wölfelschneider. - */ -#define FTDI_TERATRONIK_VCP_PID 0xEC88 /* Teratronik device (preferring VCP driver on windows) */ -#define FTDI_TERATRONIK_D2XX_PID 0xEC89 /* Teratronik device (preferring D2XX driver on windows) */ - /* * Evolution Robotics products (http://www.evolution.com/). * Submitted by Shawn M. Lavelle. @@ -359,12 +352,6 @@ /* Pyramid Computer GmbH */ #define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ -/* - * Posiflex inc retail equipment (http://www.posiflex.com.tw) - */ -#define POSIFLEX_VID 0x0d3a /* Vendor ID */ -#define POSIFLEX_PP7000_PID 0x0300 /* PP-7000II thermal printer */ - /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff --git a/trunk/drivers/usb/serial/garmin_gps.c b/trunk/drivers/usb/serial/garmin_gps.c index 452efce72714..35820bda7ae1 100644 --- a/trunk/drivers/usb/serial/garmin_gps.c +++ b/trunk/drivers/usb/serial/garmin_gps.c @@ -222,11 +222,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver garmin_driver = { + .owner = THIS_MODULE, .name = "garmin_gps", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; diff --git a/trunk/drivers/usb/serial/generic.c b/trunk/drivers/usb/serial/generic.c index 4ddac620fc0c..53a47c31cd0e 100644 --- a/trunk/drivers/usb/serial/generic.c +++ b/trunk/drivers/usb/serial/generic.c @@ -68,11 +68,11 @@ static int generic_probe(struct usb_interface *interface, } static struct usb_driver generic_driver = { + .owner = THIS_MODULE, .name = "usbserial_generic", .probe = generic_probe, .disconnect = usb_serial_disconnect, .id_table = generic_serial_ids, - .no_dynamic_id = 1, }; #endif diff --git a/trunk/drivers/usb/serial/hp4x.c b/trunk/drivers/usb/serial/hp4x.c index e9719da2aca1..8eadfb705601 100644 --- a/trunk/drivers/usb/serial/hp4x.c +++ b/trunk/drivers/usb/serial/hp4x.c @@ -37,11 +37,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver hp49gp_driver = { + .owner = THIS_MODULE, .name = "hp4X", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver hp49gp_device = { diff --git a/trunk/drivers/usb/serial/io_edgeport.c b/trunk/drivers/usb/serial/io_edgeport.c index faedbeb6ba49..dc4c498bd1ed 100644 --- a/trunk/drivers/usb/serial/io_edgeport.c +++ b/trunk/drivers/usb/serial/io_edgeport.c @@ -184,7 +184,7 @@ struct divisor_table_entry { // These assume a 3.6864MHz crystal, the standard /16, and // MCR.7 = 0. // -static const struct divisor_table_entry divisor_table[] = { +static struct divisor_table_entry divisor_table[] = { { 50, 4608}, { 75, 3072}, { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */ @@ -242,11 +242,11 @@ static void edge_shutdown (struct usb_serial *serial); #include "io_tables.h" /* all of the devices that this driver supports */ static struct usb_driver io_driver = { + .owner = THIS_MODULE, .name = "io_edgeport", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* function prototypes for all of our local functions */ @@ -2353,7 +2353,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor) dbg("%s - %d", __FUNCTION__, baudrate); - for (i = 0; i < ARRAY_SIZE(divisor_table); i++) { + for (i = 0; i < NUM_ENTRIES(divisor_table); i++) { if ( divisor_table[i].BaudRate == baudrate ) { *divisor = divisor_table[i].Divisor; return 0; diff --git a/trunk/drivers/usb/serial/io_edgeport.h b/trunk/drivers/usb/serial/io_edgeport.h index 123fa8a904e6..5112d7aac055 100644 --- a/trunk/drivers/usb/serial/io_edgeport.h +++ b/trunk/drivers/usb/serial/io_edgeport.h @@ -31,6 +31,9 @@ #ifndef HIGH8 #define HIGH8(a) ((unsigned char)((a & 0xff00) >> 8)) #endif +#ifndef NUM_ENTRIES + #define NUM_ENTRIES(x) (sizeof(x)/sizeof((x)[0])) +#endif #ifndef __KERNEL__ #define __KERNEL__ diff --git a/trunk/drivers/usb/serial/io_fw_boot2.h b/trunk/drivers/usb/serial/io_fw_boot2.h index e3463de99de4..c7c3a3c305fe 100644 --- a/trunk/drivers/usb/serial/io_fw_boot2.h +++ b/trunk/drivers/usb/serial/io_fw_boot2.h @@ -537,7 +537,7 @@ static unsigned char IMAGE_ARRAY_NAME[] = { }; -static const struct edge_firmware_version_info IMAGE_VERSION_NAME = { +static struct edge_firmware_version_info IMAGE_VERSION_NAME = { 2, 0, 3 }; // Major, Minor, Build #undef IMAGE_VERSION_NAME diff --git a/trunk/drivers/usb/serial/io_ti.c b/trunk/drivers/usb/serial/io_ti.c index 2edf9cabad20..832b6d6734c0 100644 --- a/trunk/drivers/usb/serial/io_ti.c +++ b/trunk/drivers/usb/serial/io_ti.c @@ -216,11 +216,11 @@ static struct usb_device_id id_table_combined [] = { MODULE_DEVICE_TABLE (usb, id_table_combined); static struct usb_driver io_driver = { + .owner = THIS_MODULE, .name = "io_ti", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; @@ -2843,7 +2843,7 @@ static struct edge_buf *edge_buf_alloc(unsigned int size) * Free the buffer and all associated memory. */ -static void edge_buf_free(struct edge_buf *eb) +void edge_buf_free(struct edge_buf *eb) { if (eb) { kfree(eb->buf_buf); diff --git a/trunk/drivers/usb/serial/ipaq.c b/trunk/drivers/usb/serial/ipaq.c index 06d07cea0b70..d5d066488100 100644 --- a/trunk/drivers/usb/serial/ipaq.c +++ b/trunk/drivers/usb/serial/ipaq.c @@ -542,11 +542,11 @@ static struct usb_device_id ipaq_id_table [] = { MODULE_DEVICE_TABLE (usb, ipaq_id_table); static struct usb_driver ipaq_driver = { + .owner = THIS_MODULE, .name = "ipaq", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = ipaq_id_table, - .no_dynamic_id = 1, }; diff --git a/trunk/drivers/usb/serial/ipw.c b/trunk/drivers/usb/serial/ipw.c index 2dd191f5fe76..7744b8148bc5 100644 --- a/trunk/drivers/usb/serial/ipw.c +++ b/trunk/drivers/usb/serial/ipw.c @@ -152,11 +152,11 @@ static struct usb_device_id usb_ipw_ids[] = { MODULE_DEVICE_TABLE(usb, usb_ipw_ids); static struct usb_driver usb_ipw_driver = { + .owner = THIS_MODULE, .name = "ipwtty", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = usb_ipw_ids, - .no_dynamic_id = 1, }; static int debug; diff --git a/trunk/drivers/usb/serial/ir-usb.c b/trunk/drivers/usb/serial/ir-usb.c index a59010421444..19f329e9bdcf 100644 --- a/trunk/drivers/usb/serial/ir-usb.c +++ b/trunk/drivers/usb/serial/ir-usb.c @@ -125,11 +125,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver ir_driver = { + .owner = THIS_MODULE, .name = "ir-usb", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; diff --git a/trunk/drivers/usb/serial/keyspan.h b/trunk/drivers/usb/serial/keyspan.h index 7472ed6bf626..5cfc13b5e56f 100644 --- a/trunk/drivers/usb/serial/keyspan.h +++ b/trunk/drivers/usb/serial/keyspan.h @@ -520,11 +520,11 @@ static struct usb_device_id keyspan_ids_combined[] = { MODULE_DEVICE_TABLE(usb, keyspan_ids_combined); static struct usb_driver keyspan_driver = { + .owner = THIS_MODULE, .name = "keyspan", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = keyspan_ids_combined, - .no_dynamic_id = 1, }; /* usb_device_id table for the pre-firmware download keyspan devices */ diff --git a/trunk/drivers/usb/serial/keyspan_pda.c b/trunk/drivers/usb/serial/keyspan_pda.c index b0441c35f98f..cd4f48bd83b6 100644 --- a/trunk/drivers/usb/serial/keyspan_pda.c +++ b/trunk/drivers/usb/serial/keyspan_pda.c @@ -150,11 +150,11 @@ static struct usb_device_id id_table_combined [] = { MODULE_DEVICE_TABLE (usb, id_table_combined); static struct usb_driver keyspan_pda_driver = { + .owner = THIS_MODULE, .name = "keyspan_pda", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static struct usb_device_id id_table_std [] = { diff --git a/trunk/drivers/usb/serial/kl5kusb105.c b/trunk/drivers/usb/serial/kl5kusb105.c index 4e2f7dfb58b2..a8951c0fd020 100644 --- a/trunk/drivers/usb/serial/kl5kusb105.c +++ b/trunk/drivers/usb/serial/kl5kusb105.c @@ -116,11 +116,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver kl5kusb105d_driver = { + .owner = THIS_MODULE, .name = "kl5kusb105d", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver kl5kusb105d_device = { diff --git a/trunk/drivers/usb/serial/kobil_sct.c b/trunk/drivers/usb/serial/kobil_sct.c index d9c21e275130..9456dd9dd136 100644 --- a/trunk/drivers/usb/serial/kobil_sct.c +++ b/trunk/drivers/usb/serial/kobil_sct.c @@ -97,11 +97,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver kobil_driver = { + .owner = THIS_MODULE, .name = "kobil", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; diff --git a/trunk/drivers/usb/serial/mct_u232.c b/trunk/drivers/usb/serial/mct_u232.c index b6d6cab9c859..ca5dbadb9b7e 100644 --- a/trunk/drivers/usb/serial/mct_u232.c +++ b/trunk/drivers/usb/serial/mct_u232.c @@ -125,11 +125,11 @@ static struct usb_device_id id_table_combined [] = { MODULE_DEVICE_TABLE (usb, id_table_combined); static struct usb_driver mct_u232_driver = { + .owner = THIS_MODULE, .name = "mct_u232", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver mct_u232_device = { diff --git a/trunk/drivers/usb/serial/omninet.c b/trunk/drivers/usb/serial/omninet.c index 762d8ff9a1e4..3caf97072ac0 100644 --- a/trunk/drivers/usb/serial/omninet.c +++ b/trunk/drivers/usb/serial/omninet.c @@ -80,11 +80,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver omninet_driver = { + .owner = THIS_MODULE, .name = "omninet", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index 3fd2405304fd..7716000045b7 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -95,11 +95,11 @@ static struct usb_device_id option_ids[] = { MODULE_DEVICE_TABLE(usb, option_ids); static struct usb_driver option_driver = { + .owner = THIS_MODULE, .name = "option", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = option_ids, - .no_dynamic_id = 1, }; /* The card has three separate interfaces, wich the serial driver diff --git a/trunk/drivers/usb/serial/pl2303.c b/trunk/drivers/usb/serial/pl2303.c index f03721056190..41a45a5025b2 100644 --- a/trunk/drivers/usb/serial/pl2303.c +++ b/trunk/drivers/usb/serial/pl2303.c @@ -82,11 +82,11 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver pl2303_driver = { + .owner = THIS_MODULE, .name = "pl2303", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; #define SET_LINE_REQUEST_TYPE 0x21 @@ -810,7 +810,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port, struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; u8 status_idx = UART_STATE; - u8 length = UART_STATE + 1; + u8 length = UART_STATE; if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) && (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65 || diff --git a/trunk/drivers/usb/serial/safe_serial.c b/trunk/drivers/usb/serial/safe_serial.c index f0215f850d2d..c22bdc0c4dfd 100644 --- a/trunk/drivers/usb/serial/safe_serial.c +++ b/trunk/drivers/usb/serial/safe_serial.c @@ -160,14 +160,14 @@ static struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver safe_driver = { + .owner = THIS_MODULE, .name = "safe_serial", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; -static const __u16 crc10_table[256] = { +static __u16 crc10_table[256] = { 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe, 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf, 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c, @@ -425,7 +425,7 @@ static int __init safe_init (void) if (vendor || product) { info ("vendor: %x product: %x\n", vendor, product); - for (i = 0; i < ARRAY_SIZE(id_table); i++) { + for (i = 0; i < (sizeof (id_table) / sizeof (struct usb_device_id)); i++) { if (!id_table[i].idVendor && !id_table[i].idProduct) { id_table[i].idVendor = vendor; id_table[i].idProduct = product; diff --git a/trunk/drivers/usb/serial/ti_usb_3410_5052.c b/trunk/drivers/usb/serial/ti_usb_3410_5052.c index abb830cb77bd..205dbf7201da 100644 --- a/trunk/drivers/usb/serial/ti_usb_3410_5052.c +++ b/trunk/drivers/usb/serial/ti_usb_3410_5052.c @@ -248,11 +248,11 @@ static struct usb_device_id ti_id_table_combined[] = { }; static struct usb_driver ti_usb_driver = { + .owner = THIS_MODULE, .name = "ti_usb_3410_5052", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = ti_id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver ti_1port_device = { @@ -351,14 +351,17 @@ static int __init ti_init(void) int i,j; int ret; + /* insert extra vendor and product ids */ - j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1; + j = sizeof(ti_id_table_3410)/sizeof(struct usb_device_id) + - TI_EXTRA_VID_PID_COUNT - 1; for (i=0; i #include #include -#include #include #include "usb-serial.h" #include "pl2303.h" @@ -43,10 +42,10 @@ /* Driver structure we register with the USB core */ static struct usb_driver usb_serial_driver = { + .owner = THIS_MODULE, .name = "usbserial", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, - .no_dynamic_id = 1, }; /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead @@ -189,11 +188,6 @@ static int serial_open (struct tty_struct *tty, struct file * filp) portNumber = tty->index - serial->minor; port = serial->port[portNumber]; - if (!port) - return -ENODEV; - - if (down_interruptible(&port->sem)) - return -ERESTARTSYS; ++port->open_count; @@ -219,7 +213,6 @@ static int serial_open (struct tty_struct *tty, struct file * filp) goto bailout_module_put; } - up(&port->sem); return 0; bailout_module_put: @@ -227,7 +220,6 @@ static int serial_open (struct tty_struct *tty, struct file * filp) bailout_kref_put: kref_put(&serial->kref, destroy_serial); port->open_count = 0; - up(&port->sem); return retval; } @@ -240,10 +232,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp) dbg("%s - port %d", __FUNCTION__, port->number); - down(&port->sem); - if (port->open_count == 0) - goto out; + return; --port->open_count; if (port->open_count == 0) { @@ -261,9 +251,6 @@ static void serial_close(struct tty_struct *tty, struct file * filp) } kref_put(&port->serial->kref, destroy_serial); - -out: - up(&port->sem); } static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) @@ -271,9 +258,6 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int struct usb_serial_port *port = tty->driver_data; int retval = -EINVAL; - if (!port) - goto exit; - dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); if (!port->open_count) { @@ -293,9 +277,6 @@ static int serial_write_room (struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; int retval = -EINVAL; - if (!port) - goto exit; - dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -315,9 +296,6 @@ static int serial_chars_in_buffer (struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; int retval = -EINVAL; - if (!port) - goto exit; - dbg("%s = port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -336,9 +314,6 @@ static void serial_throttle (struct tty_struct * tty) { struct usb_serial_port *port = tty->driver_data; - if (!port) - return; - dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -355,9 +330,6 @@ static void serial_unthrottle (struct tty_struct * tty) { struct usb_serial_port *port = tty->driver_data; - if (!port) - return; - dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -375,9 +347,6 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in struct usb_serial_port *port = tty->driver_data; int retval = -ENODEV; - if (!port) - goto exit; - dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); if (!port->open_count) { @@ -399,9 +368,6 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old) { struct usb_serial_port *port = tty->driver_data; - if (!port) - return; - dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -418,9 +384,6 @@ static void serial_break (struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; - if (!port) - return; - dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -482,9 +445,6 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file) { struct usb_serial_port *port = tty->driver_data; - if (!port) - goto exit; - dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -504,9 +464,6 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file, { struct usb_serial_port *port = tty->driver_data; - if (!port) - goto exit; - dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -785,7 +742,6 @@ int usb_serial_probe(struct usb_interface *interface, port->number = i + serial->minor; port->serial = serial; spin_lock_init(&port->lock); - sema_init(&port->sem, 1); INIT_WORK(&port->work, usb_serial_port_softint, port); serial->port[i] = port; } diff --git a/trunk/drivers/usb/serial/usb-serial.h b/trunk/drivers/usb/serial/usb-serial.h index d7d27c3385b3..238a5a871ed6 100644 --- a/trunk/drivers/usb/serial/usb-serial.h +++ b/trunk/drivers/usb/serial/usb-serial.h @@ -16,7 +16,6 @@ #include #include -#include #define SERIAL_TTY_MAJOR 188 /* Nice legal number now */ #define SERIAL_TTY_MINORS 255 /* loads of devices :) */ @@ -31,8 +30,6 @@ * @serial: pointer back to the struct usb_serial owner of this port. * @tty: pointer to the corresponding tty for this port. * @lock: spinlock to grab when updating portions of this structure. - * @sem: semaphore used to synchronize serial_open() and serial_close() - * access for this port. * @number: the number of the port (the minor number). * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. @@ -63,7 +60,6 @@ struct usb_serial_port { struct usb_serial * serial; struct tty_struct * tty; spinlock_t lock; - struct semaphore sem; unsigned char number; unsigned char * interrupt_in_buffer; diff --git a/trunk/drivers/usb/serial/visor.c b/trunk/drivers/usb/serial/visor.c index 49b1fbe61f25..a473c1c34559 100644 --- a/trunk/drivers/usb/serial/visor.c +++ b/trunk/drivers/usb/serial/visor.c @@ -173,11 +173,11 @@ static struct usb_device_id id_table_combined [] = { MODULE_DEVICE_TABLE (usb, id_table_combined); static struct usb_driver visor_driver = { + .owner = THIS_MODULE, .name = "visor", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */ diff --git a/trunk/drivers/usb/serial/whiteheat.c b/trunk/drivers/usb/serial/whiteheat.c index a7c3c4734d83..18c3183be769 100644 --- a/trunk/drivers/usb/serial/whiteheat.c +++ b/trunk/drivers/usb/serial/whiteheat.c @@ -127,11 +127,11 @@ static struct usb_device_id id_table_combined [] = { MODULE_DEVICE_TABLE (usb, id_table_combined); static struct usb_driver whiteheat_driver = { + .owner = THIS_MODULE, .name = "whiteheat", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */ diff --git a/trunk/drivers/usb/storage/Kconfig b/trunk/drivers/usb/storage/Kconfig index 92be101feba7..c41d64dbb0f0 100644 --- a/trunk/drivers/usb/storage/Kconfig +++ b/trunk/drivers/usb/storage/Kconfig @@ -112,15 +112,6 @@ config USB_STORAGE_JUMPSHOT Say Y here to include additional code to support the Lexar Jumpshot USB CompactFlash reader. -config USB_STORAGE_ALAUDA - bool "Olympus MAUSB-10/Fuji DPC-R1 support (EXPERIMENTAL)" - depends on USB_STORAGE && EXPERIMENTAL - help - Say Y here to include additional code to support the Olympus MAUSB-10 - and Fujifilm DPC-R1 USB Card reader/writer devices. - - These devices are based on the Alauda chip and support support both - XD and SmartMedia cards. config USB_STORAGE_ONETOUCH bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)" @@ -133,17 +124,3 @@ config USB_STORAGE_ONETOUCH hard drive's as an input device. An action can be associated with this input in any keybinding software. (e.g. gnome's keyboard short- cuts) - -config USB_LIBUSUAL - bool "The shared table of common (or usual) storage devices" - depends on USB - help - This module contains a table of common (or usual) devices - for usb-storage and ub drivers, and allows to switch binding - of these devices without rebuilding modules. - - Typical syntax of /etc/modprobe.conf is: - - options libusual bias="ub" - - If unsure, say N. diff --git a/trunk/drivers/usb/storage/Makefile b/trunk/drivers/usb/storage/Makefile index 8cbba22508a4..44ab8f9978fe 100644 --- a/trunk/drivers/usb/storage/Makefile +++ b/trunk/drivers/usb/storage/Makefile @@ -18,12 +18,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM) += dpcm.o usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o $(usb-storage-obj-y) - -ifneq ($(CONFIG_USB_LIBUSUAL),) - obj-$(CONFIG_USB) += libusual.o -endif diff --git a/trunk/drivers/usb/storage/alauda.c b/trunk/drivers/usb/storage/alauda.c deleted file mode 100644 index 4d3cbb12b713..000000000000 --- a/trunk/drivers/usb/storage/alauda.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * Driver for Alauda-based card readers - * - * Current development and maintenance by: - * (c) 2005 Daniel Drake - * - * The 'Alauda' is a chip manufacturered by RATOC for OEM use. - * - * Alauda implements a vendor-specific command set to access two media reader - * ports (XD, SmartMedia). This driver converts SCSI commands to the commands - * which are accepted by these devices. - * - * The driver was developed through reverse-engineering, with the help of the - * sddr09 driver which has many similarities, and with some help from the - * (very old) vendor-supplied GPL sma03 driver. - * - * For protocol info, see http://alauda.sourceforge.net - * - * 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, 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. - */ - -#include -#include -#include - -#include "usb.h" -#include "transport.h" -#include "protocol.h" -#include "debug.h" -#include "alauda.h" - -#define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) -#define LSB_of(s) ((s)&0xFF) -#define MSB_of(s) ((s)>>8) - -#define MEDIA_PORT(us) us->srb->device->lun -#define MEDIA_INFO(us) ((struct alauda_info *)us->extra)->port[MEDIA_PORT(us)] - -#define PBA_LO(pba) ((pba & 0xF) << 5) -#define PBA_HI(pba) (pba >> 3) -#define PBA_ZONE(pba) (pba >> 11) - -/* - * Media handling - */ - -struct alauda_card_info { - unsigned char id; /* id byte */ - unsigned char chipshift; /* 1< LBA mappings for a particular port - */ -static void alauda_free_maps (struct alauda_media_info *media_info) -{ - unsigned int shift = media_info->zoneshift - + media_info->blockshift + media_info->pageshift; - unsigned int num_zones = media_info->capacity >> shift; - unsigned int i; - - if (media_info->lba_to_pba != NULL) - for (i = 0; i < num_zones; i++) { - kfree(media_info->lba_to_pba[i]); - media_info->lba_to_pba[i] = NULL; - } - - if (media_info->pba_to_lba != NULL) - for (i = 0; i < num_zones; i++) { - kfree(media_info->pba_to_lba[i]); - media_info->pba_to_lba[i] = NULL; - } -} - -/* - * Returns 2 bytes of status data - * The first byte describes media status, and second byte describes door status - */ -static int alauda_get_media_status(struct us_data *us, unsigned char *data) -{ - int rc; - unsigned char command; - - if (MEDIA_PORT(us) == ALAUDA_PORT_XD) - command = ALAUDA_GET_XD_MEDIA_STATUS; - else - command = ALAUDA_GET_SM_MEDIA_STATUS; - - rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, - command, 0xc0, 0, 1, data, 2); - - US_DEBUGP("alauda_get_media_status: Media status %02X %02X\n", - data[0], data[1]); - - return rc; -} - -/* - * Clears the "media was changed" bit so that we know when it changes again - * in the future. - */ -static int alauda_ack_media(struct us_data *us) -{ - unsigned char command; - - if (MEDIA_PORT(us) == ALAUDA_PORT_XD) - command = ALAUDA_ACK_XD_MEDIA_CHANGE; - else - command = ALAUDA_ACK_SM_MEDIA_CHANGE; - - return usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, - command, 0x40, 0, 1, NULL, 0); -} - -/* - * Retrieves a 4-byte media signature, which indicates manufacturer, capacity, - * and some other details. - */ -static int alauda_get_media_signature(struct us_data *us, unsigned char *data) -{ - unsigned char command; - - if (MEDIA_PORT(us) == ALAUDA_PORT_XD) - command = ALAUDA_GET_XD_MEDIA_SIG; - else - command = ALAUDA_GET_SM_MEDIA_SIG; - - return usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, - command, 0xc0, 0, 0, data, 4); -} - -/* - * Resets the media status (but not the whole device?) - */ -static int alauda_reset_media(struct us_data *us) -{ - unsigned char *command = us->iobuf; - - memset(command, 0, 9); - command[0] = ALAUDA_BULK_CMD; - command[1] = ALAUDA_BULK_RESET_MEDIA; - command[8] = MEDIA_PORT(us); - - return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, - command, 9, NULL); -} - -/* - * Examines the media and deduces capacity, etc. - */ -static int alauda_init_media(struct us_data *us) -{ - unsigned char *data = us->iobuf; - int ready = 0; - struct alauda_card_info *media_info; - unsigned int num_zones; - - while (ready == 0) { - msleep(20); - - if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; - - if (data[0] & 0x10) - ready = 1; - } - - US_DEBUGP("alauda_init_media: We are ready for action!\n"); - - if (alauda_ack_media(us) != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; - - msleep(10); - - if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; - - if (data[0] != 0x14) { - US_DEBUGP("alauda_init_media: Media not ready after ack\n"); - return USB_STOR_TRANSPORT_ERROR; - } - - if (alauda_get_media_signature(us, data) != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; - - US_DEBUGP("alauda_init_media: Media signature: %02X %02X %02X %02X\n", - data[0], data[1], data[2], data[3]); - media_info = alauda_card_find_id(data[1]); - if (media_info == NULL) { - printk("alauda_init_media: Unrecognised media signature: " - "%02X %02X %02X %02X\n", - data[0], data[1], data[2], data[3]); - return USB_STOR_TRANSPORT_ERROR; - } - - MEDIA_INFO(us).capacity = 1 << media_info->chipshift; - US_DEBUGP("Found media with capacity: %ldMB\n", - MEDIA_INFO(us).capacity >> 20); - - MEDIA_INFO(us).pageshift = media_info->pageshift; - MEDIA_INFO(us).blockshift = media_info->blockshift; - MEDIA_INFO(us).zoneshift = media_info->zoneshift; - - MEDIA_INFO(us).pagesize = 1 << media_info->pageshift; - MEDIA_INFO(us).blocksize = 1 << media_info->blockshift; - MEDIA_INFO(us).zonesize = 1 << media_info->zoneshift; - - MEDIA_INFO(us).uzonesize = ((1 << media_info->zoneshift) / 128) * 125; - MEDIA_INFO(us).blockmask = MEDIA_INFO(us).blocksize - 1; - - num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift - + MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift); - MEDIA_INFO(us).pba_to_lba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO); - MEDIA_INFO(us).lba_to_pba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO); - - if (alauda_reset_media(us) != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; - - return USB_STOR_TRANSPORT_GOOD; -} - -/* - * Examines the media status and does the right thing when the media has gone, - * appeared, or changed. - */ -static int alauda_check_media(struct us_data *us) -{ - struct alauda_info *info = (struct alauda_info *) us->extra; - unsigned char status[2]; - int rc; - - rc = alauda_get_media_status(us, status); - - /* Check for no media or door open */ - if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10) - || ((status[1] & 0x01) == 0)) { - US_DEBUGP("alauda_check_media: No media, or door open\n"); - alauda_free_maps(&MEDIA_INFO(us)); - info->sense_key = 0x02; - info->sense_asc = 0x3A; - info->sense_ascq = 0x00; - return USB_STOR_TRANSPORT_FAILED; - } - - /* Check for media change */ - if (status[0] & 0x08) { - US_DEBUGP("alauda_check_media: Media change detected\n"); - alauda_free_maps(&MEDIA_INFO(us)); - alauda_init_media(us); - - info->sense_key = UNIT_ATTENTION; - info->sense_asc = 0x28; - info->sense_ascq = 0x00; - return USB_STOR_TRANSPORT_FAILED; - } - - return USB_STOR_TRANSPORT_GOOD; -} - -/* - * Checks the status from the 2nd status register - * Returns 3 bytes of status data, only the first is known - */ -static int alauda_check_status2(struct us_data *us) -{ - int rc; - unsigned char command[] = { - ALAUDA_BULK_CMD, ALAUDA_BULK_GET_STATUS2, - 0, 0, 0, 0, 3, 0, MEDIA_PORT(us) - }; - unsigned char data[3]; - - rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, - command, 9, NULL); - if (rc != USB_STOR_XFER_GOOD) - return rc; - - rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - data, 3, NULL); - if (rc != USB_STOR_XFER_GOOD) - return rc; - - US_DEBUGP("alauda_check_status2: %02X %02X %02X\n", data[0], data[1], data[2]); - if (data[0] & ALAUDA_STATUS_ERROR) - return USB_STOR_XFER_ERROR; - - return USB_STOR_XFER_GOOD; -} - -/* - * Gets the redundancy data for the first page of a PBA - * Returns 16 bytes. - */ -static int alauda_get_redu_data(struct us_data *us, u16 pba, unsigned char *data) -{ - int rc; - unsigned char command[] = { - ALAUDA_BULK_CMD, ALAUDA_BULK_GET_REDU_DATA, - PBA_HI(pba), PBA_ZONE(pba), 0, PBA_LO(pba), 0, 0, MEDIA_PORT(us) - }; - - rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, - command, 9, NULL); - if (rc != USB_STOR_XFER_GOOD) - return rc; - - return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - data, 16, NULL); -} - -/* - * Finds the first unused PBA in a zone - * Returns the absolute PBA of an unused PBA, or 0 if none found. - */ -static u16 alauda_find_unused_pba(struct alauda_media_info *info, - unsigned int zone) -{ - u16 *pba_to_lba = info->pba_to_lba[zone]; - unsigned int i; - - for (i = 0; i < info->zonesize; i++) - if (pba_to_lba[i] == UNDEF) - return (zone << info->zoneshift) + i; - - return 0; -} - -/* - * Reads the redundancy data for all PBA's in a zone - * Produces lba <--> pba mappings - */ -static int alauda_read_map(struct us_data *us, unsigned int zone) -{ - unsigned char *data = us->iobuf; - int result; - int i, j; - unsigned int zonesize = MEDIA_INFO(us).zonesize; - unsigned int uzonesize = MEDIA_INFO(us).uzonesize; - unsigned int lba_offset, lba_real, blocknum; - unsigned int zone_base_lba = zone * uzonesize; - unsigned int zone_base_pba = zone * zonesize; - u16 *lba_to_pba = kcalloc(zonesize, sizeof(u16), GFP_NOIO); - u16 *pba_to_lba = kcalloc(zonesize, sizeof(u16), GFP_NOIO); - if (lba_to_pba == NULL || pba_to_lba == NULL) { - result = USB_STOR_TRANSPORT_ERROR; - goto error; - } - - US_DEBUGP("alauda_read_map: Mapping blocks for zone %d\n", zone); - - /* 1024 PBA's per zone */ - for (i = 0; i < zonesize; i++) - lba_to_pba[i] = pba_to_lba[i] = UNDEF; - - for (i = 0; i < zonesize; i++) { - blocknum = zone_base_pba + i; - - result = alauda_get_redu_data(us, blocknum, data); - if (result != USB_STOR_XFER_GOOD) { - result = USB_STOR_TRANSPORT_ERROR; - goto error; - } - - /* special PBAs have control field 0^16 */ - for (j = 0; j < 16; j++) - if (data[j] != 0) - goto nonz; - pba_to_lba[i] = UNUSABLE; - US_DEBUGP("alauda_read_map: PBA %d has no logical mapping\n", blocknum); - continue; - - nonz: - /* unwritten PBAs have control field FF^16 */ - for (j = 0; j < 16; j++) - if (data[j] != 0xff) - goto nonff; - continue; - - nonff: - /* normal PBAs start with six FFs */ - if (j < 6) { - US_DEBUGP("alauda_read_map: PBA %d has no logical mapping: " - "reserved area = %02X%02X%02X%02X " - "data status %02X block status %02X\n", - blocknum, data[0], data[1], data[2], data[3], - data[4], data[5]); - pba_to_lba[i] = UNUSABLE; - continue; - } - - if ((data[6] >> 4) != 0x01) { - US_DEBUGP("alauda_read_map: PBA %d has invalid address " - "field %02X%02X/%02X%02X\n", - blocknum, data[6], data[7], data[11], data[12]); - pba_to_lba[i] = UNUSABLE; - continue; - } - - /* check even parity */ - if (parity[data[6] ^ data[7]]) { - printk("alauda_read_map: Bad parity in LBA for block %d" - " (%02X %02X)\n", i, data[6], data[7]); - pba_to_lba[i] = UNUSABLE; - continue; - } - - lba_offset = short_pack(data[7], data[6]); - lba_offset = (lba_offset & 0x07FF) >> 1; - lba_real = lba_offset + zone_base_lba; - - /* - * Every 1024 physical blocks ("zone"), the LBA numbers - * go back to zero, but are within a higher block of LBA's. - * Also, there is a maximum of 1000 LBA's per zone. - * In other words, in PBA 1024-2047 you will find LBA 0-999 - * which are really LBA 1000-1999. This allows for 24 bad - * or special physical blocks per zone. - */ - - if (lba_offset >= uzonesize) { - printk("alauda_read_map: Bad low LBA %d for block %d\n", - lba_real, blocknum); - continue; - } - - if (lba_to_pba[lba_offset] != UNDEF) { - printk("alauda_read_map: LBA %d seen for PBA %d and %d\n", - lba_real, lba_to_pba[lba_offset], blocknum); - continue; - } - - pba_to_lba[i] = lba_real; - lba_to_pba[lba_offset] = blocknum; - continue; - } - - MEDIA_INFO(us).lba_to_pba[zone] = lba_to_pba; - MEDIA_INFO(us).pba_to_lba[zone] = pba_to_lba; - result = 0; - goto out; - -error: - kfree(lba_to_pba); - kfree(pba_to_lba); -out: - return result; -} - -/* - * Checks to see whether we have already mapped a certain zone - * If we haven't, the map is generated - */ -static void alauda_ensure_map_for_zone(struct us_data *us, unsigned int zone) -{ - if (MEDIA_INFO(us).lba_to_pba[zone] == NULL - || MEDIA_INFO(us).pba_to_lba[zone] == NULL) - alauda_read_map(us, zone); -} - -/* - * Erases an entire block - */ -static int alauda_erase_block(struct us_data *us, u16 pba) -{ - int rc; - unsigned char command[] = { - ALAUDA_BULK_CMD, ALAUDA_BULK_ERASE_BLOCK, PBA_HI(pba), - PBA_ZONE(pba), 0, PBA_LO(pba), 0x02, 0, MEDIA_PORT(us) - }; - unsigned char buf[2]; - - US_DEBUGP("alauda_erase_block: Erasing PBA %d\n", pba); - - rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, - command, 9, NULL); - if (rc != USB_STOR_XFER_GOOD) - return rc; - - rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - buf, 2, NULL); - if (rc != USB_STOR_XFER_GOOD) - return rc; - - US_DEBUGP("alauda_erase_block: Erase result: %02X %02X\n", - buf[0], buf[1]); - return rc; -} - -/* - * Reads data from a certain offset page inside a PBA, including interleaved - * redundancy data. Returns (pagesize+64)*pages bytes in data. - */ -static int alauda_read_block_raw(struct us_data *us, u16 pba, - unsigned int page, unsigned int pages, unsigned char *data) -{ - int rc; - unsigned char command[] = { - ALAUDA_BULK_CMD, ALAUDA_BULK_READ_BLOCK, PBA_HI(pba), - PBA_ZONE(pba), 0, PBA_LO(pba) + page, pages, 0, MEDIA_PORT(us) - }; - - US_DEBUGP("alauda_read_block: pba %d page %d count %d\n", - pba, page, pages); - - rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, - command, 9, NULL); - if (rc != USB_STOR_XFER_GOOD) - return rc; - - return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - data, (MEDIA_INFO(us).pagesize + 64) * pages, NULL); -} - -/* - * Reads data from a certain offset page inside a PBA, excluding redundancy - * data. Returns pagesize*pages bytes in data. Note that data must be big enough - * to hold (pagesize+64)*pages bytes of data, but you can ignore those 'extra' - * trailing bytes outside this function. - */ -static int alauda_read_block(struct us_data *us, u16 pba, - unsigned int page, unsigned int pages, unsigned char *data) -{ - int i, rc; - unsigned int pagesize = MEDIA_INFO(us).pagesize; - - rc = alauda_read_block_raw(us, pba, page, pages, data); - if (rc != USB_STOR_XFER_GOOD) - return rc; - - /* Cut out the redundancy data */ - for (i = 0; i < pages; i++) { - int dest_offset = i * pagesize; - int src_offset = i * (pagesize + 64); - memmove(data + dest_offset, data + src_offset, pagesize); - } - - return rc; -} - -/* - * Writes an entire block of data and checks status after write. - * Redundancy data must be already included in data. Data should be - * (pagesize+64)*blocksize bytes in length. - */ -static int alauda_write_block(struct us_data *us, u16 pba, unsigned char *data) -{ - int rc; - struct alauda_info *info = (struct alauda_info *) us->extra; - unsigned char command[] = { - ALAUDA_BULK_CMD, ALAUDA_BULK_WRITE_BLOCK, PBA_HI(pba), - PBA_ZONE(pba), 0, PBA_LO(pba), 32, 0, MEDIA_PORT(us) - }; - - US_DEBUGP("alauda_write_block: pba %d\n", pba); - - rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, - command, 9, NULL); - if (rc != USB_STOR_XFER_GOOD) - return rc; - - rc = usb_stor_bulk_transfer_buf(us, info->wr_ep, data, - (MEDIA_INFO(us).pagesize + 64) * MEDIA_INFO(us).blocksize, - NULL); - if (rc != USB_STOR_XFER_GOOD) - return rc; - - return alauda_check_status2(us); -} - -/* - * Write some data to a specific LBA. - */ -static int alauda_write_lba(struct us_data *us, u16 lba, - unsigned int page, unsigned int pages, - unsigned char *ptr, unsigned char *blockbuffer) -{ - u16 pba, lbap, new_pba; - unsigned char *bptr, *cptr, *xptr; - unsigned char ecc[3]; - int i, result; - unsigned int uzonesize = MEDIA_INFO(us).uzonesize; - unsigned int zonesize = MEDIA_INFO(us).zonesize; - unsigned int pagesize = MEDIA_INFO(us).pagesize; - unsigned int blocksize = MEDIA_INFO(us).blocksize; - unsigned int lba_offset = lba % uzonesize; - unsigned int new_pba_offset; - unsigned int zone = lba / uzonesize; - - alauda_ensure_map_for_zone(us, zone); - - pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset]; - if (pba == 1) { - /* Maybe it is impossible to write to PBA 1. - Fake success, but don't do anything. */ - printk("alauda_write_lba: avoid writing to pba 1\n"); - return USB_STOR_TRANSPORT_GOOD; - } - - new_pba = alauda_find_unused_pba(&MEDIA_INFO(us), zone); - if (!new_pba) { - printk("alauda_write_lba: Out of unused blocks\n"); - return USB_STOR_TRANSPORT_ERROR; - } - - /* read old contents */ - if (pba != UNDEF) { - result = alauda_read_block_raw(us, pba, 0, - blocksize, blockbuffer); - if (result != USB_STOR_XFER_GOOD) - return result; - } else { - memset(blockbuffer, 0, blocksize * (pagesize + 64)); - } - - lbap = (lba_offset << 1) | 0x1000; - if (parity[MSB_of(lbap) ^ LSB_of(lbap)]) - lbap ^= 1; - - /* check old contents and fill lba */ - for (i = 0; i < blocksize; i++) { - bptr = blockbuffer + (i * (pagesize + 64)); - cptr = bptr + pagesize; - nand_compute_ecc(bptr, ecc); - if (!nand_compare_ecc(cptr+13, ecc)) { - US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n", - i, pba); - nand_store_ecc(cptr+13, ecc); - } - nand_compute_ecc(bptr + (pagesize / 2), ecc); - if (!nand_compare_ecc(cptr+8, ecc)) { - US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n", - i, pba); - nand_store_ecc(cptr+8, ecc); - } - cptr[6] = cptr[11] = MSB_of(lbap); - cptr[7] = cptr[12] = LSB_of(lbap); - } - - /* copy in new stuff and compute ECC */ - xptr = ptr; - for (i = page; i < page+pages; i++) { - bptr = blockbuffer + (i * (pagesize + 64)); - cptr = bptr + pagesize; - memcpy(bptr, xptr, pagesize); - xptr += pagesize; - nand_compute_ecc(bptr, ecc); - nand_store_ecc(cptr+13, ecc); - nand_compute_ecc(bptr + (pagesize / 2), ecc); - nand_store_ecc(cptr+8, ecc); - } - - result = alauda_write_block(us, new_pba, blockbuffer); - if (result != USB_STOR_XFER_GOOD) - return result; - - new_pba_offset = new_pba - (zone * zonesize); - MEDIA_INFO(us).pba_to_lba[zone][new_pba_offset] = lba; - MEDIA_INFO(us).lba_to_pba[zone][lba_offset] = new_pba; - US_DEBUGP("alauda_write_lba: Remapped LBA %d to PBA %d\n", - lba, new_pba); - - if (pba != UNDEF) { - unsigned int pba_offset = pba - (zone * zonesize); - result = alauda_erase_block(us, pba); - if (result != USB_STOR_XFER_GOOD) - return result; - MEDIA_INFO(us).pba_to_lba[zone][pba_offset] = UNDEF; - } - - return USB_STOR_TRANSPORT_GOOD; -} - -/* - * Read data from a specific sector address - */ -static int alauda_read_data(struct us_data *us, unsigned long address, - unsigned int sectors) -{ - unsigned char *buffer; - u16 lba, max_lba; - unsigned int page, len, index, offset; - unsigned int blockshift = MEDIA_INFO(us).blockshift; - unsigned int pageshift = MEDIA_INFO(us).pageshift; - unsigned int blocksize = MEDIA_INFO(us).blocksize; - unsigned int pagesize = MEDIA_INFO(us).pagesize; - unsigned int uzonesize = MEDIA_INFO(us).uzonesize; - int result; - - /* - * Since we only read in one block at a time, we have to create - * a bounce buffer and move the data a piece at a time between the - * bounce buffer and the actual transfer buffer. - * We make this buffer big enough to hold temporary redundancy data, - * which we use when reading the data blocks. - */ - - len = min(sectors, blocksize) * (pagesize + 64); - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) { - printk("alauda_read_data: Out of memory\n"); - return USB_STOR_TRANSPORT_ERROR; - } - - /* Figure out the initial LBA and page */ - lba = address >> blockshift; - page = (address & MEDIA_INFO(us).blockmask); - max_lba = MEDIA_INFO(us).capacity >> (blockshift + pageshift); - - result = USB_STOR_TRANSPORT_GOOD; - index = offset = 0; - - while (sectors > 0) { - unsigned int zone = lba / uzonesize; /* integer division */ - unsigned int lba_offset = lba - (zone * uzonesize); - unsigned int pages; - u16 pba; - alauda_ensure_map_for_zone(us, zone); - - /* Not overflowing capacity? */ - if (lba >= max_lba) { - US_DEBUGP("Error: Requested lba %u exceeds " - "maximum %u\n", lba, max_lba); - result = USB_STOR_TRANSPORT_ERROR; - break; - } - - /* Find number of pages we can read in this block */ - pages = min(sectors, blocksize - page); - len = pages << pageshift; - - /* Find where this lba lives on disk */ - pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset]; - - if (pba == UNDEF) { /* this lba was never written */ - US_DEBUGP("Read %d zero pages (LBA %d) page %d\n", - pages, lba, page); - - /* This is not really an error. It just means - that the block has never been written. - Instead of returning USB_STOR_TRANSPORT_ERROR - it is better to return all zero data. */ - - memset(buffer, 0, len); - } else { - US_DEBUGP("Read %d pages, from PBA %d" - " (LBA %d) page %d\n", - pages, pba, lba, page); - - result = alauda_read_block(us, pba, page, pages, buffer); - if (result != USB_STOR_TRANSPORT_GOOD) - break; - } - - /* Store the data in the transfer buffer */ - usb_stor_access_xfer_buf(buffer, len, us->srb, - &index, &offset, TO_XFER_BUF); - - page = 0; - lba++; - sectors -= pages; - } - - kfree(buffer); - return result; -} - -/* - * Write data to a specific sector address - */ -static int alauda_write_data(struct us_data *us, unsigned long address, - unsigned int sectors) -{ - unsigned char *buffer, *blockbuffer; - unsigned int page, len, index, offset; - unsigned int blockshift = MEDIA_INFO(us).blockshift; - unsigned int pageshift = MEDIA_INFO(us).pageshift; - unsigned int blocksize = MEDIA_INFO(us).blocksize; - unsigned int pagesize = MEDIA_INFO(us).pagesize; - u16 lba, max_lba; - int result; - - /* - * Since we don't write the user data directly to the device, - * we have to create a bounce buffer and move the data a piece - * at a time between the bounce buffer and the actual transfer buffer. - */ - - len = min(sectors, blocksize) * pagesize; - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) { - printk("alauda_write_data: Out of memory\n"); - return USB_STOR_TRANSPORT_ERROR; - } - - /* - * We also need a temporary block buffer, where we read in the old data, - * overwrite parts with the new data, and manipulate the redundancy data - */ - blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO); - if (blockbuffer == NULL) { - printk("alauda_write_data: Out of memory\n"); - kfree(buffer); - return USB_STOR_TRANSPORT_ERROR; - } - - /* Figure out the initial LBA and page */ - lba = address >> blockshift; - page = (address & MEDIA_INFO(us).blockmask); - max_lba = MEDIA_INFO(us).capacity >> (pageshift + blockshift); - - result = USB_STOR_TRANSPORT_GOOD; - index = offset = 0; - - while (sectors > 0) { - /* Write as many sectors as possible in this block */ - unsigned int pages = min(sectors, blocksize - page); - len = pages << pageshift; - - /* Not overflowing capacity? */ - if (lba >= max_lba) { - US_DEBUGP("alauda_write_data: Requested lba %u exceeds " - "maximum %u\n", lba, max_lba); - result = USB_STOR_TRANSPORT_ERROR; - break; - } - - /* Get the data from the transfer buffer */ - usb_stor_access_xfer_buf(buffer, len, us->srb, - &index, &offset, FROM_XFER_BUF); - - result = alauda_write_lba(us, lba, page, pages, buffer, - blockbuffer); - if (result != USB_STOR_TRANSPORT_GOOD) - break; - - page = 0; - lba++; - sectors -= pages; - } - - kfree(buffer); - kfree(blockbuffer); - return result; -} - -/* - * Our interface with the rest of the world - */ - -static void alauda_info_destructor(void *extra) -{ - struct alauda_info *info = (struct alauda_info *) extra; - int port; - - if (!info) - return; - - for (port = 0; port < 2; port++) { - struct alauda_media_info *media_info = &info->port[port]; - - alauda_free_maps(media_info); - kfree(media_info->lba_to_pba); - kfree(media_info->pba_to_lba); - } -} - -/* - * Initialize alauda_info struct and find the data-write endpoint - */ -int init_alauda(struct us_data *us) -{ - struct alauda_info *info; - struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting; - nand_init_ecc(); - - us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO); - if (!us->extra) { - US_DEBUGP("init_alauda: Gah! Can't allocate storage for" - "alauda info struct!\n"); - return USB_STOR_TRANSPORT_ERROR; - } - info = (struct alauda_info *) us->extra; - us->extra_destructor = alauda_info_destructor; - - info->wr_ep = usb_sndbulkpipe(us->pusb_dev, - altsetting->endpoint[0].desc.bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK); - - return USB_STOR_TRANSPORT_GOOD; -} - -int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) -{ - int rc; - struct alauda_info *info = (struct alauda_info *) us->extra; - unsigned char *ptr = us->iobuf; - static unsigned char inquiry_response[36] = { - 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00 - }; - - if (srb->cmnd[0] == INQUIRY) { - US_DEBUGP("alauda_transport: INQUIRY. " - "Returning bogus response.\n"); - memcpy(ptr, inquiry_response, sizeof(inquiry_response)); - fill_inquiry_response(us, ptr, 36); - return USB_STOR_TRANSPORT_GOOD; - } - - if (srb->cmnd[0] == TEST_UNIT_READY) { - US_DEBUGP("alauda_transport: TEST_UNIT_READY.\n"); - return alauda_check_media(us); - } - - if (srb->cmnd[0] == READ_CAPACITY) { - unsigned int num_zones; - unsigned long capacity; - - rc = alauda_check_media(us); - if (rc != USB_STOR_TRANSPORT_GOOD) - return rc; - - num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift - + MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift); - - capacity = num_zones * MEDIA_INFO(us).uzonesize - * MEDIA_INFO(us).blocksize; - - /* Report capacity and page size */ - ((__be32 *) ptr)[0] = cpu_to_be32(capacity - 1); - ((__be32 *) ptr)[1] = cpu_to_be32(512); - - usb_stor_set_xfer_buf(ptr, 8, srb); - return USB_STOR_TRANSPORT_GOOD; - } - - if (srb->cmnd[0] == READ_10) { - unsigned int page, pages; - - rc = alauda_check_media(us); - if (rc != USB_STOR_TRANSPORT_GOOD) - return rc; - - page = short_pack(srb->cmnd[3], srb->cmnd[2]); - page <<= 16; - page |= short_pack(srb->cmnd[5], srb->cmnd[4]); - pages = short_pack(srb->cmnd[8], srb->cmnd[7]); - - US_DEBUGP("alauda_transport: READ_10: page %d pagect %d\n", - page, pages); - - return alauda_read_data(us, page, pages); - } - - if (srb->cmnd[0] == WRITE_10) { - unsigned int page, pages; - - rc = alauda_check_media(us); - if (rc != USB_STOR_TRANSPORT_GOOD) - return rc; - - page = short_pack(srb->cmnd[3], srb->cmnd[2]); - page <<= 16; - page |= short_pack(srb->cmnd[5], srb->cmnd[4]); - pages = short_pack(srb->cmnd[8], srb->cmnd[7]); - - US_DEBUGP("alauda_transport: WRITE_10: page %d pagect %d\n", - page, pages); - - return alauda_write_data(us, page, pages); - } - - if (srb->cmnd[0] == REQUEST_SENSE) { - US_DEBUGP("alauda_transport: REQUEST_SENSE.\n"); - - memset(ptr, 0, 18); - ptr[0] = 0xF0; - ptr[2] = info->sense_key; - ptr[7] = 11; - ptr[12] = info->sense_asc; - ptr[13] = info->sense_ascq; - usb_stor_set_xfer_buf(ptr, 18, srb); - - return USB_STOR_TRANSPORT_GOOD; - } - - if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { - /* sure. whatever. not like we can stop the user from popping - the media out of the device (no locking doors, etc) */ - return USB_STOR_TRANSPORT_GOOD; - } - - US_DEBUGP("alauda_transport: Gah! Unknown command: %d (0x%x)\n", - srb->cmnd[0], srb->cmnd[0]); - info->sense_key = 0x05; - info->sense_asc = 0x20; - info->sense_ascq = 0x00; - return USB_STOR_TRANSPORT_FAILED; -} - diff --git a/trunk/drivers/usb/storage/alauda.h b/trunk/drivers/usb/storage/alauda.h deleted file mode 100644 index a700f87d0803..000000000000 --- a/trunk/drivers/usb/storage/alauda.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Driver for Alauda-based card readers - * - * Current development and maintenance by: - * (c) 2005 Daniel Drake - * - * See alauda.c for more explanation. - * - * 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, 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. - */ - -#ifndef _USB_ALAUDA_H -#define _USB_ALAUDA_H - -/* - * Status bytes - */ -#define ALAUDA_STATUS_ERROR 0x01 -#define ALAUDA_STATUS_READY 0x40 - -/* - * Control opcodes (for request field) - */ -#define ALAUDA_GET_XD_MEDIA_STATUS 0x08 -#define ALAUDA_GET_SM_MEDIA_STATUS 0x98 -#define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a -#define ALAUDA_ACK_SM_MEDIA_CHANGE 0x9a -#define ALAUDA_GET_XD_MEDIA_SIG 0x86 -#define ALAUDA_GET_SM_MEDIA_SIG 0x96 - -/* - * Bulk command identity (byte 0) - */ -#define ALAUDA_BULK_CMD 0x40 - -/* - * Bulk opcodes (byte 1) - */ -#define ALAUDA_BULK_GET_REDU_DATA 0x85 -#define ALAUDA_BULK_READ_BLOCK 0x94 -#define ALAUDA_BULK_ERASE_BLOCK 0xa3 -#define ALAUDA_BULK_WRITE_BLOCK 0xb4 -#define ALAUDA_BULK_GET_STATUS2 0xb7 -#define ALAUDA_BULK_RESET_MEDIA 0xe0 - -/* - * Port to operate on (byte 8) - */ -#define ALAUDA_PORT_XD 0x00 -#define ALAUDA_PORT_SM 0x01 - -/* - * LBA and PBA are unsigned ints. Special values. - */ -#define UNDEF 0xffff -#define SPARE 0xfffe -#define UNUSABLE 0xfffd - -int init_alauda(struct us_data *us); -int alauda_transport(struct scsi_cmnd *srb, struct us_data *us); - -struct alauda_media_info { - unsigned long capacity; /* total media size in bytes */ - unsigned int pagesize; /* page size in bytes */ - unsigned int blocksize; /* number of pages per block */ - unsigned int uzonesize; /* number of usable blocks per zone */ - unsigned int zonesize; /* number of blocks per zone */ - unsigned int blockmask; /* mask to get page from address */ - - unsigned char pageshift; - unsigned char blockshift; - unsigned char zoneshift; - - u16 **lba_to_pba; /* logical to physical block map */ - u16 **pba_to_lba; /* physical to logical block map */ -}; - -struct alauda_info { - struct alauda_media_info port[2]; - int wr_ep; /* endpoint to write data out of */ - - unsigned char sense_key; - unsigned long sense_asc; /* additional sense code */ - unsigned long sense_ascq; /* additional sense code qualifier */ -}; - -#endif - diff --git a/trunk/drivers/usb/storage/debug.c b/trunk/drivers/usb/storage/debug.c index 01e430654a13..5a9321705a74 100644 --- a/trunk/drivers/usb/storage/debug.c +++ b/trunk/drivers/usb/storage/debug.c @@ -132,7 +132,6 @@ void usb_stor_show_command(struct scsi_cmnd *srb) case 0x5C: what = "READ BUFFER CAPACITY"; break; case 0x5D: what = "SEND CUE SHEET"; break; case GPCMD_BLANK: what = "BLANK"; break; - case REPORT_LUNS: what = "REPORT LUNS"; break; case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break; case READ_12: what = "READ_12"; break; case WRITE_12: what = "WRITE_12"; break; diff --git a/trunk/drivers/usb/storage/initializers.h b/trunk/drivers/usb/storage/initializers.h index 4c1b2bd2e2e4..7372386f33d5 100644 --- a/trunk/drivers/usb/storage/initializers.h +++ b/trunk/drivers/usb/storage/initializers.h @@ -45,6 +45,10 @@ * mode */ int usb_stor_euscsi_init(struct us_data *us); +#ifdef CONFIG_USB_STORAGE_SDDR09 +int sddr09_init(struct us_data *us); +#endif + /* This function is required to activate all four slots on the UCR-61S2B * flash reader */ int usb_stor_ucr61s2b_init(struct us_data *us); diff --git a/trunk/drivers/usb/storage/libusual.c b/trunk/drivers/usb/storage/libusual.c deleted file mode 100644 index b28151d1b609..000000000000 --- a/trunk/drivers/usb/storage/libusual.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * libusual - * - * The libusual contains the table of devices common for ub and usb-storage. - */ -#include -#include -#include -#include -#include - -/* - */ -#define USU_MOD_FL_THREAD 1 /* Thread is running */ -#define USU_MOD_FL_PRESENT 2 /* The module is loaded */ - -struct mod_status { - unsigned long fls; -}; - -static struct mod_status stat[3]; -static DEFINE_SPINLOCK(usu_lock); - -/* - */ -#define USB_US_DEFAULT_BIAS USB_US_TYPE_STOR -static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS); - -#define BIAS_NAME_SIZE (sizeof("usb-storage")) -static const char *bias_names[3] = { "none", "usb-storage", "ub" }; - -static DECLARE_MUTEX_LOCKED(usu_init_notify); -static DECLARE_COMPLETION(usu_end_notify); -static atomic_t total_threads = ATOMIC_INIT(0); - -static int usu_probe_thread(void *arg); - -/* - * The table. - */ -#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName,useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = ((useType)<<24) } - -struct usb_device_id storage_usb_ids [] = { -# include "unusual_devs.h" - { } /* Terminating entry */ -}; - -#undef USUAL_DEV -#undef UNUSUAL_DEV - -MODULE_DEVICE_TABLE(usb, storage_usb_ids); -EXPORT_SYMBOL_GPL(storage_usb_ids); - -/* - * @type: the module type as an integer - */ -void usb_usual_set_present(int type) -{ - struct mod_status *st; - unsigned long flags; - - if (type <= 0 || type >= 3) - return; - st = &stat[type]; - spin_lock_irqsave(&usu_lock, flags); - st->fls |= USU_MOD_FL_PRESENT; - spin_unlock_irqrestore(&usu_lock, flags); -} -EXPORT_SYMBOL_GPL(usb_usual_set_present); - -void usb_usual_clear_present(int type) -{ - struct mod_status *st; - unsigned long flags; - - if (type <= 0 || type >= 3) - return; - st = &stat[type]; - spin_lock_irqsave(&usu_lock, flags); - st->fls &= ~USU_MOD_FL_PRESENT; - spin_unlock_irqrestore(&usu_lock, flags); -} -EXPORT_SYMBOL_GPL(usb_usual_clear_present); - -/* - * Match the calling driver type against the table. - * Returns: 0 if the device matches. - */ -int usb_usual_check_type(const struct usb_device_id *id, int caller_type) -{ - int id_type = USB_US_TYPE(id->driver_info); - - if (caller_type <= 0 || caller_type >= 3) - return -EINVAL; - - /* Drivers grab fixed assignment devices */ - if (id_type == caller_type) - return 0; - /* Drivers grab devices biased to them */ - if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias)) - return 0; - return -ENODEV; -} -EXPORT_SYMBOL_GPL(usb_usual_check_type); - -/* - */ -static int usu_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int type; - int rc; - unsigned long flags; - - type = USB_US_TYPE(id->driver_info); - if (type == 0) - type = atomic_read(&usu_bias); - - spin_lock_irqsave(&usu_lock, flags); - if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) { - spin_unlock_irqrestore(&usu_lock, flags); - return -ENXIO; - } - stat[type].fls |= USU_MOD_FL_THREAD; - spin_unlock_irqrestore(&usu_lock, flags); - - rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM); - if (rc < 0) { - printk(KERN_WARNING "libusual: " - "Unable to start the thread for %s: %d\n", - bias_names[type], rc); - spin_lock_irqsave(&usu_lock, flags); - stat[type].fls &= ~USU_MOD_FL_THREAD; - spin_unlock_irqrestore(&usu_lock, flags); - return rc; /* Not being -ENXIO causes a message printed */ - } - atomic_inc(&total_threads); - - return -ENXIO; -} - -static void usu_disconnect(struct usb_interface *intf) -{ - ; /* We should not be here. */ -} - -static struct usb_driver usu_driver = { - .name = "libusual", - .probe = usu_probe, - .disconnect = usu_disconnect, - .id_table = storage_usb_ids, -}; - -/* - * A whole new thread for a purpose of request_module seems quite stupid. - * The request_module forks once inside again. However, if we attempt - * to load a storage module from our own modprobe thread, that module - * references our symbols, which cannot be resolved until our module is - * initialized. I wish there was a way to wait for the end of initialization. - * The module notifier reports MODULE_STATE_COMING only. - * So, we wait until module->init ends as the next best thing. - */ -static int usu_probe_thread(void *arg) -{ - int type = (unsigned long) arg; - struct mod_status *st = &stat[type]; - int rc; - unsigned long flags; - - daemonize("libusual_%d", type); /* "usb-storage" is kinda too long */ - - /* A completion does not work here because it's counted. */ - down(&usu_init_notify); - up(&usu_init_notify); - - rc = request_module(bias_names[type]); - spin_lock_irqsave(&usu_lock, flags); - if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) { - /* - * This should not happen, but let us keep tabs on it. - */ - printk(KERN_NOTICE "libusual: " - "modprobe for %s succeeded, but module is not present\n", - bias_names[type]); - } - st->fls &= ~USU_MOD_FL_THREAD; - spin_unlock_irqrestore(&usu_lock, flags); - - complete_and_exit(&usu_end_notify, 0); -} - -/* - */ -static int __init usb_usual_init(void) -{ - int rc; - - rc = usb_register(&usu_driver); - up(&usu_init_notify); - return rc; -} - -static void __exit usb_usual_exit(void) -{ - /* - * We do not check for any drivers present, because - * they keep us pinned with symbol references. - */ - - usb_deregister(&usu_driver); - - while (atomic_read(&total_threads) > 0) { - wait_for_completion(&usu_end_notify); - atomic_dec(&total_threads); - } -} - -/* - * Validate and accept the bias parameter. - */ -static int usu_set_bias(const char *bias_s, struct kernel_param *kp) -{ - int i; - int len; - int bias_n = 0; - - len = strlen(bias_s); - if (len == 0) - return -EDOM; - if (bias_s[len-1] == '\n') - --len; - - for (i = 1; i < 3; i++) { - if (strncmp(bias_s, bias_names[i], len) == 0) { - bias_n = i; - break; - } - } - if (bias_n == 0) - return -EINVAL; - - atomic_set(&usu_bias, bias_n); - return 0; -} - -static int usu_get_bias(char *buffer, struct kernel_param *kp) -{ - return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)])); -} - -module_init(usb_usual_init); -module_exit(usb_usual_exit); - -module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR); -__MODULE_PARM_TYPE(bias, "string"); -MODULE_PARM_DESC(bias, "Bias to usb-storage or ub"); - -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/storage/onetouch.c b/trunk/drivers/usb/storage/onetouch.c index 55ee2d36d585..89401a59f952 100644 --- a/trunk/drivers/usb/storage/onetouch.c +++ b/trunk/drivers/usb/storage/onetouch.c @@ -52,7 +52,6 @@ struct usb_onetouch { struct urb *irq; /* urb for interrupt in report */ unsigned char *data; /* input data */ dma_addr_t data_dma; - unsigned int is_open:1; }; static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs) @@ -90,7 +89,6 @@ static int usb_onetouch_open(struct input_dev *dev) { struct usb_onetouch *onetouch = dev->private; - onetouch->is_open = 1; onetouch->irq->dev = onetouch->udev; if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) { err("usb_submit_urb failed"); @@ -105,30 +103,8 @@ static void usb_onetouch_close(struct input_dev *dev) struct usb_onetouch *onetouch = dev->private; usb_kill_urb(onetouch->irq); - onetouch->is_open = 0; } -#ifdef CONFIG_PM -static void usb_onetouch_pm_hook(struct us_data *us, int action) -{ - struct usb_onetouch *onetouch = (struct usb_onetouch *) us->extra; - - if (onetouch->is_open) { - switch (action) { - case US_SUSPEND: - usb_kill_urb(onetouch->irq); - break; - case US_RESUME: - if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0) - err("usb_submit_urb failed"); - break; - default: - break; - } - } -} -#endif /* CONFIG_PM */ - int onetouch_connect_input(struct us_data *ss) { struct usb_device *udev = ss->pusb_dev; @@ -209,9 +185,6 @@ int onetouch_connect_input(struct us_data *ss) ss->extra_destructor = onetouch_release_input; ss->extra = onetouch; -#ifdef CONFIG_PM - ss->suspend_resume_hook = usb_onetouch_pm_hook; -#endif input_register_device(onetouch->dev); diff --git a/trunk/drivers/usb/storage/protocol.h b/trunk/drivers/usb/storage/protocol.h index 845bed4b8031..02bff01ab09c 100644 --- a/trunk/drivers/usb/storage/protocol.h +++ b/trunk/drivers/usb/storage/protocol.h @@ -41,6 +41,20 @@ #ifndef _PROTOCOL_H_ #define _PROTOCOL_H_ +/* Sub Classes */ + +#define US_SC_RBC 0x01 /* Typically, flash devices */ +#define US_SC_8020 0x02 /* CD-ROM */ +#define US_SC_QIC 0x03 /* QIC-157 Tapes */ +#define US_SC_UFI 0x04 /* Floppy */ +#define US_SC_8070 0x05 /* Removable media */ +#define US_SC_SCSI 0x06 /* Transparent */ +#define US_SC_ISD200 0x07 /* ISD200 ATA */ +#define US_SC_MIN US_SC_RBC +#define US_SC_MAX US_SC_ISD200 + +#define US_SC_DEVICE 0xff /* Use device's value */ + /* Protocol handling routines */ extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*); extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*); diff --git a/trunk/drivers/usb/storage/sddr09.c b/trunk/drivers/usb/storage/sddr09.c index fb8bacaae27c..0ea2f5ab66ba 100644 --- a/trunk/drivers/usb/storage/sddr09.c +++ b/trunk/drivers/usb/storage/sddr09.c @@ -133,11 +133,13 @@ static struct nand_flash_dev nand_flash_ids[] = { { 0,} }; +#define SIZE(a) (sizeof(a)/sizeof((a)[0])) + static struct nand_flash_dev * nand_find_id(unsigned char id) { int i; - for (i = 0; i < ARRAY_SIZE(nand_flash_ids); i++) + for (i = 0; i < SIZE(nand_flash_ids); i++) if (nand_flash_ids[i].model_id == id) return &(nand_flash_ids[i]); return NULL; @@ -212,20 +214,6 @@ static void nand_store_ecc(unsigned char *data, unsigned char *ecc) { * The actual driver starts here. */ -struct sddr09_card_info { - unsigned long capacity; /* Size of card in bytes */ - int pagesize; /* Size of page in bytes */ - int pageshift; /* log2 of pagesize */ - int blocksize; /* Size of block in pages */ - int blockshift; /* log2 of blocksize */ - int blockmask; /* 2^blockshift - 1 */ - int *lba_to_pba; /* logical to physical map */ - int *pba_to_lba; /* physical to logical map */ - int lbact; /* number of available pages */ - int flags; -#define SDDR09_WP 1 /* write protected */ -}; - /* * On my 16MB card, control blocks have size 64 (16 real control bytes, * and 48 junk bytes). In reality of course the card uses 16 control bytes, @@ -249,7 +237,7 @@ struct sddr09_card_info { #define SPARE 0xfffffffe #define UNUSABLE 0xfffffffd -static const int erase_bad_lba_entries = 0; +static int erase_bad_lba_entries = 0; /* send vendor interface command (0x41) */ /* called for requests 0, 1, 8 */ @@ -272,11 +260,8 @@ sddr09_send_command(struct us_data *us, rc = usb_stor_ctrl_transfer(us, pipe, request, requesttype, 0, 0, xfer_data, xfer_len); - switch (rc) { - case USB_STOR_XFER_GOOD: return 0; - case USB_STOR_XFER_STALLED: return -EPIPE; - default: return -EIO; - } + return (rc == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD : + USB_STOR_TRANSPORT_ERROR); } static int @@ -323,12 +308,20 @@ sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) { command[4] = buflen; result = sddr09_send_scsi_command(us, command, 12); - if (result) + if (result != USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("request sense failed\n"); return result; + } result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, sensebuf, buflen, NULL); - return (result == USB_STOR_XFER_GOOD ? 0 : -EIO); + if (result != USB_STOR_XFER_GOOD) { + US_DEBUGP("request sense bulk in failed\n"); + return USB_STOR_TRANSPORT_ERROR; + } else { + US_DEBUGP("request sense worked\n"); + return USB_STOR_TRANSPORT_GOOD; + } } /* @@ -376,7 +369,7 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress, result = sddr09_send_scsi_command(us, command, 12); - if (result) { + if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("Result for send_control in sddr09_read2%d %d\n", x, result); return result; @@ -388,9 +381,9 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress, if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n", x, result); - return -EIO; + return USB_STOR_TRANSPORT_ERROR; } - return 0; + return USB_STOR_TRANSPORT_GOOD; } /* @@ -504,7 +497,7 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) { result = sddr09_send_scsi_command(us, command, 12); - if (result) + if (result != USB_STOR_TRANSPORT_GOOD) US_DEBUGP("Result for send_control in sddr09_erase %d\n", result); @@ -562,7 +555,7 @@ sddr09_writeX(struct us_data *us, result = sddr09_send_scsi_command(us, command, 12); - if (result) { + if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("Result for send_control in sddr09_writeX %d\n", result); return result; @@ -574,9 +567,9 @@ sddr09_writeX(struct us_data *us, if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n", result); - return -EIO; + return USB_STOR_TRANSPORT_ERROR; } - return 0; + return USB_STOR_TRANSPORT_GOOD; } /* erase address, write same address */ @@ -640,7 +633,7 @@ sddr09_read_sg_test_only(struct us_data *us) { result = sddr09_send_scsi_command(us, command, 4*nsg+3); - if (result) { + if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("Result for send_control in sddr09_read_sg %d\n", result); return result; @@ -648,7 +641,7 @@ sddr09_read_sg_test_only(struct us_data *us) { buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO); if (!buf) - return -ENOMEM; + return USB_STOR_TRANSPORT_ERROR; result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, buf, bulklen, NULL); @@ -656,10 +649,10 @@ sddr09_read_sg_test_only(struct us_data *us) { if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n", result); - return -EIO; + return USB_STOR_TRANSPORT_ERROR; } - return 0; + return USB_STOR_TRANSPORT_GOOD; } #endif @@ -688,13 +681,14 @@ sddr09_read_status(struct us_data *us, unsigned char *status) { command[1] = LUNBITS; result = sddr09_send_scsi_command(us, command, 12); - if (result) + if (result != USB_STOR_TRANSPORT_GOOD) return result; result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, 64, NULL); *status = data[0]; - return (result == USB_STOR_XFER_GOOD ? 0 : -EIO); + return (result == USB_STOR_XFER_GOOD ? + USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); } static int @@ -709,13 +703,6 @@ sddr09_read_data(struct us_data *us, unsigned int len, index, offset; int result; - // Figure out the initial LBA and page - lba = address >> info->blockshift; - page = (address & info->blockmask); - maxlba = info->capacity >> (info->pageshift + info->blockshift); - if (lba >= maxlba) - return -EIO; - // Since we only read in one block at a time, we have to create // a bounce buffer and move the data a piece at a time between the // bounce buffer and the actual transfer buffer. @@ -724,13 +711,18 @@ sddr09_read_data(struct us_data *us, buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { printk("sddr09_read_data: Out of memory\n"); - return -ENOMEM; + return USB_STOR_TRANSPORT_ERROR; } + // Figure out the initial LBA and page + lba = address >> info->blockshift; + page = (address & info->blockmask); + maxlba = info->capacity >> (info->pageshift + info->blockshift); + // This could be made much more efficient by checking for // contiguous LBA's. Another exercise left to the student. - result = 0; + result = USB_STOR_TRANSPORT_GOOD; index = offset = 0; while (sectors > 0) { @@ -743,7 +735,7 @@ sddr09_read_data(struct us_data *us, if (lba >= maxlba) { US_DEBUGP("Error: Requested lba %u exceeds " "maximum %u\n", lba, maxlba); - result = -EIO; + result = USB_STOR_TRANSPORT_ERROR; break; } @@ -757,7 +749,7 @@ sddr09_read_data(struct us_data *us, /* This is not really an error. It just means that the block has never been written. - Instead of returning an error + Instead of returning USB_STOR_TRANSPORT_ERROR it is better to return all zero data. */ memset(buffer, 0, len); @@ -772,7 +764,7 @@ sddr09_read_data(struct us_data *us, result = sddr09_read20(us, address>>1, pages, info->pageshift, buffer, 0); - if (result) + if (result != USB_STOR_TRANSPORT_GOOD) break; } @@ -838,7 +830,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, pba = sddr09_find_unused_pba(info, lba); if (!pba) { printk("sddr09_write_lba: Out of unused blocks\n"); - return -ENOSPC; + return USB_STOR_TRANSPORT_ERROR; } info->pba_to_lba[pba] = lba; info->lba_to_pba[lba] = pba; @@ -849,7 +841,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, /* Maybe it is impossible to write to PBA 1. Fake success, but don't do anything. */ printk("sddr09: avoid writing to pba 1\n"); - return 0; + return USB_STOR_TRANSPORT_GOOD; } pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT); @@ -858,7 +850,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, address = (pba << (info->pageshift + info->blockshift)); result = sddr09_read22(us, address>>1, info->blocksize, info->pageshift, blockbuffer, 0); - if (result) + if (result != USB_STOR_TRANSPORT_GOOD) return result; /* check old contents and fill lba */ @@ -905,7 +897,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, { unsigned char status = 0; int result2 = sddr09_read_status(us, &status); - if (result2) + if (result2 != USB_STOR_TRANSPORT_GOOD) US_DEBUGP("sddr09_write_inplace: cannot read status\n"); else if (status != 0xc0) US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n", @@ -928,20 +920,13 @@ sddr09_write_data(struct us_data *us, unsigned int sectors) { struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra; - unsigned int lba, maxlba, page, pages; + unsigned int lba, page, pages; unsigned int pagelen, blocklen; unsigned char *blockbuffer; unsigned char *buffer; unsigned int len, index, offset; int result; - // Figure out the initial LBA and page - lba = address >> info->blockshift; - page = (address & info->blockmask); - maxlba = info->capacity >> (info->pageshift + info->blockshift); - if (lba >= maxlba) - return -EIO; - // blockbuffer is used for reading in the old data, overwriting // with the new data, and performing ECC calculations @@ -953,7 +938,7 @@ sddr09_write_data(struct us_data *us, blockbuffer = kmalloc(blocklen, GFP_NOIO); if (!blockbuffer) { printk("sddr09_write_data: Out of memory\n"); - return -ENOMEM; + return USB_STOR_TRANSPORT_ERROR; } // Since we don't write the user data directly to the device, @@ -965,10 +950,14 @@ sddr09_write_data(struct us_data *us, if (buffer == NULL) { printk("sddr09_write_data: Out of memory\n"); kfree(blockbuffer); - return -ENOMEM; + return USB_STOR_TRANSPORT_ERROR; } - result = 0; + // Figure out the initial LBA and page + lba = address >> info->blockshift; + page = (address & info->blockmask); + + result = USB_STOR_TRANSPORT_GOOD; index = offset = 0; while (sectors > 0) { @@ -978,21 +967,13 @@ sddr09_write_data(struct us_data *us, pages = min(sectors, info->blocksize - page); len = (pages << info->pageshift); - /* Not overflowing capacity? */ - if (lba >= maxlba) { - US_DEBUGP("Error: Requested lba %u exceeds " - "maximum %u\n", lba, maxlba); - result = -EIO; - break; - } - // Get the data from the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, &index, &offset, FROM_XFER_BUF); result = sddr09_write_lba(us, lba, page, pages, buffer, blockbuffer); - if (result) + if (result != USB_STOR_TRANSPORT_GOOD) break; page = 0; @@ -1041,7 +1022,7 @@ sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) { command[1] = LUNBITS; result = sddr09_send_scsi_command(us, command, 12); - if (result) + if (result != USB_STOR_TRANSPORT_GOOD) return result; result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, @@ -1050,7 +1031,8 @@ sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) { for (i = 0; i < 4; i++) deviceID[i] = content[i]; - return (result == USB_STOR_XFER_GOOD ? 0 : -EIO); + return (result == USB_STOR_XFER_GOOD ? + USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); } static int @@ -1059,7 +1041,7 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) { unsigned char status; result = sddr09_read_status(us, &status); - if (result) { + if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("sddr09_get_wp: read_status fails\n"); return result; } @@ -1075,7 +1057,7 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) { if (status & 0x1) US_DEBUGP(" Error"); US_DEBUGP("\n"); - return 0; + return USB_STOR_TRANSPORT_GOOD; } #if 0 @@ -1107,7 +1089,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { result = sddr09_read_deviceID(us, deviceID); - if (result) { + if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("Result of read_deviceID is %d\n", result); printk("sddr09: could not read card info\n"); return NULL; @@ -1218,7 +1200,7 @@ sddr09_read_map(struct us_data *us) { us, address>>1, min(alloc_blocks, numblocks - i), buffer, 0); - if (result) { + if (result != USB_STOR_TRANSPORT_GOOD) { result = -1; goto done; } @@ -1360,53 +1342,29 @@ sddr09_card_info_destructor(void *extra) { kfree(info->pba_to_lba); } -static int -sddr09_common_init(struct us_data *us) { - int result; - - /* set the configuration -- STALL is an acceptable response here */ - if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) { - US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev - ->actconfig->desc.bConfigurationValue); - return -EINVAL; - } - - result = usb_reset_configuration(us->pusb_dev); - US_DEBUGP("Result of usb_reset_configuration is %d\n", result); - if (result == -EPIPE) { - US_DEBUGP("-- stall on control interface\n"); - } else if (result != 0) { - /* it's not a stall, but another error -- time to bail */ - US_DEBUGP("-- Unknown error. Rejecting device\n"); - return -EINVAL; +static void +sddr09_init_card_info(struct us_data *us) { + if (!us->extra) { + us->extra = kmalloc(sizeof(struct sddr09_card_info), GFP_NOIO); + if (us->extra) { + memset(us->extra, 0, sizeof(struct sddr09_card_info)); + us->extra_destructor = sddr09_card_info_destructor; + } } - - us->extra = kzalloc(sizeof(struct sddr09_card_info), GFP_NOIO); - if (!us->extra) - return -ENOMEM; - us->extra_destructor = sddr09_card_info_destructor; - - nand_init_ecc(); - return 0; } - /* * This is needed at a very early stage. If this is not listed in the * unusual devices list but called from here then LUN 0 of the combo reader * is not recognized. But I do not know what precisely these calls do. */ int -usb_stor_sddr09_dpcm_init(struct us_data *us) { +sddr09_init(struct us_data *us) { int result; unsigned char *data = us->iobuf; - result = sddr09_common_init(us); - if (result) - return result; - result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2); - if (result) { + if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("sddr09_init: send_command fails\n"); return result; } @@ -1415,7 +1373,7 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) { // get 07 02 result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2); - if (result) { + if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("sddr09_init: 2nd send_command fails\n"); return result; } @@ -1424,7 +1382,7 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) { // get 07 00 result = sddr09_request_sense(us, data, 18); - if (result == 0 && data[2] != 0) { + if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) { int j; for (j=0; j<18; j++) printk(" %02X", data[j]); @@ -1440,7 +1398,7 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) { // test unit ready - return 0; /* not result */ + return USB_STOR_TRANSPORT_GOOD; /* not result */ } /* @@ -1469,6 +1427,13 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) }; info = (struct sddr09_card_info *)us->extra; + if (!info) { + nand_init_ecc(); + sddr09_init_card_info(us); + info = (struct sddr09_card_info *)us->extra; + if (!info) + return USB_STOR_TRANSPORT_ERROR; + } if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) { /* for a faked command, we have to follow with a faked sense */ @@ -1571,9 +1536,7 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) US_DEBUGP("READ_10: read page %d pagect %d\n", page, pages); - result = sddr09_read_data(us, page, pages); - return (result == 0 ? USB_STOR_TRANSPORT_GOOD : - USB_STOR_TRANSPORT_ERROR); + return sddr09_read_data(us, page, pages); } if (srb->cmnd[0] == WRITE_10) { @@ -1586,9 +1549,7 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) US_DEBUGP("WRITE_10: write page %d pagect %d\n", page, pages); - result = sddr09_write_data(us, page, pages); - return (result == 0 ? USB_STOR_TRANSPORT_GOOD : - USB_STOR_TRANSPORT_ERROR); + return sddr09_write_data(us, page, pages); } /* catch-all for all other commands, except @@ -1614,10 +1575,10 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) US_DEBUGP("SDDR09: Send control for command %s\n", ptr); result = sddr09_send_scsi_command(us, srb->cmnd, 12); - if (result) { + if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("sddr09_transport: sddr09_send_scsi_command " "returns %d\n", result); - return USB_STOR_TRANSPORT_ERROR; + return result; } if (srb->request_bufflen == 0) @@ -1645,10 +1606,3 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -/* - * Initialization routine for the sddr09 subdriver - */ -int -usb_stor_sddr09_init(struct us_data *us) { - return sddr09_common_init(us); -} diff --git a/trunk/drivers/usb/storage/sddr09.h b/trunk/drivers/usb/storage/sddr09.h index c03089a9ec38..c9d78d6188b1 100644 --- a/trunk/drivers/usb/storage/sddr09.h +++ b/trunk/drivers/usb/storage/sddr09.h @@ -31,7 +31,18 @@ extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_sddr09_dpcm_init(struct us_data *us); -extern int usb_stor_sddr09_init(struct us_data *us); +struct sddr09_card_info { + unsigned long capacity; /* Size of card in bytes */ + int pagesize; /* Size of page in bytes */ + int pageshift; /* log2 of pagesize */ + int blocksize; /* Size of block in pages */ + int blockshift; /* log2 of blocksize */ + int blockmask; /* 2^blockshift - 1 */ + int *lba_to_pba; /* logical to physical map */ + int *pba_to_lba; /* physical to logical map */ + int lbact; /* number of available pages */ + int flags; +#define SDDR09_WP 1 /* write protected */ +}; #endif diff --git a/trunk/drivers/usb/storage/transport.h b/trunk/drivers/usb/storage/transport.h index 633a715850a4..0a362cc781ad 100644 --- a/trunk/drivers/usb/storage/transport.h +++ b/trunk/drivers/usb/storage/transport.h @@ -41,8 +41,39 @@ #ifndef _TRANSPORT_H_ #define _TRANSPORT_H_ +#include #include +/* Protocols */ + +#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ +#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ +#define US_PR_BULK 0x50 /* bulk only */ +#ifdef CONFIG_USB_STORAGE_USBAT +#define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */ +#endif +#ifdef CONFIG_USB_STORAGE_SDDR09 +#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ +#endif +#ifdef CONFIG_USB_STORAGE_SDDR55 +#define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */ +#endif +#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ + +#ifdef CONFIG_USB_STORAGE_FREECOM +#define US_PR_FREECOM 0xf1 /* Freecom */ +#endif + +#ifdef CONFIG_USB_STORAGE_DATAFAB +#define US_PR_DATAFAB 0xf2 /* Datafab chipsets */ +#endif + +#ifdef CONFIG_USB_STORAGE_JUMPSHOT +#define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ +#endif + +#define US_PR_DEVICE 0xff /* Use device's value */ + /* * Bulk only data structures */ diff --git a/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index dc301e567cfc..f5f47a34b168 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/drivers/usb/storage/unusual_devs.h @@ -79,6 +79,13 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, US_SC_8070, US_PR_USBAT, init_usbat, 0), #endif +/* Patch submitted by Mihnea-Costin Grigore */ +UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003, + "VIA Technologies Inc.", + "USB 2.0 Card Reader", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Sebastian Kapfer * and Olaf Hering (different bcd's, same vendor/product) * for USB floppies that need the SINGLE_LUN enforcement. @@ -89,13 +96,6 @@ UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -/* Patch submitted by Mihnea-Costin Grigore */ -UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003, - "VIA Technologies Inc.", - "USB 2.0 Card Reader", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_IGNORE_RESIDUE ), - /* Deduced by Jonathan Woithe * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message * always fails and confuses drive. @@ -187,14 +187,6 @@ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), -/* Patch for Nikon coolpix 2000 - * Submitted by Fabien Cosse */ -UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, - "NIKON", - "NIKON DSC E2000", - US_SC_DEVICE, US_PR_DEVICE,NULL, - US_FL_NOT_LOCKABLE ), - /* BENQ DC5330 * Reported by Manuel Fombuena and * Frank Copeland */ @@ -284,14 +276,14 @@ UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, "Sandisk", "ImageMate SDDR09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), + US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, + US_FL_SINGLE_LUN ), /* This entry is from Andries.Brouwer@cwi.nl */ UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, "SCM Microsystems", "eUSB SmartMedia / CompactFlash Adapter", - US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, + US_SC_SCSI, US_PR_DPCM_USB, sddr09_init, 0), #endif @@ -535,13 +527,6 @@ UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, "Silicon Media R/W", US_SC_DEVICE, US_PR_DEVICE, NULL, 0), -#ifdef CONFIG_USB_STORAGE_ALAUDA -UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, - "Fujifilm", - "DPC-R1 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), -#endif - /* Fabrizio Fellini */ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Fujifilm", @@ -688,8 +673,8 @@ UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, "Olympus", "Camedia MAUSB-2", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), + US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, + US_FL_SINGLE_LUN ), #endif /* Reported by Darsen Lu */ @@ -754,8 +739,8 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, "Sandisk", "ImageMate SDDR-09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), + US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, + US_FL_SINGLE_LUN ), #endif #ifdef CONFIG_USB_STORAGE_FREECOM @@ -791,13 +776,6 @@ UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA -UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, - "Olympus", - "MAUSB-10 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), -#endif - #ifdef CONFIG_USB_STORAGE_DATAFAB UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, "Datafab", @@ -1156,27 +1134,3 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, US_SC_SCSI, US_PR_SDDR55, NULL, US_FL_SINGLE_LUN), #endif - -/* Control/Bulk transport for all SubClass values */ -USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR), - -/* Control/Bulk/Interrupt transport for all SubClass values */ -USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR), - -/* Bulk-only transport for all SubClass values */ -USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0), diff --git a/trunk/drivers/usb/storage/usb.c b/trunk/drivers/usb/storage/usb.c index dbcf23980ff1..3847ebed2aa4 100644 --- a/trunk/drivers/usb/storage/usb.c +++ b/trunk/drivers/usb/storage/usb.c @@ -94,9 +94,6 @@ #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA -#include "alauda.h" -#endif /* Some informational data */ MODULE_AUTHOR("Matthew Dharm "); @@ -115,33 +112,49 @@ static atomic_t total_threads = ATOMIC_INIT(0); static DECLARE_COMPLETION(threads_gone); -/* - * The entries in this table correspond, line for line, - * with the entries of us_unusual_dev_list[]. +/* The entries in this table, except for final ones here + * (USB_MASS_STORAGE_CLASS and the empty entry), correspond, + * line for line with the entries of us_unsuaul_dev_list[]. */ -#ifndef CONFIG_USB_LIBUSUAL #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ vendorName, productName,useProtocol, useTransport, \ initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = (USB_US_TYPE_STOR<<24) } +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) } static struct usb_device_id storage_usb_ids [] = { # include "unusual_devs.h" #undef UNUSUAL_DEV -#undef USUAL_DEV + /* Control/Bulk transport for all SubClass values */ + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) }, + + /* Control/Bulk/Interrupt transport for all SubClass values */ + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) }, + + /* Bulk-only transport for all SubClass values */ + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) }, + /* Terminating entry */ { } }; MODULE_DEVICE_TABLE (usb, storage_usb_ids); -#endif /* CONFIG_USB_LIBUSUAL */ /* This is the list of devices we recognize, along with their flag data */ @@ -154,6 +167,7 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); * are free to use as many characters as you like. */ +#undef UNUSUAL_DEV #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ vendor_name, product_name, use_protocol, use_transport, \ init_function, Flags) \ @@ -163,18 +177,53 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); .useProtocol = use_protocol, \ .useTransport = use_transport, \ .initFunction = init_function, \ -} - -#define USUAL_DEV(use_protocol, use_transport, use_type) \ -{ \ - .useProtocol = use_protocol, \ - .useTransport = use_transport, \ + .flags = Flags, \ } static struct us_unusual_dev us_unusual_dev_list[] = { # include "unusual_devs.h" # undef UNUSUAL_DEV -# undef USUAL_DEV + /* Control/Bulk transport for all SubClass values */ + { .useProtocol = US_SC_RBC, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_8020, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_QIC, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_UFI, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_8070, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_SCSI, + .useTransport = US_PR_CB}, + + /* Control/Bulk/Interrupt transport for all SubClass values */ + { .useProtocol = US_SC_RBC, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_8020, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_QIC, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_UFI, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_8070, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_SCSI, + .useTransport = US_PR_CBI}, + + /* Bulk-only transport for all SubClass values */ + { .useProtocol = US_SC_RBC, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_8020, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_QIC, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_UFI, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_8070, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_SCSI, + .useTransport = US_PR_BULK}, /* Terminating entry */ { NULL } @@ -191,8 +240,6 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) down(&us->dev_semaphore); US_DEBUGP("%s\n", __FUNCTION__); - if (us->suspend_resume_hook) - (us->suspend_resume_hook)(us, US_SUSPEND); iface->dev.power.power_state.event = message.event; /* When runtime PM is working, we'll set a flag to indicate @@ -209,8 +256,6 @@ static int storage_resume(struct usb_interface *iface) down(&us->dev_semaphore); US_DEBUGP("%s\n", __FUNCTION__); - if (us->suspend_resume_hook) - (us->suspend_resume_hook)(us, US_RESUME); iface->dev.power.power_state.event = PM_EVENT_ON; up(&us->dev_semaphore); @@ -439,20 +484,14 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf) return 0; } -/* Find an unusual_dev descriptor (always succeeds in the current code) */ -static struct us_unusual_dev *find_unusual(const struct usb_device_id *id) -{ - const int id_index = id - storage_usb_ids; - return &us_unusual_dev_list[id_index]; -} - /* Get the unusual_devs entries and the string descriptors */ -static void get_device_info(struct us_data *us, const struct usb_device_id *id) +static void get_device_info(struct us_data *us, int id_index) { struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = &us->pusb_intf->cur_altsetting->desc; - struct us_unusual_dev *unusual_dev = find_unusual(id); + struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index]; + struct usb_device_id *id = &storage_usb_ids[id_index]; /* Store the entries */ us->unusual_dev = unusual_dev; @@ -462,7 +501,7 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id) us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? idesc->bInterfaceProtocol : unusual_dev->useTransport; - us->flags = USB_US_ORIG_FLAGS(id->driver_info); + us->flags = unusual_dev->flags; /* * This flag is only needed when we're in high-speed, so let's @@ -477,7 +516,7 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id) * from the unusual_devs.h table. */ if (id->idVendor || id->idProduct) { - static const char *msgs[3] = { + static char *msgs[3] = { "an unneeded SubClass entry", "an unneeded Protocol entry", "unneeded SubClass and Protocol entries"}; @@ -490,7 +529,7 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id) if (unusual_dev->useTransport != US_PR_DEVICE && us->protocol == idesc->bInterfaceProtocol) msg += 2; - if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE)) + if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE)) printk(KERN_NOTICE USB_STORAGE "This device " "(%04x,%04x,%04x S %02x P %02x)" " has %s in unusual_devs.h\n" @@ -647,15 +686,6 @@ static int get_protocol(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA - case US_PR_ALAUDA: - us->transport_name = "Alauda Control/Bulk"; - us->transport = alauda_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - default: return -EIO; } @@ -891,12 +921,10 @@ static int storage_probe(struct usb_interface *intf, { struct Scsi_Host *host; struct us_data *us; + const int id_index = id - storage_usb_ids; int result; struct task_struct *th; - if (usb_usual_check_type(id, USB_US_TYPE_STOR)) - return -ENXIO; - US_DEBUGP("USB Mass Storage device detected\n"); /* @@ -929,7 +957,29 @@ static int storage_probe(struct usb_interface *intf, * of the match from the usb_device_id table, so we can find the * corresponding entry in the private table. */ - get_device_info(us, id); + get_device_info(us, id_index); + +#ifdef CONFIG_USB_STORAGE_SDDR09 + if (us->protocol == US_PR_EUSB_SDDR09 || + us->protocol == US_PR_DPCM_USB) { + /* set the configuration -- STALL is an acceptable response here */ + if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) { + US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev + ->actconfig->desc.bConfigurationValue); + goto BadDevice; + } + result = usb_reset_configuration(us->pusb_dev); + + US_DEBUGP("Result of usb_reset_configuration is %d\n", result); + if (result == -EPIPE) { + US_DEBUGP("-- stall on control interface\n"); + } else if (result != 0) { + /* it's not a stall, but another error -- time to bail */ + US_DEBUGP("-- Unknown error. Rejecting device\n"); + goto BadDevice; + } + } +#endif /* Get the transport, protocol, and pipe settings */ result = get_transport(us); @@ -994,6 +1044,7 @@ static void storage_disconnect(struct usb_interface *intf) ***********************************************************************/ static struct usb_driver usb_storage_driver = { + .owner = THIS_MODULE, .name = "usb-storage", .probe = storage_probe, .disconnect = storage_disconnect, @@ -1011,10 +1062,9 @@ static int __init usb_stor_init(void) /* register the driver, return usb_register return code if error */ retval = usb_register(&usb_storage_driver); - if (retval == 0) { + if (retval == 0) printk(KERN_INFO "USB Mass Storage support registered.\n"); - usb_usual_set_present(USB_US_TYPE_STOR); - } + return retval; } @@ -1038,8 +1088,6 @@ static void __exit usb_stor_exit(void) wait_for_completion(&threads_gone); atomic_dec(&total_threads); } - - usb_usual_clear_present(USB_US_TYPE_STOR); } module_init(usb_stor_init); diff --git a/trunk/drivers/usb/storage/usb.h b/trunk/drivers/usb/storage/usb.h index 7259fd1f6b0d..98b09711a739 100644 --- a/trunk/drivers/usb/storage/usb.h +++ b/trunk/drivers/usb/storage/usb.h @@ -45,7 +45,6 @@ #define _USB_H_ #include -#include #include #include #include @@ -64,8 +63,38 @@ struct us_unusual_dev { __u8 useProtocol; __u8 useTransport; int (*initFunction)(struct us_data *); + unsigned int flags; }; +/* + * Static flag definitions. We use this roundabout technique so that the + * proc_info() routine can automatically display a message for each flag. + */ +#define US_DO_ALL_FLAGS \ + US_FLAG(SINGLE_LUN, 0x00000001) \ + /* allow access to only LUN 0 */ \ + US_FLAG(NEED_OVERRIDE, 0x00000002) \ + /* unusual_devs entry is necessary */ \ + US_FLAG(SCM_MULT_TARG, 0x00000004) \ + /* supports multiple targets */ \ + US_FLAG(FIX_INQUIRY, 0x00000008) \ + /* INQUIRY response needs faking */ \ + US_FLAG(FIX_CAPACITY, 0x00000010) \ + /* READ CAPACITY response too big */ \ + US_FLAG(IGNORE_RESIDUE, 0x00000020) \ + /* reported residue is wrong */ \ + US_FLAG(BULK32, 0x00000040) \ + /* Uses 32-byte CBW length */ \ + US_FLAG(NOT_LOCKABLE, 0x00000080) \ + /* PREVENT/ALLOW not supported */ \ + US_FLAG(GO_SLOW, 0x00000100) \ + /* Need delay after Command phase */ \ + US_FLAG(NO_WP_DETECT, 0x00000200) \ + /* Don't check for write-protect */ \ + +#define US_FLAG(name, value) US_FL_##name = value , +enum { US_DO_ALL_FLAGS }; +#undef US_FLAG /* Dynamic flag definitions: used in set_bit() etc. */ #define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */ @@ -93,11 +122,7 @@ struct us_unusual_dev { typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*); typedef int (*trans_reset)(struct us_data*); typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*); -typedef void (*extra_data_destructor)(void *); /* extra data destructor */ -typedef void (*pm_hook)(struct us_data *, int); /* power management hook */ - -#define US_SUSPEND 0 -#define US_RESUME 1 +typedef void (*extra_data_destructor)(void *); /* extra data destructor */ /* we allocate one of these for every device that we remember */ struct us_data { @@ -153,9 +178,6 @@ struct us_data { /* subdriver information */ void *extra; /* Any extra data */ extra_data_destructor extra_destructor;/* extra data destructor */ -#ifdef CONFIG_PM - pm_hook suspend_resume_hook; -#endif }; /* Convert between us_data and the corresponding Scsi_Host */ diff --git a/trunk/drivers/usb/usb-skeleton.c b/trunk/drivers/usb/usb-skeleton.c index 5d02f16b7d0e..6c3a53f8f26c 100644 --- a/trunk/drivers/usb/usb-skeleton.c +++ b/trunk/drivers/usb/usb-skeleton.c @@ -39,15 +39,10 @@ MODULE_DEVICE_TABLE (usb, skel_table); /* Get a minor range for your devices from the usb maintainer */ #define USB_SKEL_MINOR_BASE 192 -/* our private defines. if this grows any larger, use your own .h file */ -#define MAX_TRANSFER ( PAGE_SIZE - 512 ) -#define WRITES_IN_FLIGHT 8 - /* Structure to hold all of our device specific stuff */ struct usb_skel { struct usb_device * udev; /* the usb device for this device */ struct usb_interface * interface; /* the interface for this device */ - struct semaphore limit_sem; /* limiting the number of writes in progress */ unsigned char * bulk_in_buffer; /* the buffer to receive data */ size_t bulk_in_size; /* the size of the receive buffer */ __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ @@ -157,7 +152,6 @@ static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs) /* free up our allocated buffer */ usb_buffer_free(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); - up(&dev->limit_sem); } static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) @@ -166,7 +160,6 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou int retval = 0; struct urb *urb = NULL; char *buf = NULL; - size_t writesize = min(count, (size_t)MAX_TRANSFER); dev = (struct usb_skel *)file->private_data; @@ -174,12 +167,6 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou if (count == 0) goto exit; - /* limit the number of URBs in flight to stop a user from using up all RAM */ - if (down_interruptible(&dev->limit_sem)) { - retval = -ERESTARTSYS; - goto exit; - } - /* create a urb, and a buffer for it, and copy the data to the urb */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { @@ -187,13 +174,13 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou goto error; } - buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma); + buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error; } - if (copy_from_user(buf, user_buffer, writesize)) { + if (copy_from_user(buf, user_buffer, count)) { retval = -EFAULT; goto error; } @@ -201,7 +188,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou /* initialize the urb properly */ usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), - buf, writesize, skel_write_bulk_callback, dev); + buf, count, skel_write_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* send the data out the bulk port */ @@ -215,12 +202,11 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou usb_free_urb(urb); exit: - return writesize; + return count; error: - usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma); + usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); usb_free_urb(urb); - up(&dev->limit_sem); return retval; } @@ -252,13 +238,13 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i int retval = -ENOMEM; /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); + dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { err("Out of memory"); goto error; } + memset(dev, 0x00, sizeof(*dev)); kref_init(&dev->kref); - sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; @@ -344,6 +330,7 @@ static void skel_disconnect(struct usb_interface *interface) } static struct usb_driver skel_driver = { + .owner = THIS_MODULE, .name = "skeleton", .probe = skel_probe, .disconnect = skel_disconnect, diff --git a/trunk/drivers/w1/dscore.c b/trunk/drivers/w1/dscore.c index b9146306df49..15fb250451e5 100644 --- a/trunk/drivers/w1/dscore.c +++ b/trunk/drivers/w1/dscore.c @@ -52,6 +52,7 @@ static int ds_send_control_cmd(struct ds_device *, u16, u16); static struct usb_driver ds_driver = { + .owner = THIS_MODULE, .name = "DS9490R", .probe = ds_probe, .disconnect = ds_disconnect, diff --git a/trunk/fs/compat.c b/trunk/fs/compat.c index 55ac0324aaf1..818634120b69 100644 --- a/trunk/fs/compat.c +++ b/trunk/fs/compat.c @@ -1170,7 +1170,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, } ret = rw_verify_area(type, file, pos, tot_len); - if (ret < 0) + if (ret) goto out; fnv = NULL; diff --git a/trunk/fs/read_write.c b/trunk/fs/read_write.c index df3468a22fea..a091ee4f430d 100644 --- a/trunk/fs/read_write.c +++ b/trunk/fs/read_write.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -183,33 +182,22 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, } #endif -/* - * rw_verify_area doesn't like huge counts. We limit - * them to something that fits in "int" so that others - * won't have to do range checks all the time. - */ -#define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK) int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count) { struct inode *inode; loff_t pos; - if (unlikely((ssize_t) count < 0)) + if (unlikely(count > INT_MAX)) goto Einval; pos = *ppos; if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) goto Einval; inode = file->f_dentry->d_inode; - if (inode->i_flock && MANDATORY_LOCK(inode)) { - int retval = locks_mandatory_area( - read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, - inode, file, pos, count); - if (retval < 0) - return retval; - } - return count > MAX_RW_COUNT ? MAX_RW_COUNT : count; + if (inode->i_flock && MANDATORY_LOCK(inode)) + return locks_mandatory_area(read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, inode, file, pos, count); + return 0; Einval: return -EINVAL; @@ -256,8 +244,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) return -EFAULT; ret = rw_verify_area(READ, file, pos, count); - if (ret >= 0) { - count = ret; + if (!ret) { ret = security_file_permission (file, MAY_READ); if (!ret) { if (file->f_op->read) @@ -308,8 +295,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ return -EFAULT; ret = rw_verify_area(WRITE, file, pos, count); - if (ret >= 0) { - count = ret; + if (!ret) { ret = security_file_permission (file, MAY_WRITE); if (!ret) { if (file->f_op->write) @@ -511,7 +497,7 @@ static ssize_t do_readv_writev(int type, struct file *file, } ret = rw_verify_area(type, file, pos, tot_len); - if (ret < 0) + if (ret) goto out; ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE); if (ret) @@ -667,9 +653,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, if (!(in_file->f_mode & FMODE_PREAD)) goto fput_in; retval = rw_verify_area(READ, in_file, ppos, count); - if (retval < 0) + if (retval) goto fput_in; - count = retval; retval = security_file_permission (in_file, MAY_READ); if (retval) @@ -689,9 +674,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, goto fput_out; out_inode = out_file->f_dentry->d_inode; retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count); - if (retval < 0) + if (retval) goto fput_out; - count = retval; retval = security_file_permission (out_file, MAY_WRITE); if (retval) diff --git a/trunk/include/asm-arm/arch-pxa/ohci.h b/trunk/include/asm-arm/arch-pxa/ohci.h deleted file mode 100644 index 7da89569061e..000000000000 --- a/trunk/include/asm-arm/arch-pxa/ohci.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ASMARM_ARCH_OHCI_H -#define ASMARM_ARCH_OHCI_H - -struct device; - -struct pxaohci_platform_data { - int (*init)(struct device *); - void (*exit)(struct device *); - - int port_mode; -#define PMM_NPS_MODE 1 -#define PMM_GLOBAL_MODE 2 -#define PMM_PERPORT_MODE 3 -}; - -extern void pxa_set_ohci_info(struct pxaohci_platform_data *info); - -#endif diff --git a/trunk/include/linux/cpufreq.h b/trunk/include/linux/cpufreq.h index c31650df9241..d068176b7ad7 100644 --- a/trunk/include/linux/cpufreq.h +++ b/trunk/include/linux/cpufreq.h @@ -256,16 +256,6 @@ int cpufreq_update_policy(unsigned int cpu); /* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */ unsigned int cpufreq_get(unsigned int cpu); -/* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */ -#ifdef CONFIG_CPU_FREQ -unsigned int cpufreq_quick_get(unsigned int cpu); -#else -static inline unsigned int cpufreq_quick_get(unsigned int cpu) -{ - return 0; -} -#endif - /********************************************************************* * CPUFREQ DEFAULT GOVERNOR * diff --git a/trunk/include/linux/pfkeyv2.h b/trunk/include/linux/pfkeyv2.h index 724066778aff..6351c4055ace 100644 --- a/trunk/include/linux/pfkeyv2.h +++ b/trunk/include/linux/pfkeyv2.h @@ -216,6 +216,16 @@ struct sadb_x_nat_t_port { } __attribute__((packed)); /* sizeof(struct sadb_x_nat_t_port) == 8 */ +/* Generic LSM security context */ +struct sadb_x_sec_ctx { + uint16_t sadb_x_sec_len; + uint16_t sadb_x_sec_exttype; + uint8_t sadb_x_ctx_alg; /* LSMs: e.g., selinux == 1 */ + uint8_t sadb_x_ctx_doi; + uint16_t sadb_x_ctx_len; +} __attribute__((packed)); +/* sizeof(struct sadb_sec_ctx) = 8 */ + /* Message types */ #define SADB_RESERVED 0 #define SADB_GETSPI 1 @@ -325,7 +335,8 @@ struct sadb_x_nat_t_port { #define SADB_X_EXT_NAT_T_SPORT 21 #define SADB_X_EXT_NAT_T_DPORT 22 #define SADB_X_EXT_NAT_T_OA 23 -#define SADB_EXT_MAX 23 +#define SADB_X_EXT_SEC_CTX 24 +#define SADB_EXT_MAX 24 /* Identity Extension values */ #define SADB_IDENTTYPE_RESERVED 0 diff --git a/trunk/include/linux/security.h b/trunk/include/linux/security.h index f7e0ae018712..ef753654daa5 100644 --- a/trunk/include/linux/security.h +++ b/trunk/include/linux/security.h @@ -59,6 +59,12 @@ struct sk_buff; struct sock; struct sockaddr; struct socket; +struct flowi; +struct dst_entry; +struct xfrm_selector; +struct xfrm_policy; +struct xfrm_state; +struct xfrm_user_sec_ctx; extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); extern int cap_netlink_recv(struct sk_buff *skb); @@ -788,6 +794,52 @@ struct swap_info_struct; * which is used to copy security attributes between local stream sockets. * @sk_free_security: * Deallocate security structure. + * @sk_getsid: + * Retrieve the LSM-specific sid for the sock to enable caching of network + * authorizations. + * + * Security hooks for XFRM operations. + * + * @xfrm_policy_alloc_security: + * @xp contains the xfrm_policy being added to Security Policy Database + * used by the XFRM system. + * @sec_ctx contains the security context information being provided by + * the user-level policy update program (e.g., setkey). + * Allocate a security structure to the xp->selector.security field. + * The security field is initialized to NULL when the xfrm_policy is + * allocated. + * Return 0 if operation was successful (memory to allocate, legal context) + * @xfrm_policy_clone_security: + * @old contains an existing xfrm_policy in the SPD. + * @new contains a new xfrm_policy being cloned from old. + * Allocate a security structure to the new->selector.security field + * that contains the information from the old->selector.security field. + * Return 0 if operation was successful (memory to allocate). + * @xfrm_policy_free_security: + * @xp contains the xfrm_policy + * Deallocate xp->selector.security. + * @xfrm_state_alloc_security: + * @x contains the xfrm_state being added to the Security Association + * Database by the XFRM system. + * @sec_ctx contains the security context information being provided by + * the user-level SA generation program (e.g., setkey or racoon). + * Allocate a security structure to the x->sel.security field. The + * security field is initialized to NULL when the xfrm_state is + * allocated. + * Return 0 if operation was successful (memory to allocate, legal context). + * @xfrm_state_free_security: + * @x contains the xfrm_state. + * Deallocate x>sel.security. + * @xfrm_policy_lookup: + * @xp contains the xfrm_policy for which the access control is being + * checked. + * @sk_sid contains the sock security label that is used to authorize + * access to the policy xp. + * @dir contains the direction of the flow (input or output). + * Check permission when a sock selects a xfrm_policy for processing + * XFRMs on a packet. The hook is called when selecting either a + * per-socket policy or a generic xfrm policy. + * Return 0 if permission is granted. * * Security hooks affecting all Key Management operations * @@ -1237,8 +1289,18 @@ struct security_operations { int (*socket_getpeersec) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len); int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); void (*sk_free_security) (struct sock *sk); + unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir); #endif /* CONFIG_SECURITY_NETWORK */ +#ifdef CONFIG_SECURITY_NETWORK_XFRM + int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); + int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new); + void (*xfrm_policy_free_security) (struct xfrm_policy *xp); + int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); + void (*xfrm_state_free_security) (struct xfrm_state *x); + int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 sk_sid, u8 dir); +#endif /* CONFIG_SECURITY_NETWORK_XFRM */ + /* key management security hooks */ #ifdef CONFIG_KEYS int (*key_alloc)(struct key *key); @@ -2679,6 +2741,11 @@ static inline void security_sk_free(struct sock *sk) { return security_ops->sk_free_security(sk); } + +static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) +{ + return security_ops->sk_getsid(sk, fl, dir); +} #else /* CONFIG_SECURITY_NETWORK */ static inline int security_unix_stream_connect(struct socket * sock, struct socket * other, @@ -2795,8 +2862,73 @@ static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority) static inline void security_sk_free(struct sock *sk) { } + +static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) +{ + return 0; +} #endif /* CONFIG_SECURITY_NETWORK */ +#ifdef CONFIG_SECURITY_NETWORK_XFRM +static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) +{ + return security_ops->xfrm_policy_alloc_security(xp, sec_ctx); +} + +static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) +{ + return security_ops->xfrm_policy_clone_security(old, new); +} + +static inline void security_xfrm_policy_free(struct xfrm_policy *xp) +{ + security_ops->xfrm_policy_free_security(xp); +} + +static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) +{ + return security_ops->xfrm_state_alloc_security(x, sec_ctx); +} + +static inline void security_xfrm_state_free(struct xfrm_state *x) +{ + security_ops->xfrm_state_free_security(x); +} + +static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) +{ + return security_ops->xfrm_policy_lookup(xp, sk_sid, dir); +} +#else /* CONFIG_SECURITY_NETWORK_XFRM */ +static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) +{ + return 0; +} + +static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) +{ + return 0; +} + +static inline void security_xfrm_policy_free(struct xfrm_policy *xp) +{ +} + +static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) +{ + return 0; +} + +static inline void security_xfrm_state_free(struct xfrm_state *x) +{ +} + +static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) +{ + return 0; +} +#endif /* CONFIG_SECURITY_NETWORK_XFRM */ + #ifdef CONFIG_KEYS #ifdef CONFIG_SECURITY static inline int security_key_alloc(struct key *key) diff --git a/trunk/include/linux/usb.h b/trunk/include/linux/usb.h index e59d1bd52d4f..d81b050e5955 100644 --- a/trunk/include/linux/usb.h +++ b/trunk/include/linux/usb.h @@ -329,6 +329,8 @@ struct usb_device { struct usb_tt *tt; /* low/full speed dev, highspeed hub */ int ttport; /* device port on that tt hub */ + struct semaphore serialize; + unsigned int toggle[2]; /* one bit for each endpoint * ([0] = IN, [1] = OUT) */ @@ -347,9 +349,6 @@ struct usb_device { char **rawdescriptors; /* Raw descriptors for each config */ - unsigned short bus_mA; /* Current available from the bus */ - u8 portnum; /* Parent port number (origin 1) */ - int have_langid; /* whether string_langid is valid */ int string_langid; /* language ID for strings */ @@ -378,12 +377,11 @@ struct usb_device { extern struct usb_device *usb_get_dev(struct usb_device *dev); extern void usb_put_dev(struct usb_device *dev); -/* USB device locking */ -#define usb_lock_device(udev) down(&(udev)->dev.sem) -#define usb_unlock_device(udev) up(&(udev)->dev.sem) -#define usb_trylock_device(udev) down_trylock(&(udev)->dev.sem) +extern void usb_lock_device(struct usb_device *udev); +extern int usb_trylock_device(struct usb_device *udev); extern int usb_lock_device_for_reset(struct usb_device *udev, struct usb_interface *iface); +extern void usb_unlock_device(struct usb_device *udev); /* USB port reset for device reinitialization */ extern int usb_reset_device(struct usb_device *dev); @@ -531,13 +529,10 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, /* ----------------------------------------------------------------------- */ -struct usb_dynids { - spinlock_t lock; - struct list_head list; -}; - /** * struct usb_driver - identifies USB driver to usbcore + * @owner: Pointer to the module owner of this driver; initialize + * it using THIS_MODULE. * @name: The driver name should be unique among USB drivers, * and should normally be the same as the module name. * @probe: Called to see if the driver is willing to manage a particular @@ -558,11 +553,7 @@ struct usb_dynids { * @id_table: USB drivers use ID table to support hotplugging. * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set * or your driver's probe function will never get called. - * @dynids: used internally to hold the list of dynamically added device - * ids for this driver. * @driver: the driver model core driver structure. - * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be - * added to this driver by preventing the sysfs file from being created. * * USB drivers must provide a name, probe() and disconnect() methods, * and an id_table. Other driver fields are optional. @@ -580,6 +571,8 @@ struct usb_dynids { * them as necessary, and blocking until the unlinks complete). */ struct usb_driver { + struct module *owner; + const char *name; int (*probe) (struct usb_interface *intf, @@ -595,9 +588,7 @@ struct usb_driver { const struct usb_device_id *id_table; - struct usb_dynids dynids; struct device_driver driver; - unsigned int no_dynamic_id:1; }; #define to_usb_driver(d) container_of(d, struct usb_driver, driver) @@ -623,11 +614,7 @@ struct usb_class_driver { * use these in module_init()/module_exit() * and don't forget MODULE_DEVICE_TABLE(usb, ...) */ -int usb_register_driver(struct usb_driver *, struct module *); -static inline int usb_register(struct usb_driver *driver) -{ - return usb_register_driver(driver, THIS_MODULE); -} +extern int usb_register(struct usb_driver *); extern void usb_deregister(struct usb_driver *); extern int usb_register_dev(struct usb_interface *intf, diff --git a/trunk/include/linux/usb_usual.h b/trunk/include/linux/usb_usual.h deleted file mode 100644 index b2d08984a9f7..000000000000 --- a/trunk/include/linux/usb_usual.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Interface to the libusual. - * - * Copyright (c) 2005 Pete Zaitcev - * Copyright (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) - * Copyright (c) 1999 Michael Gee (michael@linuxspecific.com) - */ - -#ifndef __LINUX_USB_USUAL_H -#define __LINUX_USB_USUAL_H - -#include - -/* We should do this for cleanliness... But other usb_foo.h do not do this. */ -/* #include */ - -/* - * The flags field, which we store in usb_device_id.driver_info. - * It is compatible with the old usb-storage flags in lower 24 bits. - */ - -/* - * Static flag definitions. We use this roundabout technique so that the - * proc_info() routine can automatically display a message for each flag. - */ -#define US_DO_ALL_FLAGS \ - US_FLAG(SINGLE_LUN, 0x00000001) \ - /* allow access to only LUN 0 */ \ - US_FLAG(NEED_OVERRIDE, 0x00000002) \ - /* unusual_devs entry is necessary */ \ - US_FLAG(SCM_MULT_TARG, 0x00000004) \ - /* supports multiple targets */ \ - US_FLAG(FIX_INQUIRY, 0x00000008) \ - /* INQUIRY response needs faking */ \ - US_FLAG(FIX_CAPACITY, 0x00000010) \ - /* READ CAPACITY response too big */ \ - US_FLAG(IGNORE_RESIDUE, 0x00000020) \ - /* reported residue is wrong */ \ - US_FLAG(BULK32, 0x00000040) \ - /* Uses 32-byte CBW length */ \ - US_FLAG(NOT_LOCKABLE, 0x00000080) \ - /* PREVENT/ALLOW not supported */ \ - US_FLAG(GO_SLOW, 0x00000100) \ - /* Need delay after Command phase */ \ - US_FLAG(NO_WP_DETECT, 0x00000200) \ - /* Don't check for write-protect */ \ - -#define US_FLAG(name, value) US_FL_##name = value , -enum { US_DO_ALL_FLAGS }; -#undef US_FLAG - -/* - * The bias field for libusual and friends. - */ -#define USB_US_TYPE_NONE 0 -#define USB_US_TYPE_STOR 1 /* usb-storage */ -#define USB_US_TYPE_UB 2 /* ub */ - -#define USB_US_TYPE(flags) (((flags) >> 24) & 0xFF) -#define USB_US_ORIG_FLAGS(flags) ((flags) & 0x00FFFFFF) - -/* - * This is probably not the best place to keep these constants, conceptually. - * But it's the only header included into all places which need them. - */ - -/* Sub Classes */ - -#define US_SC_RBC 0x01 /* Typically, flash devices */ -#define US_SC_8020 0x02 /* CD-ROM */ -#define US_SC_QIC 0x03 /* QIC-157 Tapes */ -#define US_SC_UFI 0x04 /* Floppy */ -#define US_SC_8070 0x05 /* Removable media */ -#define US_SC_SCSI 0x06 /* Transparent */ -#define US_SC_ISD200 0x07 /* ISD200 ATA */ -#define US_SC_MIN US_SC_RBC -#define US_SC_MAX US_SC_ISD200 - -#define US_SC_DEVICE 0xff /* Use device's value */ - -/* Protocols */ - -#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ -#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ -#define US_PR_BULK 0x50 /* bulk only */ -#ifdef CONFIG_USB_STORAGE_USBAT -#define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */ -#endif -#ifdef CONFIG_USB_STORAGE_SDDR09 -#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ -#endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -#define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */ -#endif -#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ -#ifdef CONFIG_USB_STORAGE_FREECOM -#define US_PR_FREECOM 0xf1 /* Freecom */ -#endif -#ifdef CONFIG_USB_STORAGE_DATAFAB -#define US_PR_DATAFAB 0xf2 /* Datafab chipsets */ -#endif -#ifdef CONFIG_USB_STORAGE_JUMPSHOT -#define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ -#endif -#ifdef CONFIG_USB_STORAGE_ALAUDA -#define US_PR_ALAUDA 0xf4 /* Alauda chipsets */ -#endif - -#define US_PR_DEVICE 0xff /* Use device's value */ - -/* - */ -#ifdef CONFIG_USB_LIBUSUAL - -extern struct usb_device_id storage_usb_ids[]; -extern void usb_usual_set_present(int type); -extern void usb_usual_clear_present(int type); -extern int usb_usual_check_type(const struct usb_device_id *, int type); -#else - -#define usb_usual_set_present(t) do { } while(0) -#define usb_usual_clear_present(t) do { } while(0) -#define usb_usual_check_type(id, t) (0) -#endif /* CONFIG_USB_LIBUSUAL */ - -#endif /* __LINUX_USB_USUAL_H */ diff --git a/trunk/include/linux/xfrm.h b/trunk/include/linux/xfrm.h index 0fb077d68441..82fbb758e28f 100644 --- a/trunk/include/linux/xfrm.h +++ b/trunk/include/linux/xfrm.h @@ -27,6 +27,22 @@ struct xfrm_id __u8 proto; }; +struct xfrm_sec_ctx { + __u8 ctx_doi; + __u8 ctx_alg; + __u16 ctx_len; + __u32 ctx_sid; + char ctx_str[0]; +}; + +/* Security Context Domains of Interpretation */ +#define XFRM_SC_DOI_RESERVED 0 +#define XFRM_SC_DOI_LSM 1 + +/* Security Context Algorithms */ +#define XFRM_SC_ALG_RESERVED 0 +#define XFRM_SC_ALG_SELINUX 1 + /* Selector, used as selector both on policy rules (SPD) and SAs. */ struct xfrm_selector @@ -146,6 +162,18 @@ enum { #define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE) +/* + * Generic LSM security context for comunicating to user space + * NOTE: Same format as sadb_x_sec_ctx + */ +struct xfrm_user_sec_ctx { + __u16 len; + __u16 exttype; + __u8 ctx_alg; /* LSMs: e.g., selinux == 1 */ + __u8 ctx_doi; + __u16 ctx_len; +}; + struct xfrm_user_tmpl { struct xfrm_id id; __u16 family; @@ -176,6 +204,7 @@ enum xfrm_attr_type_t { XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */ XFRMA_SA, XFRMA_POLICY, + XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */ __XFRMA_MAX #define XFRMA_MAX (__XFRMA_MAX - 1) diff --git a/trunk/include/net/flow.h b/trunk/include/net/flow.h index 9a5c94b1a0ec..ec7eb86eb203 100644 --- a/trunk/include/net/flow.h +++ b/trunk/include/net/flow.h @@ -84,11 +84,12 @@ struct flowi { #define FLOW_DIR_OUT 1 #define FLOW_DIR_FWD 2 -typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir, +struct sock; +typedef void (*flow_resolve_t)(struct flowi *key, u32 sk_sid, u16 family, u8 dir, void **objp, atomic_t **obj_refp); -extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, - flow_resolve_t resolver); +extern void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir, + flow_resolve_t resolver); extern void flow_cache_flush(void); extern atomic_t flow_cache_genid; diff --git a/trunk/include/net/xfrm.h b/trunk/include/net/xfrm.h index 1cdb87912137..487abca3ca6f 100644 --- a/trunk/include/net/xfrm.h +++ b/trunk/include/net/xfrm.h @@ -144,6 +144,9 @@ struct xfrm_state * transformer. */ struct xfrm_type *type; + /* Security context */ + struct xfrm_sec_ctx *security; + /* Private data of this transformer, format is opaque, * interpreted by xfrm_type methods. */ void *data; @@ -298,6 +301,7 @@ struct xfrm_policy __u8 flags; __u8 dead; __u8 xfrm_nr; + struct xfrm_sec_ctx *security; struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; }; @@ -510,6 +514,25 @@ xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, return 0; } +#ifdef CONFIG_SECURITY_NETWORK_XFRM +/* If neither has a context --> match + * Otherwise, both must have a context and the sids, doi, alg must match + */ +static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2) +{ + return ((!s1 && !s2) || + (s1 && s2 && + (s1->ctx_sid == s2->ctx_sid) && + (s1->ctx_doi == s2->ctx_doi) && + (s1->ctx_alg == s2->ctx_alg))); +} +#else +static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2) +{ + return 1; +} +#endif + /* A struct encoding bundle of transformations to apply to some set of flow. * * dst->child points to the next element of bundle. @@ -878,8 +901,8 @@ static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsig struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp); extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); -struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, - int delete); +struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel, + struct xfrm_sec_ctx *ctx, int delete); struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete); void xfrm_policy_flush(void); u32 xfrm_get_acqseq(void); diff --git a/trunk/net/core/flow.c b/trunk/net/core/flow.c index 7e95b39de9fd..c4f25385029f 100644 --- a/trunk/net/core/flow.c +++ b/trunk/net/core/flow.c @@ -23,6 +23,7 @@ #include #include #include +#include struct flow_cache_entry { struct flow_cache_entry *next; @@ -30,6 +31,7 @@ struct flow_cache_entry { u8 dir; struct flowi key; u32 genid; + u32 sk_sid; void *object; atomic_t *object_ref; }; @@ -162,7 +164,7 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2) return 0; } -void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, +void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir, flow_resolve_t resolver) { struct flow_cache_entry *fle, **head; @@ -186,6 +188,7 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, for (fle = *head; fle; fle = fle->next) { if (fle->family == family && fle->dir == dir && + fle->sk_sid == sk_sid && flow_key_compare(key, &fle->key) == 0) { if (fle->genid == atomic_read(&flow_cache_genid)) { void *ret = fle->object; @@ -210,6 +213,7 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, *head = fle; fle->family = family; fle->dir = dir; + fle->sk_sid = sk_sid; memcpy(&fle->key, key, sizeof(*key)); fle->object = NULL; flow_count(cpu)++; @@ -221,7 +225,7 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, void *obj; atomic_t *obj_ref; - resolver(key, family, dir, &obj, &obj_ref); + resolver(key, sk_sid, family, dir, &obj, &obj_ref); if (fle) { fle->genid = atomic_read(&flow_cache_genid); diff --git a/trunk/net/key/af_key.c b/trunk/net/key/af_key.c index 39031684b65c..d32f7791f1e4 100644 --- a/trunk/net/key/af_key.c +++ b/trunk/net/key/af_key.c @@ -336,6 +336,7 @@ static u8 sadb_ext_min_len[] = { [SADB_X_EXT_NAT_T_SPORT] = (u8) sizeof(struct sadb_x_nat_t_port), [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), + [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), }; /* Verify sadb_address_{len,prefixlen} against sa_family. */ @@ -383,6 +384,55 @@ static int verify_address_len(void *p) return 0; } +static inline int pfkey_sec_ctx_len(struct sadb_x_sec_ctx *sec_ctx) +{ + int len = 0; + + len += sizeof(struct sadb_x_sec_ctx); + len += sec_ctx->sadb_x_ctx_len; + len += sizeof(uint64_t) - 1; + len /= sizeof(uint64_t); + + return len; +} + +static inline int verify_sec_ctx_len(void *p) +{ + struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p; + int len; + + if (sec_ctx->sadb_x_ctx_len > PAGE_SIZE) + return -EINVAL; + + len = pfkey_sec_ctx_len(sec_ctx); + + if (sec_ctx->sadb_x_sec_len != len) + return -EINVAL; + + return 0; +} + +static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(struct sadb_x_sec_ctx *sec_ctx) +{ + struct xfrm_user_sec_ctx *uctx = NULL; + int ctx_size = sec_ctx->sadb_x_ctx_len; + + uctx = kmalloc((sizeof(*uctx)+ctx_size), GFP_KERNEL); + + if (!uctx) + return NULL; + + uctx->len = pfkey_sec_ctx_len(sec_ctx); + uctx->exttype = sec_ctx->sadb_x_sec_exttype; + uctx->ctx_doi = sec_ctx->sadb_x_ctx_doi; + uctx->ctx_alg = sec_ctx->sadb_x_ctx_alg; + uctx->ctx_len = sec_ctx->sadb_x_ctx_len; + memcpy(uctx + 1, sec_ctx + 1, + uctx->ctx_len); + + return uctx; +} + static int present_and_same_family(struct sadb_address *src, struct sadb_address *dst) { @@ -438,6 +488,10 @@ static int parse_exthdrs(struct sk_buff *skb, struct sadb_msg *hdr, void **ext_h if (verify_address_len(p)) return -EINVAL; } + if (ext_type == SADB_X_EXT_SEC_CTX) { + if (verify_sec_ctx_len(p)) + return -EINVAL; + } ext_hdrs[ext_type-1] = p; } p += ext_len; @@ -586,6 +640,9 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, struct sadb_key *key; struct sadb_x_sa2 *sa2; struct sockaddr_in *sin; + struct sadb_x_sec_ctx *sec_ctx; + struct xfrm_sec_ctx *xfrm_ctx; + int ctx_size = 0; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct sockaddr_in6 *sin6; #endif @@ -609,6 +666,12 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, sizeof(struct sadb_address)*2 + sockaddr_size*2 + sizeof(struct sadb_x_sa2); + + if ((xfrm_ctx = x->security)) { + ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len); + size += sizeof(struct sadb_x_sec_ctx) + ctx_size; + } + /* identity & sensitivity */ if ((x->props.family == AF_INET && @@ -899,6 +962,20 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, n_port->sadb_x_nat_t_port_reserved = 0; } + /* security context */ + if (xfrm_ctx) { + sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, + sizeof(struct sadb_x_sec_ctx) + ctx_size); + sec_ctx->sadb_x_sec_len = + (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t); + sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX; + sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi; + sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg; + sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len; + memcpy(sec_ctx + 1, xfrm_ctx->ctx_str, + xfrm_ctx->ctx_len); + } + return skb; } @@ -909,6 +986,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, struct sadb_lifetime *lifetime; struct sadb_sa *sa; struct sadb_key *key; + struct sadb_x_sec_ctx *sec_ctx; uint16_t proto; int err; @@ -993,6 +1071,21 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, x->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime; x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime; } + + sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; + if (sec_ctx != NULL) { + struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); + + if (!uctx) + goto out; + + err = security_xfrm_state_alloc(x, uctx); + kfree(uctx); + + if (err) + goto out; + } + key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1]; if (sa->sadb_sa_auth) { int keysize = 0; @@ -1720,6 +1813,18 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol) return 0; } +static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp) +{ + struct xfrm_sec_ctx *xfrm_ctx = xp->security; + + if (xfrm_ctx) { + int len = sizeof(struct sadb_x_sec_ctx); + len += xfrm_ctx->ctx_len; + return PFKEY_ALIGN8(len); + } + return 0; +} + static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) { int sockaddr_size = pfkey_sockaddr_size(xp->family); @@ -1733,7 +1838,8 @@ static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) (sockaddr_size * 2) + sizeof(struct sadb_x_policy) + (xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) + - (socklen * 2))); + (socklen * 2))) + + pfkey_xfrm_policy2sec_ctx_size(xp); } static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp) @@ -1757,6 +1863,8 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i struct sadb_lifetime *lifetime; struct sadb_x_policy *pol; struct sockaddr_in *sin; + struct sadb_x_sec_ctx *sec_ctx; + struct xfrm_sec_ctx *xfrm_ctx; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct sockaddr_in6 *sin6; #endif @@ -1941,6 +2049,21 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i } } } + + /* security context */ + if ((xfrm_ctx = xp->security)) { + int ctx_size = pfkey_xfrm_policy2sec_ctx_size(xp); + + sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, ctx_size); + sec_ctx->sadb_x_sec_len = ctx_size / sizeof(uint64_t); + sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX; + sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi; + sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg; + sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len; + memcpy(sec_ctx + 1, xfrm_ctx->ctx_str, + xfrm_ctx->ctx_len); + } + hdr->sadb_msg_len = size / sizeof(uint64_t); hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); } @@ -1976,12 +2099,13 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) { - int err; + int err = 0; struct sadb_lifetime *lifetime; struct sadb_address *sa; struct sadb_x_policy *pol; struct xfrm_policy *xp; struct km_event c; + struct sadb_x_sec_ctx *sec_ctx; if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || @@ -2028,6 +2152,22 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h if (xp->selector.dport) xp->selector.dport_mask = ~0; + sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; + if (sec_ctx != NULL) { + struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); + + if (!uctx) { + err = -ENOBUFS; + goto out; + } + + err = security_xfrm_policy_alloc(xp, uctx); + kfree(uctx); + + if (err) + goto out; + } + xp->lft.soft_byte_limit = XFRM_INF; xp->lft.hard_byte_limit = XFRM_INF; xp->lft.soft_packet_limit = XFRM_INF; @@ -2051,10 +2191,9 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp, hdr->sadb_msg_type != SADB_X_SPDUPDATE); - if (err) { - kfree(xp); - return err; - } + + if (err) + goto out; if (hdr->sadb_msg_type == SADB_X_SPDUPDATE) c.event = XFRM_MSG_UPDPOLICY; @@ -2069,6 +2208,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h return 0; out: + security_xfrm_policy_free(xp); kfree(xp); return err; } @@ -2078,9 +2218,10 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg int err; struct sadb_address *sa; struct sadb_x_policy *pol; - struct xfrm_policy *xp; + struct xfrm_policy *xp, tmp; struct xfrm_selector sel; struct km_event c; + struct sadb_x_sec_ctx *sec_ctx; if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || @@ -2109,7 +2250,24 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg if (sel.dport) sel.dport_mask = ~0; - xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &sel, 1); + sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; + memset(&tmp, 0, sizeof(struct xfrm_policy)); + + if (sec_ctx != NULL) { + struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); + + if (!uctx) + return -ENOMEM; + + err = security_xfrm_policy_alloc(&tmp, uctx); + kfree(uctx); + + if (err) + return err; + } + + xp = xfrm_policy_bysel_ctx(pol->sadb_x_policy_dir-1, &sel, tmp.security, 1); + security_xfrm_policy_free(&tmp); if (xp == NULL) return -ENOENT; @@ -2660,6 +2818,7 @@ static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt, { struct xfrm_policy *xp; struct sadb_x_policy *pol = (struct sadb_x_policy*)data; + struct sadb_x_sec_ctx *sec_ctx; switch (family) { case AF_INET: @@ -2709,10 +2868,32 @@ static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt, (*dir = parse_ipsecrequests(xp, pol)) < 0) goto out; + /* security context too */ + if (len >= (pol->sadb_x_policy_len*8 + + sizeof(struct sadb_x_sec_ctx))) { + char *p = (char *)pol; + struct xfrm_user_sec_ctx *uctx; + + p += pol->sadb_x_policy_len*8; + sec_ctx = (struct sadb_x_sec_ctx *)p; + if (len < pol->sadb_x_policy_len*8 + + sec_ctx->sadb_x_sec_len) + goto out; + if ((*dir = verify_sec_ctx_len(p))) + goto out; + uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); + *dir = security_xfrm_policy_alloc(xp, uctx); + kfree(uctx); + + if (*dir) + goto out; + } + *dir = pol->sadb_x_policy_dir-1; return xp; out: + security_xfrm_policy_free(xp); kfree(xp); return NULL; } diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index d19e274b9c4a..64a447375fdb 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -10,7 +10,7 @@ * YOSHIFUJI Hideaki * Split up af-specific portion * Derek Atkins Add the post_input processor - * + * */ #include @@ -256,6 +256,7 @@ void __xfrm_policy_destroy(struct xfrm_policy *policy) if (del_timer(&policy->timer)) BUG(); + security_xfrm_policy_free(policy); kfree(policy); } EXPORT_SYMBOL(__xfrm_policy_destroy); @@ -350,7 +351,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) write_lock_bh(&xfrm_policy_lock); for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { - if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0) { + if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0 && + xfrm_sec_ctx_match(pol->security, policy->security)) { if (excl) { write_unlock_bh(&xfrm_policy_lock); return -EEXIST; @@ -416,14 +418,15 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) } EXPORT_SYMBOL(xfrm_policy_insert); -struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, - int delete) +struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel, + struct xfrm_sec_ctx *ctx, int delete) { struct xfrm_policy *pol, **p; write_lock_bh(&xfrm_policy_lock); for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { - if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) { + if ((memcmp(sel, &pol->selector, sizeof(*sel)) == 0) && + (xfrm_sec_ctx_match(ctx, pol->security))) { xfrm_pol_hold(pol); if (delete) *p = pol->next; @@ -438,7 +441,7 @@ struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, } return pol; } -EXPORT_SYMBOL(xfrm_policy_bysel); +EXPORT_SYMBOL(xfrm_policy_bysel_ctx); struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete) { @@ -519,7 +522,7 @@ EXPORT_SYMBOL(xfrm_policy_walk); /* Find policy to apply to this flow. */ -static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, +static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir, void **objp, atomic_t **obj_refp) { struct xfrm_policy *pol; @@ -533,9 +536,12 @@ static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, continue; match = xfrm_selector_match(sel, fl, family); + if (match) { - xfrm_pol_hold(pol); - break; + if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) { + xfrm_pol_hold(pol); + break; + } } } read_unlock_bh(&xfrm_policy_lock); @@ -543,15 +549,37 @@ static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, *obj_refp = &pol->refcnt; } -static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl) +static inline int policy_to_flow_dir(int dir) +{ + if (XFRM_POLICY_IN == FLOW_DIR_IN && + XFRM_POLICY_OUT == FLOW_DIR_OUT && + XFRM_POLICY_FWD == FLOW_DIR_FWD) + return dir; + switch (dir) { + default: + case XFRM_POLICY_IN: + return FLOW_DIR_IN; + case XFRM_POLICY_OUT: + return FLOW_DIR_OUT; + case XFRM_POLICY_FWD: + return FLOW_DIR_FWD; + }; +} + +static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl, u32 sk_sid) { struct xfrm_policy *pol; read_lock_bh(&xfrm_policy_lock); if ((pol = sk->sk_policy[dir]) != NULL) { - int match = xfrm_selector_match(&pol->selector, fl, + int match = xfrm_selector_match(&pol->selector, fl, sk->sk_family); + int err = 0; + if (match) + err = security_xfrm_policy_lookup(pol, sk_sid, policy_to_flow_dir(dir)); + + if (match && !err) xfrm_pol_hold(pol); else pol = NULL; @@ -624,6 +652,10 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) if (newp) { newp->selector = old->selector; + if (security_xfrm_policy_clone(old, newp)) { + kfree(newp); + return NULL; /* ENOMEM */ + } newp->lft = old->lft; newp->curlft = old->curlft; newp->action = old->action; @@ -735,22 +767,6 @@ xfrm_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx, return err; } -static inline int policy_to_flow_dir(int dir) -{ - if (XFRM_POLICY_IN == FLOW_DIR_IN && - XFRM_POLICY_OUT == FLOW_DIR_OUT && - XFRM_POLICY_FWD == FLOW_DIR_FWD) - return dir; - switch (dir) { - default: - case XFRM_POLICY_IN: - return FLOW_DIR_IN; - case XFRM_POLICY_OUT: - return FLOW_DIR_OUT; - case XFRM_POLICY_FWD: - return FLOW_DIR_FWD; - }; -} static int stale_bundle(struct dst_entry *dst); @@ -769,19 +785,20 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, int err; u32 genid; u16 family = dst_orig->ops->family; + u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); + u32 sk_sid = security_sk_sid(sk, fl, dir); restart: genid = atomic_read(&flow_cache_genid); policy = NULL; if (sk && sk->sk_policy[1]) - policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); + policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid); if (!policy) { /* To accelerate a bit... */ if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) return 0; - policy = flow_cache_lookup(fl, family, - policy_to_flow_dir(XFRM_POLICY_OUT), + policy = flow_cache_lookup(fl, sk_sid, family, dir, xfrm_policy_lookup); } @@ -962,16 +979,20 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, { struct xfrm_policy *pol; struct flowi fl; + u8 fl_dir = policy_to_flow_dir(dir); + u32 sk_sid; if (_decode_session(skb, &fl, family) < 0) return 0; + sk_sid = security_sk_sid(sk, &fl, fl_dir); + /* First, check used SA against their selectors. */ if (skb->sp) { int i; for (i=skb->sp->len-1; i>=0; i--) { - struct sec_decap_state *xvec = &(skb->sp->x[i]); + struct sec_decap_state *xvec = &(skb->sp->x[i]); if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family)) return 0; @@ -986,11 +1007,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, pol = NULL; if (sk && sk->sk_policy[dir]) - pol = xfrm_sk_policy_lookup(sk, dir, &fl); + pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid); if (!pol) - pol = flow_cache_lookup(&fl, family, - policy_to_flow_dir(dir), + pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir, xfrm_policy_lookup); if (!pol) diff --git a/trunk/net/xfrm/xfrm_state.c b/trunk/net/xfrm/xfrm_state.c index 479effc97666..e12d0be5f976 100644 --- a/trunk/net/xfrm/xfrm_state.c +++ b/trunk/net/xfrm/xfrm_state.c @@ -10,7 +10,7 @@ * Split up af-specific functions * Derek Atkins * Add UDP Encapsulation - * + * */ #include @@ -70,6 +70,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) x->type->destructor(x); xfrm_put_type(x->type); } + security_xfrm_state_free(x); kfree(x); } @@ -343,7 +344,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, selector. */ if (x->km.state == XFRM_STATE_VALID) { - if (!xfrm_selector_match(&x->sel, fl, family)) + if (!xfrm_selector_match(&x->sel, fl, family) || + !xfrm_sec_ctx_match(pol->security, x->security)) continue; if (!best || best->km.dying > x->km.dying || @@ -354,7 +356,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, acquire_in_progress = 1; } else if (x->km.state == XFRM_STATE_ERROR || x->km.state == XFRM_STATE_EXPIRED) { - if (xfrm_selector_match(&x->sel, fl, family)) + if (xfrm_selector_match(&x->sel, fl, family) && + xfrm_sec_ctx_match(pol->security, x->security)) error = -ESRCH; } } diff --git a/trunk/net/xfrm/xfrm_user.c b/trunk/net/xfrm/xfrm_user.c index 0cdd9a07e043..92e2b804c606 100644 --- a/trunk/net/xfrm/xfrm_user.c +++ b/trunk/net/xfrm/xfrm_user.c @@ -7,7 +7,7 @@ * Kazunori MIYAZAWA @USAGI * Kunihiro Ishiguro * IPv6 support - * + * */ #include @@ -88,6 +88,34 @@ static int verify_encap_tmpl(struct rtattr **xfrma) return 0; } + +static inline int verify_sec_ctx_len(struct rtattr **xfrma) +{ + struct rtattr *rt = xfrma[XFRMA_SEC_CTX - 1]; + struct xfrm_user_sec_ctx *uctx; + int len = 0; + + if (!rt) + return 0; + + if (rt->rta_len < sizeof(*uctx)) + return -EINVAL; + + uctx = RTA_DATA(rt); + + if (uctx->ctx_len > PAGE_SIZE) + return -EINVAL; + + len += sizeof(struct xfrm_user_sec_ctx); + len += uctx->ctx_len; + + if (uctx->len != len) + return -EINVAL; + + return 0; +} + + static int verify_newsa_info(struct xfrm_usersa_info *p, struct rtattr **xfrma) { @@ -145,6 +173,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, goto out; if ((err = verify_encap_tmpl(xfrma))) goto out; + if ((err = verify_sec_ctx_len(xfrma))) + goto out; err = -EINVAL; switch (p->mode) { @@ -209,6 +239,30 @@ static int attach_encap_tmpl(struct xfrm_encap_tmpl **encapp, struct rtattr *u_a return 0; } + +static inline int xfrm_user_sec_ctx_size(struct xfrm_policy *xp) +{ + struct xfrm_sec_ctx *xfrm_ctx = xp->security; + int len = 0; + + if (xfrm_ctx) { + len += sizeof(struct xfrm_user_sec_ctx); + len += xfrm_ctx->ctx_len; + } + return len; +} + +static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg) +{ + struct xfrm_user_sec_ctx *uctx; + + if (!u_arg) + return 0; + + uctx = RTA_DATA(u_arg); + return security_xfrm_state_alloc(x, uctx); +} + static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) { memcpy(&x->id, &p->id, sizeof(x->id)); @@ -253,6 +307,9 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, if (err) goto error; + if ((err = attach_sec_ctx(x, xfrma[XFRMA_SEC_CTX-1]))) + goto error; + x->km.seq = p->seq; return x; @@ -272,11 +329,11 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) int err; struct km_event c; - err = verify_newsa_info(p, (struct rtattr **) xfrma); + err = verify_newsa_info(p, (struct rtattr **)xfrma); if (err) return err; - x = xfrm_state_construct(p, (struct rtattr **) xfrma, &err); + x = xfrm_state_construct(p, (struct rtattr **)xfrma, &err); if (!x) return err; @@ -390,6 +447,19 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr) if (x->encap) RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); + if (x->security) { + int ctx_size = sizeof(struct xfrm_sec_ctx) + + x->security->ctx_len; + struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size); + struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt); + + uctx->exttype = XFRMA_SEC_CTX; + uctx->len = ctx_size; + uctx->ctx_doi = x->security->ctx_doi; + uctx->ctx_alg = x->security->ctx_alg; + uctx->ctx_len = x->security->ctx_len; + memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len); + } nlh->nlmsg_len = skb->tail - b; out: sp->this_idx++; @@ -603,6 +673,18 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) return verify_policy_dir(p->dir); } +static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct rtattr **xfrma) +{ + struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1]; + struct xfrm_user_sec_ctx *uctx; + + if (!rt) + return 0; + + uctx = RTA_DATA(rt); + return security_xfrm_policy_alloc(pol, uctx); +} + static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, int nr) { @@ -681,7 +763,10 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, } copy_from_user_policy(xp, p); - err = copy_from_user_tmpl(xp, xfrma); + + if (!(err = copy_from_user_tmpl(xp, xfrma))) + err = copy_from_user_sec_ctx(xp, xfrma); + if (err) { *errp = err; kfree(xp); @@ -700,10 +785,13 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr int excl; err = verify_newpolicy_info(p); + if (err) + return err; + err = verify_sec_ctx_len((struct rtattr **)xfrma); if (err) return err; - xp = xfrm_policy_construct(p, (struct rtattr **) xfrma, &err); + xp = xfrm_policy_construct(p, (struct rtattr **)xfrma, &err); if (!xp) return err; @@ -761,6 +849,27 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) return -1; } +static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb) +{ + if (xp->security) { + int ctx_size = sizeof(struct xfrm_sec_ctx) + + xp->security->ctx_len; + struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size); + struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt); + + uctx->exttype = XFRMA_SEC_CTX; + uctx->len = ctx_size; + uctx->ctx_doi = xp->security->ctx_doi; + uctx->ctx_alg = xp->security->ctx_alg; + uctx->ctx_len = xp->security->ctx_len; + memcpy(uctx + 1, xp->security->ctx_str, xp->security->ctx_len); + } + return 0; + + rtattr_failure: + return -1; +} + static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr) { struct xfrm_dump_info *sp = ptr; @@ -782,6 +891,8 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr copy_to_user_policy(xp, p, dir); if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; + if (copy_to_user_sec_ctx(xp, skb)) + goto nlmsg_failure; nlh->nlmsg_len = skb->tail - b; out: @@ -852,8 +963,25 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr if (p->index) xp = xfrm_policy_byid(p->dir, p->index, delete); - else - xp = xfrm_policy_bysel(p->dir, &p->sel, delete); + else { + struct rtattr **rtattrs = (struct rtattr **)xfrma; + struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; + struct xfrm_policy tmp; + + err = verify_sec_ctx_len(rtattrs); + if (err) + return err; + + memset(&tmp, 0, sizeof(struct xfrm_policy)); + if (rt) { + struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt); + + if ((err = security_xfrm_policy_alloc(&tmp, uctx))) + return err; + } + xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, delete); + security_xfrm_policy_free(&tmp); + } if (xp == NULL) return -ENOENT; @@ -1224,6 +1352,8 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; + if (copy_to_user_sec_ctx(xp, skb)) + goto nlmsg_failure; nlh->nlmsg_len = skb->tail - b; return skb->len; @@ -1241,6 +1371,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire)); + len += RTA_SPACE(xfrm_user_sec_ctx_size(xp)); skb = alloc_skb(len, GFP_ATOMIC); if (skb == NULL) return -ENOMEM; @@ -1324,6 +1455,8 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, copy_to_user_policy(xp, &upe->pol, dir); if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; + if (copy_to_user_sec_ctx(xp, skb)) + goto nlmsg_failure; upe->hard = !!hard; nlh->nlmsg_len = skb->tail - b; @@ -1341,6 +1474,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire)); + len += RTA_SPACE(xfrm_user_sec_ctx_size(xp)); skb = alloc_skb(len, GFP_ATOMIC); if (skb == NULL) return -ENOMEM; diff --git a/trunk/security/Kconfig b/trunk/security/Kconfig index 64d3f1e9ca85..34f593410d57 100644 --- a/trunk/security/Kconfig +++ b/trunk/security/Kconfig @@ -54,6 +54,19 @@ config SECURITY_NETWORK implement socket and networking access controls. If you are unsure how to answer this question, answer N. +config SECURITY_NETWORK_XFRM + bool "XFRM (IPSec) Networking Security Hooks" + depends on XFRM && SECURITY_NETWORK + help + This enables the XFRM (IPSec) networking security hooks. + If enabled, a security module can use these hooks to + implement per-packet access controls based on labels + derived from IPSec policy. Non-IPSec communications are + designated as unlabelled, and only sockets authorized + to communicate unlabelled data can send without using + IPSec. + If you are unsure how to answer this question, answer N. + config SECURITY_CAPABILITIES tristate "Default Linux Capabilities" depends on SECURITY diff --git a/trunk/security/dummy.c b/trunk/security/dummy.c index 3ca5f2b828a0..a15c54709fde 100644 --- a/trunk/security/dummy.c +++ b/trunk/security/dummy.c @@ -776,8 +776,42 @@ static inline int dummy_sk_alloc_security (struct sock *sk, int family, gfp_t pr static inline void dummy_sk_free_security (struct sock *sk) { } + +static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir) +{ + return 0; +} #endif /* CONFIG_SECURITY_NETWORK */ +#ifdef CONFIG_SECURITY_NETWORK_XFRM +static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) +{ + return 0; +} + +static inline int dummy_xfrm_policy_clone_security(struct xfrm_policy *old, struct xfrm_policy *new) +{ + return 0; +} + +static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp) +{ +} + +static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) +{ + return 0; +} + +static void dummy_xfrm_state_free_security(struct xfrm_state *x) +{ +} + +static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) +{ + return 0; +} +#endif /* CONFIG_SECURITY_NETWORK_XFRM */ static int dummy_register_security (const char *name, struct security_operations *ops) { return -EINVAL; @@ -970,7 +1004,16 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, socket_getpeersec); set_to_dummy_if_null(ops, sk_alloc_security); set_to_dummy_if_null(ops, sk_free_security); -#endif /* CONFIG_SECURITY_NETWORK */ + set_to_dummy_if_null(ops, sk_getsid); + #endif /* CONFIG_SECURITY_NETWORK */ +#ifdef CONFIG_SECURITY_NETWORK_XFRM + set_to_dummy_if_null(ops, xfrm_policy_alloc_security); + set_to_dummy_if_null(ops, xfrm_policy_clone_security); + set_to_dummy_if_null(ops, xfrm_policy_free_security); + set_to_dummy_if_null(ops, xfrm_state_alloc_security); + set_to_dummy_if_null(ops, xfrm_state_free_security); + set_to_dummy_if_null(ops, xfrm_policy_lookup); +#endif /* CONFIG_SECURITY_NETWORK_XFRM */ #ifdef CONFIG_KEYS set_to_dummy_if_null(ops, key_alloc); set_to_dummy_if_null(ops, key_free); diff --git a/trunk/sound/usb/usbaudio.c b/trunk/sound/usb/usbaudio.c index 22f8bb612bff..99dae024b640 100644 --- a/trunk/sound/usb/usbaudio.c +++ b/trunk/sound/usb/usbaudio.c @@ -1996,6 +1996,7 @@ static struct usb_device_id usb_audio_ids [] = { MODULE_DEVICE_TABLE (usb, usb_audio_ids); static struct usb_driver usb_audio_driver = { + .owner = THIS_MODULE, .name = "snd-usb-audio", .probe = usb_audio_probe, .disconnect = usb_audio_disconnect, diff --git a/trunk/sound/usb/usx2y/usbusx2y.c b/trunk/sound/usb/usx2y/usbusx2y.c index a3967f72ab4e..cf77313c609d 100644 --- a/trunk/sound/usb/usx2y/usbusx2y.c +++ b/trunk/sound/usb/usx2y/usbusx2y.c @@ -409,6 +409,7 @@ static void snd_usX2Y_disconnect(struct usb_interface *intf) MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table); static struct usb_driver snd_usX2Y_usb_driver = { + .owner = THIS_MODULE, .name = "snd-usb-usx2y", .probe = snd_usX2Y_probe, .disconnect = snd_usX2Y_disconnect,