diff options
90 files changed, 986 insertions, 501 deletions
diff --git a/Documentation/scsi/cxgb3i.txt b/Documentation/scsi/cxgb3i.txt index 8141fa01978..7ac8032ee9b 100644 --- a/Documentation/scsi/cxgb3i.txt +++ b/Documentation/scsi/cxgb3i.txt @@ -4,7 +4,7 @@ Introduction ============ The Chelsio T3 ASIC based Adapters (S310, S320, S302, S304, Mezz cards, etc. -series of products) supports iSCSI acceleration and iSCSI Direct Data Placement +series of products) support iSCSI acceleration and iSCSI Direct Data Placement (DDP) where the hardware handles the expensive byte touching operations, such as CRC computation and verification, and direct DMA to the final host memory destination: @@ -31,9 +31,9 @@ destination: the TCP segments onto the wire. It handles TCP retransmission if needed. - On receving, S3 h/w recovers the iSCSI PDU by reassembling TCP + On receiving, S3 h/w recovers the iSCSI PDU by reassembling TCP segments, separating the header and data, calculating and verifying - the digests, then forwards the header to the host. The payload data, + the digests, then forwarding the header to the host. The payload data, if possible, will be directly placed into the pre-posted host DDP buffer. Otherwise, the payload data will be sent to the host too. @@ -68,9 +68,8 @@ The following steps need to be taken to accelerates the open-iscsi initiator: sure the ip address is unique in the network. 3. edit /etc/iscsi/iscsid.conf - The default setting for MaxRecvDataSegmentLength (131072) is too big, - replace "node.conn[0].iscsi.MaxRecvDataSegmentLength" to be a value no - bigger than 15360 (for example 8192): + The default setting for MaxRecvDataSegmentLength (131072) is too big; + replace with a value no bigger than 15360 (for example 8192): node.conn[0].iscsi.MaxRecvDataSegmentLength = 8192 diff --git a/MAINTAINERS b/MAINTAINERS index 59fd2d1d94a..1c2ca1dc66f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2464,7 +2464,7 @@ S: Maintained ISDN SUBSYSTEM P: Karsten Keil -M: kkeil@suse.de +M: isdn@linux-pingi.de L: isdn4linux@listserv.isdn4linux.de (subscribers-only) W: http://www.isdn4linux.de T: git kernel.org:/pub/scm/linux/kernel/kkeil/isdn-2.6.git diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h index 36ed4407025..a6772e9507f 100644 --- a/arch/mips/include/asm/seccomp.h +++ b/arch/mips/include/asm/seccomp.h @@ -1,6 +1,5 @@ #ifndef __ASM_SECCOMP_H -#include <linux/thread_info.h> #include <linux/unistd.h> #define __NR_seccomp_read __NR_read diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index d811a8cd7b5..4774c2f9223 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -210,5 +210,10 @@ struct compat_shmid64_ds { compat_ulong_t __unused6; }; +static inline int is_compat_task(void) +{ + return test_thread_flag(TIF_32BIT); +} + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_COMPAT_H */ diff --git a/arch/powerpc/include/asm/seccomp.h b/arch/powerpc/include/asm/seccomp.h index 853765eb1f6..00c1d9133cf 100644 --- a/arch/powerpc/include/asm/seccomp.h +++ b/arch/powerpc/include/asm/seccomp.h @@ -1,10 +1,6 @@ #ifndef _ASM_POWERPC_SECCOMP_H #define _ASM_POWERPC_SECCOMP_H -#ifdef __KERNEL__ -#include <linux/thread_info.h> -#endif - #include <linux/unistd.h> #define __NR_seccomp_read __NR_read diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index f260b58f5ce..0e706257918 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -240,4 +240,9 @@ struct compat_shmid64_ds { unsigned int __unused2; }; +static inline int is_compat_task(void) +{ + return test_thread_flag(TIF_32BIT); +} + #endif /* _ASM_SPARC64_COMPAT_H */ diff --git a/arch/sparc/include/asm/seccomp.h b/arch/sparc/include/asm/seccomp.h index 7fcd9968192..adca1bce41d 100644 --- a/arch/sparc/include/asm/seccomp.h +++ b/arch/sparc/include/asm/seccomp.h @@ -1,11 +1,5 @@ #ifndef _ASM_SECCOMP_H -#include <linux/thread_info.h> /* already defines TIF_32BIT */ - -#ifndef TIF_32BIT -#error "unexpected TIF_32BIT on sparc64" -#endif - #include <linux/unistd.h> #define __NR_seccomp_read __NR_read diff --git a/arch/x86/include/asm/seccomp_32.h b/arch/x86/include/asm/seccomp_32.h index a6ad87b352c..b811d6f5780 100644 --- a/arch/x86/include/asm/seccomp_32.h +++ b/arch/x86/include/asm/seccomp_32.h @@ -1,12 +1,6 @@ #ifndef _ASM_X86_SECCOMP_32_H #define _ASM_X86_SECCOMP_32_H -#include <linux/thread_info.h> - -#ifdef TIF_32BIT -#error "unexpected TIF_32BIT on i386" -#endif - #include <linux/unistd.h> #define __NR_seccomp_read __NR_read diff --git a/arch/x86/include/asm/seccomp_64.h b/arch/x86/include/asm/seccomp_64.h index 4171bb794e9..84ec1bd161a 100644 --- a/arch/x86/include/asm/seccomp_64.h +++ b/arch/x86/include/asm/seccomp_64.h @@ -1,14 +1,6 @@ #ifndef _ASM_X86_SECCOMP_64_H #define _ASM_X86_SECCOMP_64_H -#include <linux/thread_info.h> - -#ifdef TIF_32BIT -#error "unexpected TIF_32BIT on x86_64" -#else -#define TIF_32BIT TIF_IA32 -#endif - #include <linux/unistd.h> #include <asm/ia32_unistd.h> diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 5a4c23d8989..06ca07f6ad8 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -1388,7 +1388,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, #ifdef CONFIG_X86_32 # define IS_IA32 1 #elif defined CONFIG_IA32_EMULATION -# define IS_IA32 test_thread_flag(TIF_IA32) +# define IS_IA32 is_compat_task() #else # define IS_IA32 0 #endif diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c index 6c2b1af1692..04102d42ff4 100644 --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -20,23 +20,16 @@ #include <asm/pat.h> #include <linux/module.h> -#ifdef CONFIG_X86_PAE -int -is_io_mapping_possible(resource_size_t base, unsigned long size) -{ - return 1; -} -#else -int -is_io_mapping_possible(resource_size_t base, unsigned long size) +int is_io_mapping_possible(resource_size_t base, unsigned long size) { +#ifndef CONFIG_X86_PAE /* There is no way to map greater than 1 << 32 address without PAE */ if (base + size > 0x100000000ULL) return 0; - +#endif return 1; } -#endif +EXPORT_SYMBOL_GPL(is_io_mapping_possible); /* Map 'pfn' using fixed map 'type' and protections 'prot' */ diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index aebbf67a79d..e0ab173b697 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -11,6 +11,7 @@ #include <linux/bootmem.h> #include <linux/debugfs.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/gfp.h> #include <linux/mm.h> #include <linux/fs.h> @@ -868,6 +869,7 @@ pgprot_t pgprot_writecombine(pgprot_t prot) else return pgprot_noncached(prot); } +EXPORT_SYMBOL_GPL(pgprot_writecombine); #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index c3c8b9bc40a..45470f18d7e 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -839,7 +839,7 @@ static void atkbd_disconnect(struct serio *serio) */ static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) { - const unsigned int forced_release_keys[] = { + static const unsigned int forced_release_keys[] = { 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, }; int i; @@ -856,7 +856,7 @@ static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) */ static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) { - const unsigned int forced_release_keys[] = { + static const unsigned int forced_release_keys[] = { 0x94, }; int i; diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 19284016e0f..ee855c5202e 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -209,8 +209,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) goto out; } - if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT || - !pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) { + if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || + !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { printk(KERN_ERR DRV_NAME ": Invalid Debounce/Columdrive Time from pdata\n"); bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index c8ed065ea0c..abb04c82c62 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c @@ -288,7 +288,7 @@ static int corgikbd_resume(struct platform_device *dev) #define corgikbd_resume NULL #endif -static int __init corgikbd_probe(struct platform_device *pdev) +static int __devinit corgikbd_probe(struct platform_device *pdev) { struct corgikbd *corgikbd; struct input_dev *input_dev; @@ -368,7 +368,7 @@ static int __init corgikbd_probe(struct platform_device *pdev) return err; } -static int corgikbd_remove(struct platform_device *pdev) +static int __devexit corgikbd_remove(struct platform_device *pdev) { int i; struct corgikbd *corgikbd = platform_get_drvdata(pdev); @@ -388,7 +388,7 @@ static int corgikbd_remove(struct platform_device *pdev) static struct platform_driver corgikbd_driver = { .probe = corgikbd_probe, - .remove = corgikbd_remove, + .remove = __devexit_p(corgikbd_remove), .suspend = corgikbd_suspend, .resume = corgikbd_resume, .driver = { @@ -397,7 +397,7 @@ static struct platform_driver corgikbd_driver = { }, }; -static int __devinit corgikbd_init(void) +static int __init corgikbd_init(void) { return platform_driver_register(&corgikbd_driver); } diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 3f3d1198cdb..058fa8b02c2 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -279,7 +279,7 @@ static int omap_kp_resume(struct platform_device *dev) #define omap_kp_resume NULL #endif -static int __init omap_kp_probe(struct platform_device *pdev) +static int __devinit omap_kp_probe(struct platform_device *pdev) { struct omap_kp *omap_kp; struct input_dev *input_dev; @@ -422,7 +422,7 @@ err1: return -EINVAL; } -static int omap_kp_remove(struct platform_device *pdev) +static int __devexit omap_kp_remove(struct platform_device *pdev) { struct omap_kp *omap_kp = platform_get_drvdata(pdev); @@ -454,7 +454,7 @@ static int omap_kp_remove(struct platform_device *pdev) static struct platform_driver omap_kp_driver = { .probe = omap_kp_probe, - .remove = omap_kp_remove, + .remove = __devexit_p(omap_kp_remove), .suspend = omap_kp_suspend, .resume = omap_kp_resume, .driver = { @@ -463,7 +463,7 @@ static struct platform_driver omap_kp_driver = { }, }; -static int __devinit omap_kp_init(void) +static int __init omap_kp_init(void) { printk(KERN_INFO "OMAP Keypad Driver\n"); return platform_driver_register(&omap_kp_driver); diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index c48b76a46a5..9d1781a618e 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c @@ -343,7 +343,7 @@ static int spitzkbd_resume(struct platform_device *dev) #define spitzkbd_resume NULL #endif -static int __init spitzkbd_probe(struct platform_device *dev) +static int __devinit spitzkbd_probe(struct platform_device *dev) { struct spitzkbd *spitzkbd; struct input_dev *input_dev; @@ -444,7 +444,7 @@ static int __init spitzkbd_probe(struct platform_device *dev) return err; } -static int spitzkbd_remove(struct platform_device *dev) +static int __devexit spitzkbd_remove(struct platform_device *dev) { int i; struct spitzkbd *spitzkbd = platform_get_drvdata(dev); @@ -470,7 +470,7 @@ static int spitzkbd_remove(struct platform_device *dev) static struct platform_driver spitzkbd_driver = { .probe = spitzkbd_probe, - .remove = spitzkbd_remove, + .remove = __devexit_p(spitzkbd_remove), .suspend = spitzkbd_suspend, .resume = spitzkbd_resume, .driver = { @@ -479,7 +479,7 @@ static struct platform_driver spitzkbd_driver = { }, }; -static int __devinit spitzkbd_init(void) +static int __init spitzkbd_init(void) { return platform_driver_register(&spitzkbd_driver); } diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 093c8c1bca7..9705f3a00a3 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -70,7 +70,7 @@ config MOUSE_PS2_SYNAPTICS config MOUSE_PS2_LIFEBOOK bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED default y - depends on MOUSE_PS2 + depends on MOUSE_PS2 && X86 help Say Y here if you have a Fujitsu B-series Lifebook PS/2 TouchScreen connected to your system. diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index b9a25d57bc5..6ab0eb1ada1 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -542,7 +542,7 @@ int elantech_detect(struct psmouse *psmouse, int set_properties) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { - pr_err("elantech.c: sending Elantech magic knock failed.\n"); + pr_debug("elantech.c: sending Elantech magic knock failed.\n"); return -1; } @@ -551,8 +551,27 @@ int elantech_detect(struct psmouse *psmouse, int set_properties) * set of magic numbers */ if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { - pr_info("elantech.c: unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", - param[0], param[1], param[2]); + pr_debug("elantech.c: " + "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", + param[0], param[1], param[2]); + return -1; + } + + /* + * Query touchpad's firmware version and see if it reports known + * value to avoid mis-detection. Logitech mice are known to respond + * to Elantech magic knock and there might be more. + */ + if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { + pr_debug("elantech.c: failed to query firmware version.\n"); + return -1; + } + + pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", + param[0], param[1], param[2]); + + if (param[0] == 0 || param[1] != 0) { + pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); return -1; } @@ -600,8 +619,7 @@ int elantech_init(struct psmouse *psmouse) int i, error; unsigned char param[3]; - etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); - psmouse->private = etd; + psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); if (!etd) return -1; @@ -610,14 +628,12 @@ int elantech_init(struct psmouse *psmouse) etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; /* - * Find out what version hardware this is + * Do the version query again so we can store the result */ if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { pr_err("elantech.c: failed to query firmware version.\n"); goto init_fail; } - pr_info("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", - param[0], param[1], param[2]); etd->fw_version_maj = param[0]; etd->fw_version_min = param[2]; diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index d297accf9a7..1e827ad0afb 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -83,7 +83,7 @@ static int write_tbcr(struct pxa930_trkball *trkball, int v) __raw_writel(v, trkball->mmio_base + TBCR); - while (i--) { + while (--i) { if (__raw_readl(trkball->mmio_base + TBCR) == v) break; msleep(1); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 865fc69e9bc..f3e4f7b0240 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -182,11 +182,6 @@ static int synaptics_identify(struct psmouse *psmouse) static int synaptics_query_hardware(struct psmouse *psmouse) { - int retries = 0; - - while ((retries++ < 3) && psmouse_reset(psmouse)) - /* empty */; - if (synaptics_identify(psmouse)) return -1; if (synaptics_model_id(psmouse)) @@ -582,6 +577,8 @@ static int synaptics_reconnect(struct psmouse *psmouse) struct synaptics_data *priv = psmouse->private; struct synaptics_data old_priv = *priv; + psmouse_reset(psmouse); + if (synaptics_detect(psmouse, 0)) return -1; @@ -640,6 +637,8 @@ int synaptics_init(struct psmouse *psmouse) if (!priv) return -1; + psmouse_reset(psmouse); + if (synaptics_query_hardware(psmouse)) { printk(KERN_ERR "Unable to query Synaptics hardware.\n"); goto init_fail; diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index b10ffae7c39..e29cdc13a19 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -57,7 +57,7 @@ static int amba_kmi_write(struct serio *io, unsigned char val) struct amba_kmi_port *kmi = io->port_data; unsigned int timeleft = 10000; /* timeout in 100ms */ - while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--) + while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && --timeleft) udelay(10); if (timeleft) @@ -129,8 +129,8 @@ static int amba_kmi_probe(struct amba_device *dev, void *id) io->write = amba_kmi_write; io->open = amba_kmi_open; io->close = amba_kmi_close; - strlcpy(io->name, dev->dev.bus_id, sizeof(io->name)); - strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys)); + strlcpy(io->name, dev_name(&dev->dev), sizeof(io->name)); + strlcpy(io->phys, dev_name(&dev->dev), sizeof(io->phys)); io->port_data = kmi; io->dev.parent = &dev->dev; diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index adc3bd6e7f7..bd0f92d9f40 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -359,7 +359,7 @@ static int __init gscps2_probe(struct parisc_device *dev) snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s", (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse"); - strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); + strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); serio->id.type = SERIO_8042; serio->write = gscps2_write; serio->open = gscps2_open; diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 2ad88780a17..57953c0eb82 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -246,8 +246,8 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) serio->write = ps2_write; serio->open = ps2_open; serio->close = ps2_close; - strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name)); - strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); + strlcpy(serio->name, dev_name(&dev->dev), sizeof(serio->name)); + strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); serio->port_data = ps2if; serio->dev.parent = &dev->dev; ps2if->io = serio; diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index a89a6a8f05e..055969e8be1 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -236,7 +236,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) ts_dev->bufferedmeasure = 0; snprintf(ts_dev->phys, sizeof(ts_dev->phys), - "%s/input0", pdev->dev.bus_id); + "%s/input0", dev_name(&pdev->dev)); input_dev->name = "atmel touch screen controller"; input_dev->phys = ts_dev->phys; diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index 65202c9f63f..3fb51b54fe6 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c @@ -268,7 +268,7 @@ static int corgits_resume(struct platform_device *dev) #define corgits_resume NULL #endif -static int __init corgits_probe(struct platform_device *pdev) +static int __devinit corgits_probe(struct platform_device *pdev) { struct corgi_ts *corgi_ts; struct input_dev *input_dev; @@ -343,7 +343,7 @@ static int __init corgits_probe(struct platform_device *pdev) return err; } -static int corgits_remove(struct platform_device *pdev) +static int __devexit corgits_remove(struct platform_device *pdev) { struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); @@ -352,12 +352,13 @@ static int corgits_remove(struct platform_device *pdev) corgi_ts->machinfo->put_hsync(); input_unregister_device(corgi_ts->input); kfree(corgi_ts); + return 0; } static struct platform_driver corgits_driver = { .probe = corgits_probe, - .remove = corgits_remove, + .remove = __devexit_p(corgits_remove), .suspend = corgits_suspend, .resume = corgits_resume, .driver = { @@ -366,7 +367,7 @@ static struct platform_driver corgits_driver = { }, }; -static int __devinit corgits_init(void) +static int __init corgits_init(void) { return platform_driver_register(&corgits_driver); } diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index b75dc299057..4ab07024689 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -289,7 +289,8 @@ static int tsc2007_probe(struct i2c_client *client, pdata->init_platform_hw(); - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", client->dev.bus_id); + snprintf(ts->phys, sizeof(ts->phys), + "%s/input0", dev_name(&client->dev)); input_dev->name = "TSC2007 Touchscreen"; input_dev->phys = ts->phys; diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 5080b26ba16..fb7cb9bdfbd 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -60,6 +60,10 @@ static int swap_xy; module_param(swap_xy, bool, 0644); MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); +static int hwcalib_xy; +module_param(hwcalib_xy, bool, 0644); +MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); + /* device specifc data/functions */ struct usbtouch_usb; struct usbtouch_device_info { @@ -118,6 +122,7 @@ enum { #define USB_DEVICE_HID_CLASS(vend, prod) \ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ + | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ | USB_DEVICE_ID_MATCH_DEVICE, \ .idVendor = (vend), \ .idProduct = (prod), \ @@ -260,8 +265,13 @@ static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) { - dev->x = (pkt[8] << 8) | pkt[7]; - dev->y = (pkt[10] << 8) | pkt[9]; + if (hwcalib_xy) { + dev->x = (pkt[4] << 8) | pkt[3]; + dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); + } else { + dev->x = (pkt[8] << 8) | pkt[7]; + dev->y = (pkt[10] << 8) | pkt[9]; + } dev->touch = (pkt[2] & 0x40) ? 1 : 0; return 1; @@ -294,6 +304,12 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) return ret; } + /* Default min/max xy are the raw values, override if using hw-calib */ + if (hwcalib_xy) { + input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); + input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); + } + return 0; } #endif diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index c1e4ae27c61..c705f248da8 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c @@ -46,8 +46,8 @@ static int uvc_input_init(struct uvc_device *dev) usb_to_input_id(udev, &input->id); input->dev.parent = &dev->intf->dev; - set_bit(EV_KEY, input->evbit); - set_bit(BTN_0, input->keybit); + __set_bit(EV_KEY, input->evbit); + __set_bit(KEY_CAMERA, input->keybit); if ((ret = input_register_device(input)) < 0) goto error; @@ -70,8 +70,10 @@ static void uvc_input_cleanup(struct uvc_device *dev) static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, int value) { - if (dev->input) + if (dev->input) { input_report_key(dev->input, code, value); + input_sync(dev->input); + } } #else @@ -96,7 +98,7 @@ static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len) return; uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", data[1], data[3] ? "pressed" : "released", len); - uvc_input_report_key(dev, BTN_0, data[3]); + uvc_input_report_key(dev, KEY_CAMERA, data[3]); } else { uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " "len %d.\n", data[1], data[2], data[3], len); diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 96ac88317b8..ea3aafbbda4 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -91,9 +91,9 @@ MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \ controllers (default=0)"); static int mpt_msi_enable_sas; -module_param(mpt_msi_enable_sas, int, 1); +module_param(mpt_msi_enable_sas, int, 0); MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \ - controllers (default=1)"); + controllers (default=0)"); static int mpt_channel_mapping; diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 8cff5f5e7f8..406da9a8d45 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -107,6 +107,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = { static const struct sdhci_pci_fixes sdhci_cafe = { .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | + SDHCI_QUIRK_NO_BUSY_IRQ | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, }; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f52f3053ed9..accb592764e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1291,8 +1291,11 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) if (host->cmd->data) DBG("Cannot wait for busy signal when also " "doing a data transfer"); - else + else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) return; + + /* The controller does not support the end-of-busy IRQ, + * fall through and take the SDHCI_INT_RESPONSE */ } if (intmask & SDHCI_INT_RESPONSE) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index ebb83657e27..43c37c68d07 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -208,6 +208,8 @@ struct sdhci_host { #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) /* Controller has an issue with buffer bits for small transfers */ #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) +/* Controller does not provide transfer-complete interrupt when not busy */ +#define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) int irq; /* Device IRQ */ void __iomem * ioaddr; /* Mapped address */ diff --git a/drivers/net/b44.c b/drivers/net/b44.c index c38512ebcea..dc5f051005f 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1264,8 +1264,14 @@ static void b44_clear_stats(struct b44 *bp) static void b44_chip_reset(struct b44 *bp, int reset_kind) { struct ssb_device *sdev = bp->sdev; + bool was_enabled; - if (ssb_device_is_enabled(bp->sdev)) { + was_enabled = ssb_device_is_enabled(bp->sdev); + + ssb_device_enable(bp->sdev, 0); + ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev); + + if (was_enabled) { bw32(bp, B44_RCV_LAZY, 0); bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE); b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1); @@ -1277,10 +1283,8 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind) } bw32(bp, B44_DMARX_CTRL, 0); bp->rx_prod = bp->rx_cons = 0; - } else - ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev); + } - ssb_device_enable(bp->sdev, 0); b44_clear_stats(bp); /* @@ -2236,6 +2240,7 @@ static void __devexit b44_remove_one(struct ssb_device *sdev) struct net_device *dev = ssb_get_drvdata(sdev); unregister_netdev(dev); + ssb_device_disable(sdev, 0); ssb_bus_may_powerdown(sdev->bus); free_netdev(dev); ssb_pcihost_set_power_state(sdev, PCI_D3hot); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 9b12a13a640..9831b3f408a 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1284,7 +1284,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&priv->txlock, flags); /* check if there is space to queue this packet */ - if (nr_frags > priv->num_txbdfree) { + if ((nr_frags+1) > priv->num_txbdfree) { /* no space, stop the queue */ netif_stop_queue(dev); dev->stats.tx_fifo_errors++; diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 5e070f44663..0486cbe01ad 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -467,7 +467,7 @@ init_module(void) if (this_dev != 0) break; /* only autoprobe 1st one */ printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n"); } - dev = alloc_ei_netdev(); + dev = alloc_eip_netdev(); if (!dev) break; dev->irq = irq[this_dev]; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9f33e442f40..13087782ac4 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -588,7 +588,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->pci_mem_read = netxen_nic_pci_mem_read_2M; adapter->pci_mem_write = netxen_nic_pci_mem_write_2M; - mem_ptr0 = ioremap(mem_base, mem_len); + mem_ptr0 = pci_ioremap_bar(pdev, 0); + if (mem_ptr0 == NULL) { + dev_err(&pdev->dev, "failed to map PCI bar 0\n"); + return -EIO; + } + pci_len0 = mem_len; first_page_group_start = 0; first_page_group_end = 0; @@ -795,9 +800,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * See if the firmware gave us a virtual-physical port mapping. */ adapter->physical_port = adapter->portnum; - i = adapter->pci_read_normalize(adapter, CRB_V2P(adapter->portnum)); - if (i != 0x55555555) - adapter->physical_port = i; + if (adapter->fw_major < 4) { + i = adapter->pci_read_normalize(adapter, + CRB_V2P(adapter->portnum)); + if (i != 0x55555555) + adapter->physical_port = i; + } adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0771eb6fc6e..b3473401c83 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -81,9 +81,9 @@ static const int multicast_filter_limit = 32; #define RTL8169_TX_TIMEOUT (6*HZ) #define RTL8169_PHY_TIMEOUT (10*HZ) -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) +#define RTL_EEPROM_SIG 0x8129 #define RTL_EEPROM_SIG_ADDR 0x0000 +#define RTL_EEPROM_MAC_ADDR 0x0007 /* write/read MMIO register */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) @@ -293,6 +293,11 @@ enum rtl_register_content { /* Cfg9346Bits */ Cfg9346_Lock = 0x00, Cfg9346_Unlock = 0xc0, + Cfg9346_Program = 0x80, /* Programming mode */ + Cfg9346_EECS = 0x08, /* Chip select */ + Cfg9346_EESK = 0x04, /* Serial data clock */ + Cfg9346_EEDI = 0x02, /* Data input */ + Cfg9346_EEDO = 0x01, /* Data output */ /* rx_mode_bits */ AcceptErr = 0x20, @@ -305,6 +310,7 @@ enum rtl_register_content { /* RxConfigBits */ RxCfgFIFOShift = 13, RxCfgDMAShift = 8, + RxCfg9356SEL = 6, /* EEPROM type: 0 = 9346, 1 = 9356 */ /* TxConfigBits */ TxInterFrameGapShift = 24, @@ -1963,6 +1969,108 @@ static const struct net_device_ops rtl8169_netdev_ops = { }; +/* Delay between EEPROM clock transitions. Force out buffered PCI writes. */ +#define RTL_EEPROM_DELAY() RTL_R8(Cfg9346) +#define RTL_EEPROM_READ_CMD 6 + +/* read 16bit word stored in EEPROM. EEPROM is addressed by words. */ +static u16 rtl_eeprom_read(void __iomem *ioaddr, int addr) +{ + u16 result = 0; + int cmd, cmd_len, i; + + /* check for EEPROM address size (in bits) */ + if (RTL_R32(RxConfig) & (1 << RxCfg9356SEL)) { + /* EEPROM is 93C56 */ + cmd_len = 3 + 8; /* 3 bits for command id and 8 for address */ + cmd = (RTL_EEPROM_READ_CMD << 8) | (addr & 0xff); + } else { + /* EEPROM is 93C46 */ + cmd_len = 3 + 6; /* 3 bits for command id and 6 for address */ + cmd = (RTL_EEPROM_READ_CMD << 6) | (addr & 0x3f); + } + + /* enter programming mode */ + RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); + RTL_EEPROM_DELAY(); + + /* write command and requested address */ + while (cmd_len--) { + u8 x = Cfg9346_Program | Cfg9346_EECS; + + x |= (cmd & (1 << cmd_len)) ? Cfg9346_EEDI : 0; + + /* write a bit */ + RTL_W8(Cfg9346, x); + RTL_EEPROM_DELAY(); + + /* raise clock */ + RTL_W8(Cfg9346, x | Cfg9346_EESK); + RTL_EEPROM_DELAY(); + } + + /* lower clock */ + RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); + RTL_EEPROM_DELAY(); + + /* read back 16bit value */ + for (i = 16; i > 0; i--) { + /* raise clock */ + RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS | Cfg9346_EESK); + RTL_EEPROM_DELAY(); + + result <<= 1; + result |= (RTL_R8(Cfg9346) & Cfg9346_EEDO) ? 1 : 0; + + /* lower clock */ + RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); + RTL_EEPROM_DELAY(); + } + + RTL_W8(Cfg9346, Cfg9346_Program); + /* leave programming mode */ + RTL_W8(Cfg9346, Cfg9346_Lock); + + return result; +} + +static void rtl_init_mac_address(struct rtl8169_private *tp, + void __iomem *ioaddr) +{ + struct pci_dev *pdev = tp->pci_dev; + u16 x; + u8 mac[8]; + + /* read EEPROM signature */ + x = rtl_eeprom_read(ioaddr, RTL_EEPROM_SIG_ADDR); + + if (x != RTL_EEPROM_SIG) { + dev_info(&pdev->dev, "Missing EEPROM signature: %04x\n", x); + return; + } + + /* read MAC address */ + x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR); + mac[0] = x & 0xff; + mac[1] = x >> 8; + x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 1); + mac[2] = x & 0xff; + mac[3] = x >> 8; + x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 2); + mac[4] = x & 0xff; + mac[5] = x >> 8; + + if (netif_msg_probe(tp)) { + DECLARE_MAC_BUF(buf); + + dev_info(&pdev->dev, "MAC address found in EEPROM: %s\n", + print_mac(buf, mac)); + } + + if (is_valid_ether_addr(mac)) + rtl_rar_set(tp, mac); +} + static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2141,6 +2249,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->mmio_addr = ioaddr; + rtl_init_mac_address(tp, ioaddr); + /* Get MAC address */ for (i = 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] = RTL_R8(MAC0 + i); diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e009481c606..396f821b5ff 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1451,6 +1451,14 @@ static const struct usb_device_id products [] = { // Cables-to-Go USB Ethernet Adapter USB_DEVICE(0x0b95, 0x772a), .driver_info = (unsigned long) &ax88772_info, +}, { + // ABOCOM for pci + USB_DEVICE(0x14ea, 0xab11), + .driver_info = (unsigned long) &ax88178_info, +}, { + // ASIX 88772a + USB_DEVICE(0x0db0, 0xa877), + .driver_info = (unsigned long) &ax88772_info, }, { }, // END }; diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 0e061dfea78..55e8ecc3a9e 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -559,6 +559,11 @@ static const struct usb_device_id products [] = { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, +}, { + /* Ericsson F3507g */ + USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1900, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, }, { }, // END }; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index aa314907888..c32284ff3f5 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -723,8 +723,8 @@ u32 usbnet_get_link (struct net_device *net) if (dev->mii.mdio_read) return mii_link_ok(&dev->mii); - /* Otherwise, say we're up (to avoid breaking scripts) */ - return 1; + /* Otherwise, dtrt for drivers calling netif_carrier_{on,off} */ + return ethtool_op_get_link(net); } EXPORT_SYMBOL_GPL(usbnet_get_link); diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index e24f7b3ace4..04882c8f9bf 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c @@ -341,6 +341,11 @@ static const struct usb_device_id products [] = { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &bogus_mdlm_info, +}, { + /* Motorola MOTOMAGX phones */ + USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &bogus_mdlm_info, }, /* Olympus has some models with a Zaurus-compatible option. diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 108bbbeacfb..124fe75b8a8 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -239,6 +239,16 @@ static int veth_open(struct net_device *dev) return 0; } +static int veth_close(struct net_device *dev) +{ + struct veth_priv *priv = netdev_priv(dev); + + netif_carrier_off(dev); + netif_carrier_off(priv->peer); + + return 0; +} + static int veth_dev_init(struct net_device *dev) { struct veth_net_stats *stats; @@ -265,6 +275,7 @@ static void veth_dev_free(struct net_device *dev) static const struct net_device_ops veth_netdev_ops = { .ndo_init = veth_dev_init, .ndo_open = veth_open, + .ndo_stop = veth_close, .ndo_start_xmit = veth_xmit, .ndo_get_stats = veth_get_stats, .ndo_set_mac_address = eth_mac_addr, @@ -280,44 +291,6 @@ static void veth_setup(struct net_device *dev) dev->destructor = veth_dev_free; } -static void veth_change_state(struct net_device *dev) -{ - struct net_device *peer; - struct veth_priv *priv; - - priv = netdev_priv(dev); - peer = priv->peer; - - if (netif_carrier_ok(peer)) { - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); - } else { - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); - } -} - -static int veth_device_event(struct notifier_block *unused, - unsigned long event, void *ptr) -{ - struct net_device *dev = ptr; - - if (dev->netdev_ops->ndo_open != veth_open) - goto out; - - switch (event) { - case NETDEV_CHANGE: - veth_change_state(dev); - break; - } -out: - return NOTIFY_DONE; -} - -static struct notifier_block veth_notifier_block __read_mostly = { - .notifier_call = veth_device_event, -}; - /* * netlink interface */ @@ -468,14 +441,12 @@ static struct rtnl_link_ops veth_link_ops = { static __init int veth_init(void) { - register_netdevice_notifier(&veth_notifier_block); return rtnl_link_register(&veth_link_ops); } static __exit void veth_exit(void) { rtnl_link_unregister(&veth_link_ops); - unregister_netdevice_notifier(&veth_notifier_block); } module_init(veth_init); diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 727f067aca4..0e80990d8e8 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1538,6 +1538,7 @@ bad2: bad: if (ah) ath9k_hw_detach(ah); + ath9k_exit_debug(sc); return error; } @@ -1545,7 +1546,7 @@ bad: static int ath_attach(u16 devid, struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; - int error = 0; + int error = 0, i; DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); @@ -1589,11 +1590,11 @@ static int ath_attach(u16 devid, struct ath_softc *sc) /* initialize tx/rx engine */ error = ath_tx_init(sc, ATH_TXBUF); if (error != 0) - goto detach; + goto error_attach; error = ath_rx_init(sc, ATH_RXBUF); if (error != 0) - goto detach; + goto error_attach; #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) /* Initialze h/w Rfkill */ @@ -1601,8 +1602,9 @@ static int ath_attach(u16 devid, struct ath_softc *sc) INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); /* Initialize s/w rfkill */ - if (ath_init_sw_rfkill(sc)) - goto detach; + error = ath_init_sw_rfkill(sc); + if (error) + goto error_attach; #endif error = ieee80211_register_hw(hw); @@ -1611,8 +1613,16 @@ static int ath_attach(u16 devid, struct ath_softc *sc) ath_init_leds(sc); return 0; -detach: - ath_detach(sc); + +error_attach: + /* cleanup tx queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); + + ath9k_hw_detach(sc->sc_ah); + ath9k_exit_debug(sc); + return error; } diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 61d2f50470c..b118a35ec60 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -23,7 +23,7 @@ static const char * mesh_stat_strings[]= { static void lbs_ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; snprintf(info->fw_version, 32, "%u.%u.%u.p%u", priv->fwrelease >> 24 & 0xff, @@ -47,7 +47,7 @@ static int lbs_ethtool_get_eeprom_len(struct net_device *dev) static int lbs_ethtool_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 * bytes) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct cmd_ds_802_11_eeprom_access cmd; int ret; @@ -76,7 +76,7 @@ out: static void lbs_ethtool_get_stats(struct net_device *dev, struct ethtool_stats *stats, uint64_t *data) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct cmd_ds_mesh_access mesh_access; int ret; @@ -113,7 +113,7 @@ static void lbs_ethtool_get_stats(struct net_device *dev, static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; if (sset == ETH_SS_STATS && dev == priv->mesh_dev) return MESH_STATS_NUM; @@ -143,7 +143,7 @@ static void lbs_ethtool_get_strings(struct net_device *dev, static void lbs_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; if (priv->wol_criteria == 0xffffffff) { /* Interface driver didn't configure wake */ @@ -166,7 +166,7 @@ static void lbs_ethtool_get_wol(struct net_device *dev, static int lbs_ethtool_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; uint32_t criteria = 0; if (priv->wol_criteria == 0xffffffff && wol->wolopts) diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 2fc637ad85c..ea3dc038be7 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -59,7 +59,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp); static ssize_t if_usb_firmware_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct if_usb_card *cardp = priv->card; char fwname[FIRMWARE_NAME_MAX]; int ret; @@ -86,7 +86,7 @@ static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); static ssize_t if_usb_boot2_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct if_usb_card *cardp = priv->card; char fwname[FIRMWARE_NAME_MAX]; int ret; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 4e0007d2003..f76623e0ff9 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -222,7 +222,7 @@ u8 lbs_data_rate_to_fw_index(u32 rate) static ssize_t lbs_anycast_get(struct device *dev, struct device_attribute *attr, char * buf) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_access mesh_access; int ret; @@ -241,7 +241,7 @@ static ssize_t lbs_anycast_get(struct device *dev, static ssize_t lbs_anycast_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_access mesh_access; uint32_t datum; int ret; @@ -263,7 +263,7 @@ static ssize_t lbs_anycast_set(struct device *dev, static ssize_t lbs_prb_rsp_limit_get(struct device *dev, struct device_attribute *attr, char *buf) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_access mesh_access; int ret; u32 retry_limit; @@ -286,7 +286,7 @@ static ssize_t lbs_prb_rsp_limit_get(struct device *dev, static ssize_t lbs_prb_rsp_limit_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_access mesh_access; int ret; unsigned long retry_limit; @@ -321,7 +321,7 @@ static void lbs_remove_mesh(struct lbs_private *priv); static ssize_t lbs_rtap_get(struct device *dev, struct device_attribute *attr, char * buf) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; return snprintf(buf, 5, "0x%X\n", priv->monitormode); } @@ -332,7 +332,7 @@ static ssize_t lbs_rtap_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) { int monitor_mode; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; sscanf(buf, "%x", &monitor_mode); if (monitor_mode) { @@ -383,7 +383,7 @@ static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); static ssize_t lbs_mesh_get(struct device *dev, struct device_attribute *attr, char * buf) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); } @@ -393,7 +393,7 @@ static ssize_t lbs_mesh_get(struct device *dev, static ssize_t lbs_mesh_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; int enable; int ret, action = CMD_ACT_MESH_CONFIG_STOP; @@ -452,7 +452,7 @@ static struct attribute_group lbs_mesh_attr_group = { */ static int lbs_dev_open(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev) ; + struct lbs_private *priv = dev->ml_priv; int ret = 0; lbs_deb_enter(LBS_DEB_NET); @@ -521,7 +521,7 @@ static int lbs_mesh_stop(struct net_device *dev) */ static int lbs_eth_stop(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_NET); @@ -538,7 +538,7 @@ static int lbs_eth_stop(struct net_device *dev) static void lbs_tx_timeout(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_TX); @@ -590,7 +590,7 @@ EXPORT_SYMBOL_GPL(lbs_host_to_card_done); */ static struct net_device_stats *lbs_get_stats(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_NET); return &priv->stats; @@ -599,7 +599,7 @@ static struct net_device_stats *lbs_get_stats(struct net_device *dev) static int lbs_set_mac_address(struct net_device *dev, void *addr) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct sockaddr *phwaddr = addr; struct cmd_ds_802_11_mac_address cmd; @@ -732,7 +732,7 @@ static void lbs_set_mcast_worker(struct work_struct *work) static void lbs_set_multicast_list(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; schedule_work(&priv->mcast_work); } @@ -748,7 +748,7 @@ static void lbs_set_multicast_list(struct net_device *dev) static int lbs_thread(void *data) { struct net_device *dev = data; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; wait_queue_t wait; lbs_deb_enter(LBS_DEB_THREAD); @@ -1184,6 +1184,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) goto done; } priv = netdev_priv(dev); + dev->ml_priv = priv; if (lbs_init_adapter(priv)) { lbs_pr_err("failed to initialize adapter structure.\n"); diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c index d42b7a5a1b3..18fe29faf99 100644 --- a/drivers/net/wireless/libertas/persistcfg.c +++ b/drivers/net/wireless/libertas/persistcfg.c @@ -18,7 +18,7 @@ static int mesh_get_default_parameters(struct device *dev, struct mrvl_mesh_defaults *defs) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_config cmd; int ret; @@ -57,7 +57,7 @@ static ssize_t bootflag_get(struct device *dev, static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_config cmd; uint32_t datum; int ret; @@ -100,7 +100,7 @@ static ssize_t boottime_get(struct device *dev, static ssize_t boottime_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_config cmd; uint32_t datum; int ret; @@ -152,7 +152,7 @@ static ssize_t channel_get(struct device *dev, static ssize_t channel_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_config cmd; uint32_t datum; int ret; @@ -210,7 +210,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, struct cmd_ds_mesh_config cmd; struct mrvl_mesh_defaults defs; struct mrvl_meshie *ie; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; int len; int ret; @@ -269,7 +269,7 @@ static ssize_t protocol_id_set(struct device *dev, struct cmd_ds_mesh_config cmd; struct mrvl_mesh_defaults defs; struct mrvl_meshie *ie; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; uint32_t datum; int ret; @@ -323,7 +323,7 @@ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, struct cmd_ds_mesh_config cmd; struct mrvl_mesh_defaults defs; struct mrvl_meshie *ie; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; uint32_t datum; int ret; @@ -377,7 +377,7 @@ static ssize_t capability_set(struct device *dev, struct device_attribute *attr, struct cmd_ds_mesh_config cmd; struct mrvl_mesh_defaults defs; struct mrvl_meshie *ie; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; uint32_t datum; int ret; diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 57f6c12cda2..9014950f432 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -945,7 +945,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { DECLARE_SSID_BUF(ssid); - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; lbs_deb_enter(LBS_DEB_WEXT); @@ -1008,7 +1008,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { #define SCAN_ITEM_SIZE 128 - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int err = 0; char *ev = extra; char *stop = ev + dwrq->length; diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index dac46264117..68bec31ae03 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -60,7 +60,7 @@ static u32 convert_radiotap_rate_to_mv(u8 rate) int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned long flags; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct txpd *txpd; char *p802x_hdr; uint16_t pkt_len; diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index c6102e08179..f16d136ab4b 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -163,7 +163,7 @@ static int lbs_get_name(struct net_device *dev, struct iw_request_info *info, static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct chan_freq_power *cfp; lbs_deb_enter(LBS_DEB_WEXT); @@ -189,7 +189,7 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -207,7 +207,7 @@ static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -231,7 +231,7 @@ static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -248,7 +248,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -273,7 +273,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; u32 val = vwrq->value; lbs_deb_enter(LBS_DEB_WEXT); @@ -293,7 +293,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u16 val = 0; @@ -315,7 +315,7 @@ out: static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u32 val = vwrq->value; @@ -336,7 +336,7 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u16 val = 0; @@ -359,7 +359,7 @@ out: static int lbs_get_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -385,7 +385,7 @@ static int lbs_get_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; s16 curlevel = 0; int ret = 0; @@ -418,7 +418,7 @@ out: static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u16 slimit = 0, llimit = 0; @@ -466,7 +466,7 @@ out: static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u16 val = 0; @@ -542,7 +542,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { int i, j; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct iw_range *range = (struct iw_range *)extra; struct chan_freq_power *cfp; u8 rates[MAX_RATES + 1]; @@ -708,7 +708,7 @@ out: static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -758,7 +758,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, static int lbs_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -781,7 +781,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) EXCELLENT = 95, PERFECT = 100 }; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; u32 rssi_qual; u32 tx_qual; u32 quality = 0; @@ -886,7 +886,7 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { int ret = -EINVAL; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct chan_freq_power *cfp; struct assoc_request * assoc_req; @@ -943,7 +943,7 @@ static int lbs_mesh_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct chan_freq_power *cfp; int ret = -EINVAL; @@ -994,7 +994,7 @@ out: static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; u8 new_rate = 0; int ret = -EINVAL; u8 rates[MAX_RATES + 1]; @@ -1054,7 +1054,7 @@ out: static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -1079,7 +1079,7 @@ static int lbs_set_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct assoc_request * assoc_req; lbs_deb_enter(LBS_DEB_WEXT); @@ -1124,7 +1124,7 @@ static int lbs_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, u8 * extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; lbs_deb_enter(LBS_DEB_WEXT); @@ -1319,7 +1319,7 @@ static int lbs_set_encode(struct net_device *dev, struct iw_point *dwrq, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct assoc_request * assoc_req; u16 is_default = 0, index = 0, set_tx_key = 0; @@ -1395,7 +1395,7 @@ static int lbs_get_encodeext(struct net_device *dev, char *extra) { int ret = -EINVAL; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int index, max_key_len; @@ -1501,7 +1501,7 @@ static int lbs_set_encodeext(struct net_device *dev, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int alg = ext->alg; struct assoc_request * assoc_req; @@ -1639,7 +1639,7 @@ static int lbs_set_genie(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; struct assoc_request * assoc_req; @@ -1685,7 +1685,7 @@ static int lbs_get_genie(struct net_device *dev, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -1713,7 +1713,7 @@ static int lbs_set_auth(struct net_device *dev, struct iw_param *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct assoc_request * assoc_req; int ret = 0; int updated = 0; @@ -1816,7 +1816,7 @@ static int lbs_get_auth(struct net_device *dev, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -1857,7 +1857,7 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; s16 dbm = (s16) vwrq->value; lbs_deb_enter(LBS_DEB_WEXT); @@ -1936,7 +1936,7 @@ out: static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -1971,7 +1971,7 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u8 ssid[IW_ESSID_MAX_SIZE]; u8 ssid_len = 0; @@ -2040,7 +2040,7 @@ static int lbs_mesh_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -2058,7 +2058,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; lbs_deb_enter(LBS_DEB_WEXT); @@ -2102,7 +2102,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct assoc_request * assoc_req; int ret = 0; diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 45a04faa781..067d1a9c728 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -3157,8 +3157,20 @@ static int orinoco_pm_notifier(struct notifier_block *notifier, return NOTIFY_DONE; } + +static void orinoco_register_pm_notifier(struct orinoco_private *priv) +{ + priv->pm_notifier.notifier_call = orinoco_pm_notifier; + register_pm_notifier(&priv->pm_notifier); +} + +static void orinoco_unregister_pm_notifier(struct orinoco_private *priv) +{ + unregister_pm_notifier(&priv->pm_notifier); +} #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */ -#define orinoco_pm_notifier NULL +#define orinoco_register_pm_notifier(priv) do { } while(0) +#define orinoco_unregister_pm_notifier(priv) do { } while(0) #endif /********************************************************************/ @@ -3648,8 +3660,7 @@ struct net_device priv->cached_fw = NULL; /* Register PM notifiers */ - priv->pm_notifier.notifier_call = orinoco_pm_notifier; - register_pm_notifier(&priv->pm_notifier); + orinoco_register_pm_notifier(priv); return dev; } @@ -3673,7 +3684,7 @@ void free_orinocodev(struct net_device *dev) kfree(rx_data); } - unregister_pm_notifier(&priv->pm_notifier); + orinoco_unregister_pm_notifier(priv); orinoco_uncache_fw(priv); priv->wpa_ie_len = 0; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 22bc07ef2f3..f4747a1134b 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -48,6 +48,10 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, + /* Surecom */ + {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187}, + /* Logitech */ + {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187}, /* Netgear */ {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, @@ -57,8 +61,16 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { /* Sitecom */ {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, + /* Sphairon Access Systems GmbH */ + {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, + /* Dick Smith Electronics */ + {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187}, /* Abocom */ {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, + /* Qcom */ + {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187}, + /* AirLive */ + {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187}, {} }; diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h index fde6e4c634e..a7cf550b9cc 100644 --- a/drivers/scsi/cxgb3i/cxgb3i.h +++ b/drivers/scsi/cxgb3i/cxgb3i.h @@ -20,6 +20,7 @@ #include <linux/list.h> #include <linux/netdevice.h> #include <linux/scatterlist.h> +#include <linux/skbuff.h> #include <scsi/libiscsi_tcp.h> /* from cxgb3 LLD */ @@ -113,6 +114,26 @@ struct cxgb3i_endpoint { struct cxgb3i_conn *cconn; }; +/** + * struct cxgb3i_task_data - private iscsi task data + * + * @nr_frags: # of coalesced page frags (from scsi sgl) + * @frags: coalesced page frags (from scsi sgl) + * @skb: tx pdu skb + * @offset: data offset for the next pdu + * @count: max. possible pdu payload + * @sgoffset: offset to the first sg entry for a given offset + */ +#define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512) +struct cxgb3i_task_data { + unsigned short nr_frags; + skb_frag_t frags[MAX_PDU_FRAGS]; + struct sk_buff *skb; + unsigned int offset; + unsigned int count; + unsigned int sgoffset; +}; + int cxgb3i_iscsi_init(void); void cxgb3i_iscsi_cleanup(void); diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index 08f3a09d923..a83d36e4926 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c @@ -639,10 +639,11 @@ static int ddp_init(struct t3cdev *tdev) write_unlock(&cxgb3i_ddp_rwlock); ddp_log_info("nppods %u (0x%x ~ 0x%x), bits %u, mask 0x%x,0x%x " - "pkt %u,%u.\n", + "pkt %u/%u, %u/%u.\n", ppmax, ddp->llimit, ddp->ulimit, ddp->idx_bits, ddp->idx_mask, ddp->rsvd_tag_mask, - ddp->max_txsz, ddp->max_rxsz); + ddp->max_txsz, uinfo.max_txsz, + ddp->max_rxsz, uinfo.max_rxsz); return 0; free_ddp_map: @@ -654,8 +655,8 @@ free_ddp_map: * cxgb3i_adapter_ddp_init - initialize the adapter's ddp resource * @tdev: t3cdev adapter * @tformat: tag format - * @txsz: max tx pkt size, filled in by this func. - * @rxsz: max rx pkt size, filled in by this func. + * @txsz: max tx pdu payload size, filled in by this func. + * @rxsz: max rx pdu payload size, filled in by this func. * initialize the ddp pagepod manager for a given adapter if needed and * setup the tag format for a given iscsi entity */ @@ -685,10 +686,12 @@ int cxgb3i_adapter_ddp_init(struct t3cdev *tdev, tformat->sw_bits, tformat->rsvd_bits, tformat->rsvd_shift, tformat->rsvd_mask); - *txsz = ddp->max_txsz; - *rxsz = ddp->max_rxsz; - ddp_log_info("ddp max pkt size: %u, %u.\n", - ddp->max_txsz, ddp->max_rxsz); + *txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, + ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN); + *rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, + ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN); + ddp_log_info("max payload size: %u/%u, %u/%u.\n", + *txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz); return 0; } EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_init); diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h index 5c7c4d95c49..3faae7831c8 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h @@ -13,6 +13,8 @@ #ifndef __CXGB3I_ULP2_DDP_H__ #define __CXGB3I_ULP2_DDP_H__ +#include <linux/vmalloc.h> + /** * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity * @@ -85,8 +87,9 @@ struct cxgb3i_ddp_info { struct sk_buff **gl_skb; }; +#define ISCSI_PDU_NONPAYLOAD_LEN 312 /* bhs(48) + ahs(256) + digest(8) */ #define ULP2_MAX_PKT_SIZE 16224 -#define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_MAX) +#define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN) #define PPOD_PAGES_MAX 4 #define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */ diff --git a/drivers/scsi/cxgb3i/cxgb3i_init.c b/drivers/scsi/cxgb3i/cxgb3i_init.c index 091ecb4d9f3..1ce9f244e46 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_init.c +++ b/drivers/scsi/cxgb3i/cxgb3i_init.c @@ -12,8 +12,8 @@ #include "cxgb3i.h" #define DRV_MODULE_NAME "cxgb3i" -#define DRV_MODULE_VERSION "1.0.0" -#define DRV_MODULE_RELDATE "Jun. 1, 2008" +#define DRV_MODULE_VERSION "1.0.1" +#define DRV_MODULE_RELDATE "Jan. 2009" static char version[] = "Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index d83464b9b3f..fa2a44f37b3 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c @@ -364,7 +364,8 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth, cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, cmds_max, - sizeof(struct iscsi_tcp_task), + sizeof(struct iscsi_tcp_task) + + sizeof(struct cxgb3i_task_data), initial_cmdsn, ISCSI_MAX_TARGET); if (!cls_session) return NULL; @@ -402,17 +403,15 @@ static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn) { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct cxgb3i_conn *cconn = tcp_conn->dd_data; - unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, - cconn->hba->snic->tx_max_size - - ISCSI_PDU_NONPAYLOAD_MAX); + unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM); + max = min(cconn->hba->snic->tx_max_size, max); if (conn->max_xmit_dlength) - conn->max_xmit_dlength = min_t(unsigned int, - conn->max_xmit_dlength, max); + conn->max_xmit_dlength = min(conn->max_xmit_dlength, max); else conn->max_xmit_dlength = max; align_pdu_size(conn->max_xmit_dlength); - cxgb3i_log_info("conn 0x%p, max xmit %u.\n", + cxgb3i_api_debug("conn 0x%p, max xmit %u.\n", conn, conn->max_xmit_dlength); return 0; } @@ -427,9 +426,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn) { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct cxgb3i_conn *cconn = tcp_conn->dd_data; - unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, - cconn->hba->snic->rx_max_size - - ISCSI_PDU_NONPAYLOAD_MAX); + unsigned int max = cconn->hba->snic->rx_max_size; align_pdu_size(max); if (conn->max_recv_dlength) { @@ -439,8 +436,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn) conn->max_recv_dlength, max); return -EINVAL; } - conn->max_recv_dlength = min_t(unsigned int, - conn->max_recv_dlength, max); + conn->max_recv_dlength = min(conn->max_recv_dlength, max); align_pdu_size(conn->max_recv_dlength); } else conn->max_recv_dlength = max; @@ -844,7 +840,7 @@ static struct scsi_host_template cxgb3i_host_template = { .proc_name = "cxgb3i", .queuecommand = iscsi_queuecommand, .change_queue_depth = iscsi_change_queue_depth, - .can_queue = 128 * (ISCSI_DEF_XMIT_CMDS_MAX - 1), + .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1, .sg_tablesize = SG_ALL, .max_sectors = 0xFFFF, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index a865f1fefe8..de3b3b614cc 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c @@ -23,19 +23,19 @@ #include "cxgb3i_ddp.h" #ifdef __DEBUG_C3CN_CONN__ -#define c3cn_conn_debug cxgb3i_log_info +#define c3cn_conn_debug cxgb3i_log_debug #else #define c3cn_conn_debug(fmt...) #endif #ifdef __DEBUG_C3CN_TX__ -#define c3cn_tx_debug cxgb3i_log_debug +#define c3cn_tx_debug cxgb3i_log_debug #else #define c3cn_tx_debug(fmt...) #endif #ifdef __DEBUG_C3CN_RX__ -#define c3cn_rx_debug cxgb3i_log_debug +#define c3cn_rx_debug cxgb3i_log_debug #else #define c3cn_rx_debug(fmt...) #endif @@ -47,9 +47,9 @@ static int cxgb3_rcv_win = 256 * 1024; module_param(cxgb3_rcv_win, int, 0644); MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)"); -static int cxgb3_snd_win = 64 * 1024; +static int cxgb3_snd_win = 128 * 1024; module_param(cxgb3_snd_win, int, 0644); -MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=64KB)"); +MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=128KB)"); static int cxgb3_rx_credit_thres = 10 * 1024; module_param(cxgb3_rx_credit_thres, int, 0644); @@ -301,8 +301,8 @@ static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb) static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb, int flags) { - CXGB3_SKB_CB(skb)->seq = c3cn->write_seq; - CXGB3_SKB_CB(skb)->flags = flags; + skb_tcp_seq(skb) = c3cn->write_seq; + skb_flags(skb) = flags; __skb_queue_tail(&c3cn->write_queue, skb); } @@ -457,12 +457,9 @@ static unsigned int wrlen __read_mostly; * The number of WRs needed for an skb depends on the number of fragments * in the skb and whether it has any payload in its main body. This maps the * length of the gather list represented by an skb into the # of necessary WRs. - * - * The max. length of an skb is controlled by the max pdu size which is ~16K. - * Also, assume the min. fragment length is the sector size (512), then add - * extra fragment counts for iscsi bhs and payload padding. + * The extra two fragments are for iscsi bhs and payload padding. */ -#define SKB_WR_LIST_SIZE (16384/512 + 3) +#define SKB_WR_LIST_SIZE (MAX_SKB_FRAGS + 2) static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly; static void s3_init_wr_tab(unsigned int wr_len) @@ -485,7 +482,7 @@ static void s3_init_wr_tab(unsigned int wr_len) static inline void reset_wr_list(struct s3_conn *c3cn) { - c3cn->wr_pending_head = NULL; + c3cn->wr_pending_head = c3cn->wr_pending_tail = NULL; } /* @@ -496,7 +493,7 @@ static inline void reset_wr_list(struct s3_conn *c3cn) static inline void enqueue_wr(struct s3_conn *c3cn, struct sk_buff *skb) { - skb_wr_data(skb) = NULL; + skb_tx_wr_next(skb) = NULL; /* * We want to take an extra reference since both us and the driver @@ -509,10 +506,22 @@ static inline void enqueue_wr(struct s3_conn *c3cn, if (!c3cn->wr_pending_head) c3cn->wr_pending_head = skb; else - skb_wr_data(skb) = skb; + skb_tx_wr_next(c3cn->wr_pending_tail) = skb; c3cn->wr_pending_tail = skb; } +static int count_pending_wrs(struct s3_conn *c3cn) +{ + int n = 0; + const struct sk_buff *skb = c3cn->wr_pending_head; + + while (skb) { + n += skb->csum; + skb = skb_tx_wr_next(skb); + } + return n; +} + static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn) { return c3cn->wr_pending_head; @@ -529,8 +538,8 @@ static inline struct sk_buff *dequeue_wr(struct s3_conn *c3cn) if (likely(skb)) { /* Don't bother clearing the tail */ - c3cn->wr_pending_head = skb_wr_data(skb); - skb_wr_data(skb) = NULL; + c3cn->wr_pending_head = skb_tx_wr_next(skb); + skb_tx_wr_next(skb) = NULL; } return skb; } @@ -543,13 +552,14 @@ static void purge_wr_queue(struct s3_conn *c3cn) } static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb, - int len) + int len, int req_completion) { struct tx_data_wr *req; skb_reset_transport_header(skb); req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req)); - req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)); + req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) | + (req_completion ? F_WR_COMPL : 0)); req->wr_lo = htonl(V_WR_TID(c3cn->tid)); req->sndseq = htonl(c3cn->snd_nxt); /* len includes the length of any HW ULP additions */ @@ -592,7 +602,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) if (unlikely(c3cn->state == C3CN_STATE_CONNECTING || c3cn->state == C3CN_STATE_CLOSE_WAIT_1 || - c3cn->state == C3CN_STATE_ABORTING)) { + c3cn->state >= C3CN_STATE_ABORTING)) { c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n", c3cn, c3cn->state); return 0; @@ -615,7 +625,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) if (c3cn->wr_avail < wrs_needed) { c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, " "wr %d < %u.\n", - c3cn, skb->len, skb->datalen, frags, + c3cn, skb->len, skb->data_len, frags, wrs_needed, c3cn->wr_avail); break; } @@ -627,20 +637,24 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) c3cn->wr_unacked += wrs_needed; enqueue_wr(c3cn, skb); - if (likely(CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_NEED_HDR)) { - len += ulp_extra_len(skb); - make_tx_data_wr(c3cn, skb, len); - c3cn->snd_nxt += len; - if ((req_completion - && c3cn->wr_unacked == wrs_needed) - || (CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_COMPL) - || c3cn->wr_unacked >= c3cn->wr_max / 2) { - struct work_request_hdr *wr = cplhdr(skb); + c3cn_tx_debug("c3cn 0x%p, enqueue, skb len %u/%u, frag %u, " + "wr %d, left %u, unack %u.\n", + c3cn, skb->len, skb->data_len, frags, + wrs_needed, c3cn->wr_avail, c3cn->wr_unacked); + - wr->wr_hi |= htonl(F_WR_COMPL); + if (likely(skb_flags(skb) & C3CB_FLAG_NEED_HDR)) { + if ((req_completion && + c3cn->wr_unacked == wrs_needed) || + (skb_flags(skb) & C3CB_FLAG_COMPL) || + c3cn->wr_unacked >= c3cn->wr_max / 2) { + req_completion = 1; c3cn->wr_unacked = 0; } - CXGB3_SKB_CB(skb)->flags &= ~C3CB_FLAG_NEED_HDR; + len += ulp_extra_len(skb); + make_tx_data_wr(c3cn, skb, len, req_completion); + c3cn->snd_nxt += len; + skb_flags(skb) &= ~C3CB_FLAG_NEED_HDR; } total_size += skb->truesize; @@ -735,8 +749,11 @@ static void process_act_establish(struct s3_conn *c3cn, struct sk_buff *skb) if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED))) /* upper layer has requested closing */ send_abort_req(c3cn); - else if (c3cn_push_tx_frames(c3cn, 1)) + else { + if (skb_queue_len(&c3cn->write_queue)) + c3cn_push_tx_frames(c3cn, 1); cxgb3i_conn_tx_open(c3cn); + } } static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb, @@ -1082,8 +1099,8 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) return; } - CXGB3_SKB_CB(skb)->seq = ntohl(hdr_cpl->seq); - CXGB3_SKB_CB(skb)->flags = 0; + skb_tcp_seq(skb) = ntohl(hdr_cpl->seq); + skb_flags(skb) = 0; skb_reset_transport_header(skb); __skb_pull(skb, sizeof(struct cpl_iscsi_hdr)); @@ -1103,12 +1120,12 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) goto abort_conn; skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY; - skb_ulp_pdulen(skb) = ntohs(ddp_cpl.len); - skb_ulp_ddigest(skb) = ntohl(ddp_cpl.ulp_crc); + skb_rx_pdulen(skb) = ntohs(ddp_cpl.len); + skb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc); status = ntohl(ddp_cpl.ddp_status); c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n", - skb, skb->len, skb_ulp_pdulen(skb), status); + skb, skb->len, skb_rx_pdulen(skb), status); if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT)) skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR; @@ -1126,7 +1143,7 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) } else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT)) skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED; - c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_ulp_pdulen(skb); + c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_rx_pdulen(skb); __pskb_trim(skb, len); __skb_queue_tail(&c3cn->receive_queue, skb); cxgb3i_conn_pdu_ready(c3cn); @@ -1151,12 +1168,27 @@ static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx) * Process an acknowledgment of WR completion. Advance snd_una and send the * next batch of work requests from the write queue. */ +static void check_wr_invariants(struct s3_conn *c3cn) +{ + int pending = count_pending_wrs(c3cn); + + if (unlikely(c3cn->wr_avail + pending != c3cn->wr_max)) + cxgb3i_log_error("TID %u: credit imbalance: avail %u, " + "pending %u, total should be %u\n", + c3cn->tid, c3cn->wr_avail, pending, + c3cn->wr_max); +} + static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) { struct cpl_wr_ack *hdr = cplhdr(skb); unsigned int credits = ntohs(hdr->credits); u32 snd_una = ntohl(hdr->snd_una); + c3cn_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u.\n", + credits, c3cn->wr_avail, c3cn->wr_unacked, + c3cn->tid, c3cn->state); + c3cn->wr_avail += credits; if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail) c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail; @@ -1171,6 +1203,17 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) break; } if (unlikely(credits < p->csum)) { + struct tx_data_wr *w = cplhdr(p); + cxgb3i_log_error("TID %u got %u WR credits need %u, " + "len %u, main body %u, frags %u, " + "seq # %u, ACK una %u, ACK nxt %u, " + "WR_AVAIL %u, WRs pending %u\n", + c3cn->tid, credits, p->csum, p->len, + p->len - p->data_len, + skb_shinfo(p)->nr_frags, + ntohl(w->sndseq), snd_una, + ntohl(hdr->snd_nxt), c3cn->wr_avail, + count_pending_wrs(c3cn) - credits); p->csum -= credits; break; } else { @@ -1180,15 +1223,24 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) } } - if (unlikely(before(snd_una, c3cn->snd_una))) + check_wr_invariants(c3cn); + + if (unlikely(before(snd_una, c3cn->snd_una))) { + cxgb3i_log_error("TID %u, unexpected sequence # %u in WR_ACK " + "snd_una %u\n", + c3cn->tid, snd_una, c3cn->snd_una); goto out_free; + } if (c3cn->snd_una != snd_una) { c3cn->snd_una = snd_una; dst_confirm(c3cn->dst_cache); } - if (skb_queue_len(&c3cn->write_queue) && c3cn_push_tx_frames(c3cn, 0)) + if (skb_queue_len(&c3cn->write_queue)) { + if (c3cn_push_tx_frames(c3cn, 0)) + cxgb3i_conn_tx_open(c3cn); + } else cxgb3i_conn_tx_open(c3cn); out_free: __kfree_skb(skb); @@ -1452,7 +1504,7 @@ static void init_offload_conn(struct s3_conn *c3cn, struct dst_entry *dst) { BUG_ON(c3cn->cdev != cdev); - c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs; + c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs - 1; c3cn->wr_unacked = 0; c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst)); @@ -1671,9 +1723,17 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb) goto out_err; } - err = -EPIPE; if (c3cn->err) { c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err); + err = -EPIPE; + goto out_err; + } + + if (c3cn->write_seq - c3cn->snd_una >= cxgb3_snd_win) { + c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n", + c3cn, c3cn->write_seq, c3cn->snd_una, + cxgb3_snd_win); + err = -EAGAIN; goto out_err; } diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h index d23156907ff..6344b9eb258 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.h +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.h @@ -178,25 +178,33 @@ void cxgb3i_c3cn_release(struct s3_conn *); * @flag: see C3CB_FLAG_* below * @ulp_mode: ULP mode/submode of sk_buff * @seq: tcp sequence number - * @ddigest: pdu data digest - * @pdulen: recovered pdu length - * @wr_data: scratch area for tx wr */ +struct cxgb3_skb_rx_cb { + __u32 ddigest; /* data digest */ + __u32 pdulen; /* recovered pdu length */ +}; + +struct cxgb3_skb_tx_cb { + struct sk_buff *wr_next; /* next wr */ +}; + struct cxgb3_skb_cb { __u8 flags; __u8 ulp_mode; __u32 seq; - __u32 ddigest; - __u32 pdulen; - struct sk_buff *wr_data; + union { + struct cxgb3_skb_rx_cb rx; + struct cxgb3_skb_tx_cb tx; + }; }; #define CXGB3_SKB_CB(skb) ((struct cxgb3_skb_cb *)&((skb)->cb[0])) - +#define skb_flags(skb) (CXGB3_SKB_CB(skb)->flags) #define skb_ulp_mode(skb) (CXGB3_SKB_CB(skb)->ulp_mode) -#define skb_ulp_ddigest(skb) (CXGB3_SKB_CB(skb)->ddigest) -#define skb_ulp_pdulen(skb) (CXGB3_SKB_CB(skb)->pdulen) -#define skb_wr_data(skb) (CXGB3_SKB_CB(skb)->wr_data) +#define skb_tcp_seq(skb) (CXGB3_SKB_CB(skb)->seq) +#define skb_rx_ddigest(skb) (CXGB3_SKB_CB(skb)->rx.ddigest) +#define skb_rx_pdulen(skb) (CXGB3_SKB_CB(skb)->rx.pdulen) +#define skb_tx_wr_next(skb) (CXGB3_SKB_CB(skb)->tx.wr_next) enum c3cb_flags { C3CB_FLAG_NEED_HDR = 1 << 0, /* packet needs a TX_DATA_WR header */ @@ -217,6 +225,7 @@ struct sge_opaque_hdr { /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */ #define TX_HEADER_LEN \ (sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr)) +#define SKB_TX_HEADROOM SKB_MAX_HEAD(TX_HEADER_LEN) /* * get and set private ip for iscsi traffic diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c index ce7ce8c6094..17115c230d6 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c @@ -32,6 +32,10 @@ #define cxgb3i_tx_debug(fmt...) #endif +/* always allocate rooms for AHS */ +#define SKB_TX_PDU_HEADER_LEN \ + (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE) +static unsigned int skb_extra_headroom; static struct page *pad_page; /* @@ -146,12 +150,13 @@ static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc) void cxgb3i_conn_cleanup_task(struct iscsi_task *task) { - struct iscsi_tcp_task *tcp_task = task->dd_data; + struct cxgb3i_task_data *tdata = task->dd_data + + sizeof(struct iscsi_tcp_task); /* never reached the xmit task callout */ - if (tcp_task->dd_data) - kfree_skb(tcp_task->dd_data); - tcp_task->dd_data = NULL; + if (tdata->skb) + __kfree_skb(tdata->skb); + memset(tdata, 0, sizeof(struct cxgb3i_task_data)); /* MNC - Do we need a check in case this is called but * cxgb3i_conn_alloc_pdu has never been called on the task */ @@ -159,28 +164,102 @@ void cxgb3i_conn_cleanup_task(struct iscsi_task *task) iscsi_tcp_cleanup_task(task); } -/* - * We do not support ahs yet - */ +static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt, + unsigned int offset, unsigned int *off, + struct scatterlist **sgp) +{ + int i; + struct scatterlist *sg; + + for_each_sg(sgl, sg, sgcnt, i) { + if (offset < sg->length) { + *off = offset; + *sgp = sg; + return 0; + } + offset -= sg->length; + } + return -EFAULT; +} + +static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, + unsigned int dlen, skb_frag_t *frags, + int frag_max) +{ + unsigned int datalen = dlen; + unsigned int sglen = sg->length - sgoffset; + struct page *page = sg_page(sg); + int i; + + i = 0; + do { + unsigned int copy; + + if (!sglen) { + sg = sg_next(sg); + if (!sg) { + cxgb3i_log_error("%s, sg NULL, len %u/%u.\n", + __func__, datalen, dlen); + return -EINVAL; + } + sgoffset = 0; + sglen = sg->length; + page = sg_page(sg); + + } + copy = min(datalen, sglen); + if (i && page == frags[i - 1].page && + sgoffset + sg->offset == + frags[i - 1].page_offset + frags[i - 1].size) { + frags[i - 1].size += copy; + } else { + if (i >= frag_max) { + cxgb3i_log_error("%s, too many pages %u, " + "dlen %u.\n", __func__, + frag_max, dlen); + return -EINVAL; + } + + frags[i].page = page; + frags[i].page_offset = sg->offset + sgoffset; + frags[i].size = copy; + i++; + } + datalen -= copy; + sgoffset += copy; + sglen -= copy; + } while (datalen); + + return i; +} + int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) { + struct iscsi_conn *conn = task->conn; struct iscsi_tcp_task *tcp_task = task->dd_data; - struct sk_buff *skb; + struct cxgb3i_task_data *tdata = task->dd_data + sizeof(*tcp_task); + struct scsi_cmnd *sc = task->sc; + int headroom = SKB_TX_PDU_HEADER_LEN; + tcp_task->dd_data = tdata; task->hdr = NULL; - /* always allocate rooms for AHS */ - skb = alloc_skb(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + - TX_HEADER_LEN, GFP_ATOMIC); - if (!skb) + + /* write command, need to send data pdus */ + if (skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT || + (opcode == ISCSI_OP_SCSI_CMD && + (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE)))) + headroom += min(skb_extra_headroom, conn->max_xmit_dlength); + + tdata->skb = alloc_skb(TX_HEADER_LEN + headroom, GFP_ATOMIC); + if (!tdata->skb) return -ENOMEM; + skb_reserve(tdata->skb, TX_HEADER_LEN); cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n", - task, opcode, skb); + task, opcode, tdata->skb); - tcp_task->dd_data = skb; - skb_reserve(skb, TX_HEADER_LEN); - task->hdr = (struct iscsi_hdr *)skb->data; - task->hdr_max = sizeof(struct iscsi_hdr); + task->hdr = (struct iscsi_hdr *)tdata->skb->data; + task->hdr_max = SKB_TX_PDU_HEADER_LEN; /* data_out uses scsi_cmd's itt */ if (opcode != ISCSI_OP_SCSI_DATA_OUT) @@ -192,13 +271,13 @@ int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, unsigned int count) { - struct iscsi_tcp_task *tcp_task = task->dd_data; - struct sk_buff *skb = tcp_task->dd_data; struct iscsi_conn *conn = task->conn; - struct page *pg; + struct iscsi_tcp_task *tcp_task = task->dd_data; + struct cxgb3i_task_data *tdata = tcp_task->dd_data; + struct sk_buff *skb = tdata->skb; unsigned int datalen = count; int i, padlen = iscsi_padding(count); - skb_frag_t *frag; + struct page *pg; cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n", task, task->sc, offset, count, skb); @@ -209,90 +288,94 @@ int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, return 0; if (task->sc) { - struct scatterlist *sg; - struct scsi_data_buffer *sdb; - unsigned int sgoffset = offset; - struct page *sgpg; - unsigned int sglen; - - sdb = scsi_out(task->sc); - sg = sdb->table.sgl; - - for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) { - cxgb3i_tx_debug("sg %d, page 0x%p, len %u offset %u\n", - i, sg_page(sg), sg->length, sg->offset); - - if (sgoffset < sg->length) - break; - sgoffset -= sg->length; + struct scsi_data_buffer *sdb = scsi_out(task->sc); + struct scatterlist *sg = NULL; + int err; + + tdata->offset = offset; + tdata->count = count; + err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents, + tdata->offset, &tdata->sgoffset, &sg); + if (err < 0) { + cxgb3i_log_warn("tpdu, sgl %u, bad offset %u/%u.\n", + sdb->table.nents, tdata->offset, + sdb->length); + return err; } - sgpg = sg_page(sg); - sglen = sg->length - sgoffset; - - do { - int j = skb_shinfo(skb)->nr_frags; - unsigned int copy; - - if (!sglen) { - sg = sg_next(sg); - sgpg = sg_page(sg); - sgoffset = 0; - sglen = sg->length; - ++i; + err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count, + tdata->frags, MAX_PDU_FRAGS); + if (err < 0) { + cxgb3i_log_warn("tpdu, sgl %u, bad offset %u + %u.\n", + sdb->table.nents, tdata->offset, + tdata->count); + return err; + } + tdata->nr_frags = err; + + if (tdata->nr_frags > MAX_SKB_FRAGS || + (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) { + char *dst = skb->data + task->hdr_len; + skb_frag_t *frag = tdata->frags; + + /* data fits in the skb's headroom */ + for (i = 0; i < tdata->nr_frags; i++, frag++) { + char *src = kmap_atomic(frag->page, + KM_SOFTIRQ0); + + memcpy(dst, src+frag->page_offset, frag->size); + dst += frag->size; + kunmap_atomic(src, KM_SOFTIRQ0); } - copy = min(sglen, datalen); - if (j && skb_can_coalesce(skb, j, sgpg, - sg->offset + sgoffset)) { - skb_shinfo(skb)->frags[j - 1].size += copy; - } else { - get_page(sgpg); - skb_fill_page_desc(skb, j, sgpg, - sg->offset + sgoffset, copy); + if (padlen) { + memset(dst, 0, padlen); + padlen = 0; } - sgoffset += copy; - sglen -= copy; - datalen -= copy; - } while (datalen); + skb_put(skb, count + padlen); + } else { + /* data fit into frag_list */ + for (i = 0; i < tdata->nr_frags; i++) + get_page(tdata->frags[i].page); + + memcpy(skb_shinfo(skb)->frags, tdata->frags, + sizeof(skb_frag_t) * tdata->nr_frags); + skb_shinfo(skb)->nr_frags = tdata->nr_frags; + skb->len += count; + skb->data_len += count; + skb->truesize += count; + } + } else { pg = virt_to_page(task->data); - while (datalen) { - i = skb_shinfo(skb)->nr_frags; - frag = &skb_shinfo(skb)->frags[i]; - - get_page(pg); - frag->page = pg; - frag->page_offset = 0; - frag->size = min((unsigned int)PAGE_SIZE, datalen); - - skb_shinfo(skb)->nr_frags++; - datalen -= frag->size; - pg++; - } + get_page(pg); + skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data), + count); + skb->len += count; + skb->data_len += count; + skb->truesize += count; } if (padlen) { i = skb_shinfo(skb)->nr_frags; - frag = &skb_shinfo(skb)->frags[i]; - frag->page = pad_page; - frag->page_offset = 0; - frag->size = padlen; - skb_shinfo(skb)->nr_frags++; + get_page(pad_page); + skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, pad_page, 0, + padlen); + + skb->data_len += padlen; + skb->truesize += padlen; + skb->len += padlen; } - datalen = count + padlen; - skb->data_len += datalen; - skb->truesize += datalen; - skb->len += datalen; return 0; } int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) { - struct iscsi_tcp_task *tcp_task = task->dd_data; - struct sk_buff *skb = tcp_task->dd_data; struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; struct cxgb3i_conn *cconn = tcp_conn->dd_data; + struct iscsi_tcp_task *tcp_task = task->dd_data; + struct cxgb3i_task_data *tdata = tcp_task->dd_data; + struct sk_buff *skb = tdata->skb; unsigned int datalen; int err; @@ -300,13 +383,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) return 0; datalen = skb->data_len; - tcp_task->dd_data = NULL; + tdata->skb = NULL; err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb); - cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n", - task, skb, skb->len, skb->data_len, err); if (err > 0) { int pdulen = err; + cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n", + task, skb, skb->len, skb->data_len, err); + if (task->conn->hdrdgst_en) pdulen += ISCSI_DIGEST_SIZE; if (datalen && task->conn->datadgst_en) @@ -325,12 +409,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) return err; } /* reset skb to send when we are called again */ - tcp_task->dd_data = skb; + tdata->skb = skb; return -EAGAIN; } int cxgb3i_pdu_init(void) { + if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS)) + skb_extra_headroom = SKB_TX_HEADROOM; pad_page = alloc_page(GFP_KERNEL); if (!pad_page) return -ENOMEM; @@ -366,7 +452,9 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn) skb = skb_peek(&c3cn->receive_queue); while (!err && skb) { __skb_unlink(skb, &c3cn->receive_queue); - read += skb_ulp_pdulen(skb); + read += skb_rx_pdulen(skb); + cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n", + conn, c3cn, skb, skb_rx_pdulen(skb)); err = cxgb3i_conn_read_pdu_skb(conn, skb); __kfree_skb(skb); skb = skb_peek(&c3cn->receive_queue); @@ -377,6 +465,11 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn) cxgb3i_c3cn_rx_credits(c3cn, read); } conn->rxdata_octets += read; + + if (err) { + cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + } } void cxgb3i_conn_tx_open(struct s3_conn *c3cn) diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.h b/drivers/scsi/cxgb3i/cxgb3i_pdu.h index a3f685cc236..0770b23d90d 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.h +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.h @@ -53,7 +53,7 @@ struct cpl_rx_data_ddp_norss { #define ULP2_FLAG_DCRC_ERROR 0x20 #define ULP2_FLAG_PAD_ERROR 0x40 -void cxgb3i_conn_closing(struct s3_conn *); +void cxgb3i_conn_closing(struct s3_conn *c3cn); void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn); void cxgb3i_conn_tx_open(struct s3_conn *c3cn); #endif diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index a48e4990fe1..34be88d7afa 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1251,6 +1251,7 @@ static struct pci_device_id hptiop_id_table[] = { { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops }, + { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops }, diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 940dc32ff0d..b82ffd90632 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1040,12 +1040,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) action = ACTION_FAIL; break; case ABORTED_COMMAND: + action = ACTION_FAIL; if (sshdr.asc == 0x10) { /* DIF */ description = "Target Data Integrity Failure"; - action = ACTION_FAIL; error = -EILSEQ; - } else - action = ACTION_RETRY; + } break; case NOT_READY: /* If the device is in the process of becoming diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d57566b8be0..55310dbc10a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -107,6 +107,7 @@ static void scsi_disk_release(struct device *cdev); static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); static void sd_print_result(struct scsi_disk *, int); +static DEFINE_SPINLOCK(sd_index_lock); static DEFINE_IDA(sd_index_ida); /* This semaphore is used to mediate the 0->1 reference get in the @@ -1914,7 +1915,9 @@ static int sd_probe(struct device *dev) if (!ida_pre_get(&sd_index_ida, GFP_KERNEL)) goto out_put; + spin_lock(&sd_index_lock); error = ida_get_new(&sd_index_ida, &index); + spin_unlock(&sd_index_lock); } while (error == -EAGAIN); if (error) @@ -1936,7 +1939,9 @@ static int sd_probe(struct device *dev) return 0; out_free_index: + spin_lock(&sd_index_lock); ida_remove(&sd_index_ida, index); + spin_unlock(&sd_index_lock); out_put: put_disk(gd); out_free: @@ -1986,7 +1991,9 @@ static void scsi_disk_release(struct device *dev) struct scsi_disk *sdkp = to_scsi_disk(dev); struct gendisk *disk = sdkp->disk; + spin_lock(&sd_index_lock); ida_remove(&sd_index_ida, sdkp->index); + spin_unlock(&sd_index_lock); disk->private_data = NULL; put_disk(disk); diff --git a/fs/Makefile b/fs/Makefile index 38bc735c67a..dc20db34867 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -69,10 +69,12 @@ obj-$(CONFIG_DLM) += dlm/ # Do not add any filesystems before this line obj-$(CONFIG_REISERFS_FS) += reiserfs/ obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3 -obj-$(CONFIG_EXT4_FS) += ext4/ # Before ext2 so root fs can be ext4 +obj-$(CONFIG_EXT2_FS) += ext2/ +# We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2 +# unless explicitly requested by rootfstype +obj-$(CONFIG_EXT4_FS) += ext4/ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ -obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ obj-$(CONFIG_SQUASHFS) += squashfs/ obj-y += ramfs/ diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 9a50b8052dc..de9459b4cb9 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -609,7 +609,9 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi, */ int ext4_should_retry_alloc(struct super_block *sb, int *retries) { - if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || (*retries)++ > 3) + if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || + (*retries)++ > 3 || + !EXT4_SB(sb)->s_journal) return 0; jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 51cdd13e1c3..c7fed5b1874 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2544,7 +2544,7 @@ retry: ext4_journal_stop(handle); - if (mpd.retval == -ENOSPC) { + if ((mpd.retval == -ENOSPC) && sbi->s_journal) { /* commit the transaction which would * free blocks released in the transaction * and try again diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a5732c58f67..39d1993cfa1 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3091,7 +3091,6 @@ static int ext4_freeze(struct super_block *sb) /* Journal blocked and flushed, clear needs_recovery flag. */ EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); - ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); if (error) goto out; diff --git a/include/linux/Kbuild b/include/linux/Kbuild index b97cdc516a8..106c3ba5084 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -52,6 +52,7 @@ header-y += const.h header-y += cgroupstats.h header-y += cramfs_fs.h header-y += cycx_cfm.h +header-y += dcbnl.h header-y += dlmconstants.h header-y += dlm_device.h header-y += dlm_netlink.h diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index b0ef274e003..7d2e1000618 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h @@ -20,10 +20,12 @@ #ifndef __LINUX_DCBNL_H__ #define __LINUX_DCBNL_H__ +#include <linux/types.h> + #define DCB_PROTO_VERSION 1 struct dcbmsg { - unsigned char dcb_family; + __u8 dcb_family; __u8 cmd; __u16 dcb_pad; }; diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index cbc2f0cd631..0adb0f91568 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h @@ -91,8 +91,11 @@ io_mapping_unmap_atomic(void *vaddr) static inline void * io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) { + resource_size_t phys_addr; + BUG_ON(offset >= mapping->size); - resource_size_t phys_addr = mapping->base + offset; + phys_addr = mapping->base + offset; + return ioremap_wc(phys_addr, PAGE_SIZE); } diff --git a/include/linux/netfilter/xt_NFLOG.h b/include/linux/netfilter/xt_NFLOG.h index cdcd0ed58f7..4b36aeb46a1 100644 --- a/include/linux/netfilter/xt_NFLOG.h +++ b/include/linux/netfilter/xt_NFLOG.h @@ -2,7 +2,7 @@ #define _XT_NFLOG_TARGET #define XT_NFLOG_DEFAULT_GROUP 0x1 -#define XT_NFLOG_DEFAULT_THRESHOLD 1 +#define XT_NFLOG_DEFAULT_THRESHOLD 0 #define XT_NFLOG_MASK 0x0 diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index e78afe7f28e..c25068e3851 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -59,7 +59,7 @@ static inline int nf_conntrack_confirm(struct sk_buff *skb) struct nf_conn *ct = (struct nf_conn *)skb->nfct; int ret = NF_ACCEPT; - if (ct) { + if (ct && ct != &nf_conntrack_untracked) { if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) ret = __nf_conntrack_confirm(skb); nf_ct_deliver_cached_events(ct); diff --git a/init/Kconfig b/init/Kconfig index f068071fcc5..90003163e55 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -683,6 +683,8 @@ menuconfig EMBEDDED environments which can tolerate a "non-standard" kernel. Only use this if you really know what you are doing. +if EMBEDDED + config UID16 bool "Enable 16-bit UID system calls" if EMBEDDED depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION) @@ -780,18 +782,6 @@ config PCSPKR_PLATFORM This option allows to disable the internal PC-Speaker support, saving some memory. -config COMPAT_BRK - bool "Disable heap randomization" - default y - help - Randomizing heap placement makes heap exploits harder, but it - also breaks ancient binaries (including anything libc5 based). - This option changes the bootup default to heap randomization - disabled, and can be overriden runtime by setting - /proc/sys/kernel/randomize_va_space to 2. - - On non-ancient distros (post-2000 ones) N is usually a safe choice. - config BASE_FULL default y bool "Enable full-sized data structures for core" if EMBEDDED @@ -897,6 +887,20 @@ config SLUB_DEBUG SLUB sysfs support. /sys/slab will not exist and there will be no support for cache validation etc. +endif # EMBEDDED + +config COMPAT_BRK + bool "Disable heap randomization" + default y + help + Randomizing heap placement makes heap exploits harder, but it + also breaks ancient binaries (including anything libc5 based). + This option changes the bootup default to heap randomization + disabled, and can be overriden runtime by setting + /proc/sys/kernel/randomize_va_space to 2. + + On non-ancient distros (post-2000 ones) N is usually a safe choice. + choice prompt "Choose SLAB allocator" default SLUB diff --git a/kernel/seccomp.c b/kernel/seccomp.c index ad64fcb731f..57d4b13b631 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -8,6 +8,7 @@ #include <linux/seccomp.h> #include <linux/sched.h> +#include <linux/compat.h> /* #define SECCOMP_DEBUG 1 */ #define NR_SECCOMP_MODES 1 @@ -22,7 +23,7 @@ static int mode1_syscalls[] = { 0, /* null terminated */ }; -#ifdef TIF_32BIT +#ifdef CONFIG_COMPAT static int mode1_syscalls_32[] = { __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32, 0, /* null terminated */ @@ -37,8 +38,8 @@ void __secure_computing(int this_syscall) switch (mode) { case 1: syscall = mode1_syscalls; -#ifdef TIF_32BIT - if (test_thread_flag(TIF_32BIT)) +#ifdef CONFIG_COMPAT + if (is_compat_task()) syscall = mode1_syscalls_32; #endif do { diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index e9db889d622..2886d2fb9ab 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -1,12 +1,16 @@ #include <linux/skbuff.h> #include <linux/netdevice.h> #include <linux/if_vlan.h> +#include <linux/netpoll.h> #include "vlan.h" /* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling) { + if (netpoll_rx(skb)) + return NET_RX_DROP; + if (skb_bond_should_drop(skb)) goto drop; @@ -100,6 +104,9 @@ int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, { int err = NET_RX_SUCCESS; + if (netpoll_receive_skb(skb)) + return NET_RX_DROP; + switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { case -1: return netif_receive_skb(skb); @@ -126,6 +133,9 @@ int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, if (!skb) goto out; + if (netpoll_receive_skb(skb)) + goto out; + err = NET_RX_SUCCESS; switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { diff --git a/net/core/dev.c b/net/core/dev.c index a17e0066236..72b0d26fd46 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2488,6 +2488,9 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { + if (netpoll_receive_skb(skb)) + return NET_RX_DROP; + switch (__napi_gro_receive(napi, skb)) { case -1: return netif_receive_skb(skb); @@ -2558,6 +2561,9 @@ int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) if (!skb) goto out; + if (netpoll_receive_skb(skb)) + goto out; + err = NET_RX_SUCCESS; switch (__napi_gro_receive(napi, skb)) { diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a6961d75c7e..c28976a7e59 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1374,7 +1374,8 @@ static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk, static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, struct tcp_sacktag_state *state, - unsigned int pcount, int shifted, int mss) + unsigned int pcount, int shifted, int mss, + int dup_sack) { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *prev = tcp_write_queue_prev(sk, skb); @@ -1410,7 +1411,7 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, } /* We discard results */ - tcp_sacktag_one(skb, sk, state, 0, pcount); + tcp_sacktag_one(skb, sk, state, dup_sack, pcount); /* Difference in this won't matter, both ACKed by the same cumul. ACK */ TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS); @@ -1561,7 +1562,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, if (!skb_shift(prev, skb, len)) goto fallback; - if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss)) + if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss, dup_sack)) goto out; /* Hole filled allows collapsing with the next as well, this is very @@ -1580,7 +1581,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, len = skb->len; if (skb_shift(prev, skb, len)) { pcount += tcp_skb_pcount(skb); - tcp_shifted_skb(sk, skb, state, tcp_skb_pcount(skb), len, mss); + tcp_shifted_skb(sk, skb, state, tcp_skb_pcount(skb), len, mss, 0); } out: diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c index 2747ec7bfb6..4660b088a8c 100644 --- a/net/ipv4/tcp_scalable.c +++ b/net/ipv4/tcp_scalable.c @@ -1,6 +1,6 @@ /* Tom Kelly's Scalable TCP * - * See htt://www-lce.eng.cam.ac.uk/~ctk21/scalable/ + * See http://www.deneholme.net/tom/scalable/ * * John Heffner <jheffner@sc.edu> */ diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 8fe267feb81..1bcc3431859 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -258,11 +258,11 @@ unique: if (twp != NULL) { *twp = tw; - NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITRECYCLED); + NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED); } else if (tw != NULL) { /* Silly. Should hash-dance instead... */ inet_twsk_deschedule(tw, death_row); - NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITRECYCLED); + NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED); inet_twsk_put(tw); } diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index c323643ffcf..72dbb6d1a6b 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -201,8 +201,9 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, - "nf_ct_icmpv6: ICMPv6 checksum failed\n"); + if (LOG_INVALID(net, IPPROTO_ICMPV6)) + nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, + "nf_ct_icmpv6: ICMPv6 checksum failed "); return -NF_ACCEPT; } diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index fa49dc7fe10..c712e9fc6bb 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -39,7 +39,7 @@ #endif #define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE -#define NFULNL_TIMEOUT_DEFAULT HZ /* every second */ +#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ #define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ #define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */ @@ -590,8 +590,10 @@ nfulnl_log_packet(u_int8_t pf, qthreshold = inst->qthreshold; /* per-rule qthreshold overrides per-instance */ - if (qthreshold > li->u.ulog.qthreshold) - qthreshold = li->u.ulog.qthreshold; + if (li->u.ulog.qthreshold) + if (qthreshold > li->u.ulog.qthreshold) + qthreshold = li->u.ulog.qthreshold; + switch (inst->copy_mode) { case NFULNL_COPY_META: diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index bfbf521f6ea..5baccfa5a0d 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -827,59 +827,143 @@ static const struct file_operations xt_table_ops = { .release = seq_release_net, }; -static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) +/* + * Traverse state for ip{,6}_{tables,matches} for helping crossing + * the multi-AF mutexes. + */ +struct nf_mttg_trav { + struct list_head *head, *curr; + uint8_t class, nfproto; +}; + +enum { + MTTG_TRAV_INIT, + MTTG_TRAV_NFP_UNSPEC, + MTTG_TRAV_NFP_SPEC, + MTTG_TRAV_DONE, +}; + +static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos, + bool is_target) { - struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; - u_int16_t af = (unsigned long)pde->data; + static const uint8_t next_class[] = { + [MTTG_TRAV_NFP_UNSPEC] = MTTG_TRAV_NFP_SPEC, + [MTTG_TRAV_NFP_SPEC] = MTTG_TRAV_DONE, + }; + struct nf_mttg_trav *trav = seq->private; + + switch (trav->class) { + case MTTG_TRAV_INIT: + trav->class = MTTG_TRAV_NFP_UNSPEC; + mutex_lock(&xt[NFPROTO_UNSPEC].mutex); + trav->head = trav->curr = is_target ? + &xt[NFPROTO_UNSPEC].target : &xt[NFPROTO_UNSPEC].match; + break; + case MTTG_TRAV_NFP_UNSPEC: + trav->curr = trav->curr->next; + if (trav->curr != trav->head) + break; + mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); + mutex_lock(&xt[trav->nfproto].mutex); + trav->head = trav->curr = is_target ? + &xt[trav->nfproto].target : &xt[trav->nfproto].match; + trav->class = next_class[trav->class]; + break; + case MTTG_TRAV_NFP_SPEC: + trav->curr = trav->curr->next; + if (trav->curr != trav->head) + break; + /* fallthru, _stop will unlock */ + default: + return NULL; + } - mutex_lock(&xt[af].mutex); - return seq_list_start(&xt[af].match, *pos); + if (ppos != NULL) + ++*ppos; + return trav; } -static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *pos) +static void *xt_mttg_seq_start(struct seq_file *seq, loff_t *pos, + bool is_target) { - struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; - u_int16_t af = (unsigned long)pde->data; + struct nf_mttg_trav *trav = seq->private; + unsigned int j; - return seq_list_next(v, &xt[af].match, pos); + trav->class = MTTG_TRAV_INIT; + for (j = 0; j < *pos; ++j) + if (xt_mttg_seq_next(seq, NULL, NULL, is_target) == NULL) + return NULL; + return trav; } -static void xt_match_seq_stop(struct seq_file *seq, void *v) +static void xt_mttg_seq_stop(struct seq_file *seq, void *v) { - struct proc_dir_entry *pde = seq->private; - u_int16_t af = (unsigned long)pde->data; + struct nf_mttg_trav *trav = seq->private; + + switch (trav->class) { + case MTTG_TRAV_NFP_UNSPEC: + mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); + break; + case MTTG_TRAV_NFP_SPEC: + mutex_unlock(&xt[trav->nfproto].mutex); + break; + } +} - mutex_unlock(&xt[af].mutex); +static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) +{ + return xt_mttg_seq_start(seq, pos, false); } -static int xt_match_seq_show(struct seq_file *seq, void *v) +static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos) { - struct xt_match *match = list_entry(v, struct xt_match, list); + return xt_mttg_seq_next(seq, v, ppos, false); +} - if (strlen(match->name)) - return seq_printf(seq, "%s\n", match->name); - else - return 0; +static int xt_match_seq_show(struct seq_file *seq, void *v) +{ + const struct nf_mttg_trav *trav = seq->private; + const struct xt_match *match; + + switch (trav->class) { + case MTTG_TRAV_NFP_UNSPEC: + case MTTG_TRAV_NFP_SPEC: + if (trav->curr == trav->head) + return 0; + match = list_entry(trav->curr, struct xt_match, list); + return (*match->name == '\0') ? 0 : + seq_printf(seq, "%s\n", match->name); + } + return 0; } static const struct seq_operations xt_match_seq_ops = { .start = xt_match_seq_start, .next = xt_match_seq_next, - .stop = xt_match_seq_stop, + .stop = xt_mttg_seq_stop, .show = xt_match_seq_show, }; static int xt_match_open(struct inode *inode, struct file *file) { + struct seq_file *seq; + struct nf_mttg_trav *trav; int ret; - ret = seq_open(file, &xt_match_seq_ops); - if (!ret) { - struct seq_file *seq = file->private_data; + trav = kmalloc(sizeof(*trav), GFP_KERNEL); + if (trav == NULL) + return -ENOMEM; - seq->private = PDE(inode); + ret = seq_open(file, &xt_match_seq_ops); + if (ret < 0) { + kfree(trav); + return ret; } - return ret; + + seq = file->private_data; + seq->private = trav; + trav->nfproto = (unsigned long)PDE(inode)->data; + return 0; } static const struct file_operations xt_match_ops = { @@ -887,62 +971,63 @@ static const struct file_operations xt_match_ops = { .open = xt_match_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = seq_release_private, }; static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos) { - struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; - u_int16_t af = (unsigned long)pde->data; - - mutex_lock(&xt[af].mutex); - return seq_list_start(&xt[af].target, *pos); + return xt_mttg_seq_start(seq, pos, true); } -static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *pos) +static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *ppos) { - struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; - u_int16_t af = (unsigned long)pde->data; - - return seq_list_next(v, &xt[af].target, pos); -} - -static void xt_target_seq_stop(struct seq_file *seq, void *v) -{ - struct proc_dir_entry *pde = seq->private; - u_int16_t af = (unsigned long)pde->data; - - mutex_unlock(&xt[af].mutex); + return xt_mttg_seq_next(seq, v, ppos, true); } static int xt_target_seq_show(struct seq_file *seq, void *v) { - struct xt_target *target = list_entry(v, struct xt_target, list); - - if (strlen(target->name)) - return seq_printf(seq, "%s\n", target->name); - else - return 0; + const struct nf_mttg_trav *trav = seq->private; + const struct xt_target *target; + + switch (trav->class) { + case MTTG_TRAV_NFP_UNSPEC: + case MTTG_TRAV_NFP_SPEC: + if (trav->curr == trav->head) + return 0; + target = list_entry(trav->curr, struct xt_target, list); + return (*target->name == '\0') ? 0 : + seq_printf(seq, "%s\n", target->name); + } + return 0; } static const struct seq_operations xt_target_seq_ops = { .start = xt_target_seq_start, .next = xt_target_seq_next, - .stop = xt_target_seq_stop, + .stop = xt_mttg_seq_stop, .show = xt_target_seq_show, }; static int xt_target_open(struct inode *inode, struct file *file) { + struct seq_file *seq; + struct nf_mttg_trav *trav; int ret; - ret = seq_open(file, &xt_target_seq_ops); - if (!ret) { - struct seq_file *seq = file->private_data; + trav = kmalloc(sizeof(*trav), GFP_KERNEL); + if (trav == NULL) + return -ENOMEM; - seq->private = PDE(inode); + ret = seq_open(file, &xt_target_seq_ops); + if (ret < 0) { + kfree(trav); + return ret; } - return ret; + + seq = file->private_data; + seq->private = trav; + trav->nfproto = (unsigned long)PDE(inode)->data; + return 0; } static const struct file_operations xt_target_ops = { @@ -950,7 +1035,7 @@ static const struct file_operations xt_target_ops = { .open = xt_target_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = seq_release_private, }; #define FORMAT_TABLES "_tables_names" diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index fe80b614a40..791e030ea90 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -542,7 +542,7 @@ recent_mt_proc_write(struct file *file, const char __user *input, struct recent_entry *e; char buf[sizeof("+b335:1d35:1e55:dead:c0de:1715:5afe:c0de")]; const char *c = buf; - union nf_inet_addr addr; + union nf_inet_addr addr = {}; u_int16_t family; bool add, succ; diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index f6b4fa97df7..e36e94ab4e1 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -66,11 +66,15 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid, { struct drr_sched *q = qdisc_priv(sch); struct drr_class *cl = (struct drr_class *)*arg; + struct nlattr *opt = tca[TCA_OPTIONS]; struct nlattr *tb[TCA_DRR_MAX + 1]; u32 quantum; int err; - err = nla_parse_nested(tb, TCA_DRR_MAX, tca[TCA_OPTIONS], drr_policy); + if (!opt) + return -EINVAL; + + err = nla_parse_nested(tb, TCA_DRR_MAX, opt, drr_policy); if (err < 0) return err; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 3f4b2664738..350794ab9b4 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -386,11 +386,12 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) if (!S_ISSOCK(inode->i_mode) || ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) return 0; - sock = SOCKET_I(inode); sk = sock->sk; + if (sk == NULL) + return 0; sksec = sk->sk_security; - if (sksec->nlbl_state != NLBL_REQUIRE) + if (sksec == NULL || sksec->nlbl_state != NLBL_REQUIRE) return 0; local_bh_disable(); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c8d9178f47e..5e909e0da04 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2095,6 +2095,8 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = { SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), /* including bogus ALC268 in slot#2 that conflicts with ALC888 */ SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), + /* conflict of ALC268 in slot#3 (digital I/O); a temporary fix */ + SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba laptop", 0x03), {} }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a680be0d453..6c26afcb826 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10557,6 +10557,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC), SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC), SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC), + SND_PCI_QUIRK(0x103c, 0x170b, "HP xw*", ALC262_HP_BPC), SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 8027edf3c8f..3bc427645da 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4989,7 +4989,7 @@ again: case STAC_DELL_M4_3: spec->num_dmics = 1; spec->num_smuxes = 0; - spec->num_dmuxes = 0; + spec->num_dmuxes = 1; break; default: spec->num_dmics = STAC92HD71BXX_NUM_DMICS; |