diff --git a/[refs] b/[refs] index 411dabb72868..a61fe015fd28 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d342894c5d2f8c7df194c793ec4059656e09ca31 +refs/heads/master: 726ba0e14a7915effee9e8e652a37306d9637d13 diff --git a/trunk/Documentation/ABI/testing/sysfs-ptp b/trunk/Documentation/ABI/testing/sysfs-ptp index 05aeedf17794..d40d2b550502 100644 --- a/trunk/Documentation/ABI/testing/sysfs-ptp +++ b/trunk/Documentation/ABI/testing/sysfs-ptp @@ -19,11 +19,7 @@ Date: September 2010 Contact: Richard Cochran Description: This file contains the name of the PTP hardware clock - as a human readable string. The purpose of this - attribute is to provide the user with a "friendly - name" and to help distinguish PHY based devices from - MAC based ones. The string does not necessarily have - to be any kind of unique id. + as a human readable string. What: /sys/class/ptp/ptpN/max_adjustment Date: September 2010 diff --git a/trunk/Documentation/devicetree/bindings/net/can/c_can.txt b/trunk/Documentation/devicetree/bindings/net/can/c_can.txt deleted file mode 100644 index 8f1ae81228e3..000000000000 --- a/trunk/Documentation/devicetree/bindings/net/can/c_can.txt +++ /dev/null @@ -1,49 +0,0 @@ -Bosch C_CAN/D_CAN controller Device Tree Bindings -------------------------------------------------- - -Required properties: -- compatible : Should be "bosch,c_can" for C_CAN controllers and - "bosch,d_can" for D_CAN controllers. -- reg : physical base address and size of the C_CAN/D_CAN - registers map -- interrupts : property with a value describing the interrupt - number - -Optional properties: -- ti,hwmods : Must be "d_can" or "c_can", n being the - instance number - -Note: "ti,hwmods" field is used to fetch the base address and irq -resources from TI, omap hwmod data base during device registration. -Future plan is to migrate hwmod data base contents into device tree -blob so that, all the required data will be used from device tree dts -file. - -Example: - -Step1: SoC common .dtsi file - - dcan1: d_can@481d0000 { - compatible = "bosch,d_can"; - reg = <0x481d0000 0x2000>; - interrupts = <55>; - interrupt-parent = <&intc>; - status = "disabled"; - }; - -(or) - - dcan1: d_can@481d0000 { - compatible = "bosch,d_can"; - ti,hwmods = "d_can1"; - reg = <0x481d0000 0x2000>; - interrupts = <55>; - interrupt-parent = <&intc>; - status = "disabled"; - }; - -Step 2: board specific .dts file - - &dcan1 { - status = "okay"; - }; diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index e824c1e74202..e45fa5c0aa20 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -508,6 +508,18 @@ Who: Kees Cook ---------------------------- +What: Removing the pn544 raw driver. +When: 3.6 +Why: With the introduction of the NFC HCI and SHDL kernel layers, pn544.c + is being replaced by pn544_hci.c which is accessible through the netlink + and socket NFC APIs. Moreover, pn544.c is outdated and does not seem to + work properly with the latest Android stacks. + Having 2 drivers for the same hardware is confusing and as such we + should only keep the one following the kernel NFC APIs. +Who: Samuel Ortiz + +---------------------------- + What: setitimer accepts user NULL pointer (value) When: 3.6 Why: setitimer is not returning -EFAULT if user pointer is NULL. This diff --git a/trunk/Documentation/networking/vxlan.txt b/trunk/Documentation/networking/vxlan.txt deleted file mode 100644 index 5b34b762d7d5..000000000000 --- a/trunk/Documentation/networking/vxlan.txt +++ /dev/null @@ -1,47 +0,0 @@ -Virtual eXtensible Local Area Networking documentation -====================================================== - -The VXLAN protocol is a tunnelling protocol that is designed to -solve the problem of limited number of available VLAN's (4096). -With VXLAN identifier is expanded to 24 bits. - -It is a draft RFC standard, that is implemented by Cisco Nexus, -Vmware and Brocade. The protocol runs over UDP using a single -destination port (still not standardized by IANA). -This document describes the Linux kernel tunnel device, -there is also an implantation of VXLAN for Openvswitch. - -Unlike most tunnels, a VXLAN is a 1 to N network, not just point -to point. A VXLAN device can either dynamically learn the IP address -of the other end, in a manner similar to a learning bridge, or the -forwarding entries can be configured statically. - -The management of vxlan is done in a similar fashion to it's -too closest neighbors GRE and VLAN. Configuring VXLAN requires -the version of iproute2 that matches the kernel release -where VXLAN was first merged upstream. - -1. Create vxlan device - # ip li add vxlan0 type vxlan id 42 group 239.1.1.1 dev eth1 - -This creates a new device (vxlan0). The device uses the -the multicast group 239.1.1.1 over eth1 to handle packets where -no entry is in the forwarding table. - -2. Delete vxlan device - # ip link delete vxlan0 - -3. Show vxlan info - # ip -d show vxlan0 - -It is possible to create, destroy and display the vxlan -forwarding table using the new bridge command. - -1. Create forwarding table entry - # bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0 - -2. Delete forwarding table entry - # bridge fdb delete 00:17:42:8a:b4:05 - -3. Show forwarding table - # bridge fdb show dev vxlan0 diff --git a/trunk/Documentation/vfio.txt b/trunk/Documentation/vfio.txt index 8eda3635a17d..0cb6685c8029 100644 --- a/trunk/Documentation/vfio.txt +++ b/trunk/Documentation/vfio.txt @@ -133,7 +133,7 @@ character devices for this group: $ lspci -n -s 0000:06:0d.0 06:0d.0 0401: 1102:0002 (rev 08) # echo 0000:06:0d.0 > /sys/bus/pci/devices/0000:06:0d.0/driver/unbind -# echo 1102 0002 > /sys/bus/pci/drivers/vfio-pci/new_id +# echo 1102 0002 > /sys/bus/pci/drivers/vfio/new_id Now we need to look at what other devices are in the group to free it for use by VFIO: diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 64458f0ee80e..53cc13c82cb1 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -3552,12 +3552,11 @@ K: \b(ABS|SYN)_MT_ INTEL C600 SERIES SAS CONTROLLER DRIVER M: Intel SCU Linux support -M: Lukasz Dorau -M: Maciej Patelczyk M: Dave Jiang +M: Ed Nadolski L: linux-scsi@vger.kernel.org -T: git git://git.code.sf.net/p/intel-sas/isci -S: Supported +T: git git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git +S: Maintained F: drivers/scsi/isci/ F: firmware/isci/ @@ -3667,12 +3666,11 @@ F: Documentation/networking/README.ipw2200 F: drivers/net/wireless/ipw2x00/ INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) -M: Richard L Maliszewski -M: Gang Wei +M: Joseph Cihula M: Shane Wang L: tboot-devel@lists.sourceforge.net W: http://tboot.sourceforge.net -T: hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot +T: Mercurial http://www.bughost.org/repos.hg/tboot.hg S: Supported F: Documentation/intel_txt.txt F: include/linux/tboot.h @@ -4799,7 +4797,6 @@ M: Lauro Ramos Venancio M: Aloisio Almeida Jr M: Samuel Ortiz L: linux-wireless@vger.kernel.org -L: linux-nfc@lists.01.org (moderated for non-subscribers) S: Maintained F: net/nfc/ F: include/linux/nfc.h @@ -5546,8 +5543,6 @@ F: Documentation/devicetree/bindings/pwm/ F: include/linux/pwm.h F: include/linux/of_pwm.h F: drivers/pwm/ -F: drivers/video/backlight/pwm_bl.c -F: include/linux/pwm_backlight.h PXA2xx/PXA3xx SUPPORT M: Eric Miao diff --git a/trunk/Makefile b/trunk/Makefile index a3c11d589681..0f66f146d57e 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,8 +1,8 @@ VERSION = 3 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -rc7 -NAME = Terrified Chipmunk +EXTRAVERSION = -rc5 +NAME = Saber-toothed Squirrel # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff --git a/trunk/arch/arm/boot/compressed/head.S b/trunk/arch/arm/boot/compressed/head.S index bc67cbff3944..81769c1341fa 100644 --- a/trunk/arch/arm/boot/compressed/head.S +++ b/trunk/arch/arm/boot/compressed/head.S @@ -653,7 +653,6 @@ __armv7_mmu_cache_on: mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs #endif mrc p15, 0, r0, c1, c0, 0 @ read control reg - bic r0, r0, #1 << 28 @ clear SCTLR.TRE orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x003c @ write buffer #ifdef CONFIG_MMU diff --git a/trunk/arch/arm/boot/dts/at91sam9260.dtsi b/trunk/arch/arm/boot/dts/at91sam9260.dtsi index 7c95f76398de..66389c1c6f62 100644 --- a/trunk/arch/arm/boot/dts/at91sam9260.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9260.dtsi @@ -104,7 +104,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff600 { @@ -114,7 +113,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff800 { @@ -124,7 +122,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@fffff200 { diff --git a/trunk/arch/arm/boot/dts/at91sam9263.dtsi b/trunk/arch/arm/boot/dts/at91sam9263.dtsi index 195019b7ca0e..b460d6ce9eb5 100644 --- a/trunk/arch/arm/boot/dts/at91sam9263.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9263.dtsi @@ -95,7 +95,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff400 { @@ -105,7 +104,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff600 { @@ -115,7 +113,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioD: gpio@fffff800 { @@ -125,7 +122,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioE: gpio@fffffa00 { @@ -135,7 +131,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@ffffee00 { diff --git a/trunk/arch/arm/boot/dts/at91sam9g45.dtsi b/trunk/arch/arm/boot/dts/at91sam9g45.dtsi index 63751b1e744b..bafa8806fc17 100644 --- a/trunk/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9g45.dtsi @@ -113,7 +113,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff400 { @@ -123,7 +122,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff600 { @@ -133,7 +131,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioD: gpio@fffff800 { @@ -143,7 +140,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioE: gpio@fffffa00 { @@ -153,7 +149,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@ffffee00 { diff --git a/trunk/arch/arm/boot/dts/at91sam9n12.dtsi b/trunk/arch/arm/boot/dts/at91sam9n12.dtsi index ef9336ae9614..bfac0dfc332c 100644 --- a/trunk/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9n12.dtsi @@ -107,7 +107,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff600 { @@ -117,7 +116,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff800 { @@ -127,7 +125,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioD: gpio@fffffa00 { @@ -137,7 +134,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@fffff200 { diff --git a/trunk/arch/arm/boot/dts/at91sam9x5.dtsi b/trunk/arch/arm/boot/dts/at91sam9x5.dtsi index 8a387a8d61b7..4a18c393b136 100644 --- a/trunk/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/trunk/arch/arm/boot/dts/at91sam9x5.dtsi @@ -115,7 +115,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioB: gpio@fffff600 { @@ -125,7 +124,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioC: gpio@fffff800 { @@ -135,7 +133,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; pioD: gpio@fffffa00 { @@ -145,7 +142,6 @@ #gpio-cells = <2>; gpio-controller; interrupt-controller; - #interrupt-cells = <2>; }; dbgu: serial@fffff200 { diff --git a/trunk/arch/arm/include/asm/unistd.h b/trunk/arch/arm/include/asm/unistd.h index 2fde5fd1acce..0cab47d4a83f 100644 --- a/trunk/arch/arm/include/asm/unistd.h +++ b/trunk/arch/arm/include/asm/unistd.h @@ -404,7 +404,6 @@ #define __NR_setns (__NR_SYSCALL_BASE+375) #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) - /* 378 for kcmp */ /* * The following SWIs are ARM private. @@ -484,7 +483,6 @@ */ #define __IGNORE_fadvise64_64 #define __IGNORE_migrate_pages -#define __IGNORE_kcmp #endif /* __KERNEL__ */ #endif /* __ASM_ARM_UNISTD_H */ diff --git a/trunk/arch/arm/kernel/calls.S b/trunk/arch/arm/kernel/calls.S index e337879595e5..463ff4a0ec8a 100644 --- a/trunk/arch/arm/kernel/calls.S +++ b/trunk/arch/arm/kernel/calls.S @@ -387,7 +387,6 @@ /* 375 */ CALL(sys_setns) CALL(sys_process_vm_readv) CALL(sys_process_vm_writev) - CALL(sys_ni_syscall) /* reserved for sys_kcmp */ #ifndef syscalls_counted .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls #define syscalls_counted diff --git a/trunk/arch/arm/kernel/smp_twd.c b/trunk/arch/arm/kernel/smp_twd.c index e1f906989bb8..fef42b21cecb 100644 --- a/trunk/arch/arm/kernel/smp_twd.c +++ b/trunk/arch/arm/kernel/smp_twd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -95,52 +96,7 @@ static void twd_timer_stop(struct clock_event_device *clk) disable_percpu_irq(clk->irq); } -#ifdef CONFIG_COMMON_CLK - -/* - * Updates clockevent frequency when the cpu frequency changes. - * Called on the cpu that is changing frequency with interrupts disabled. - */ -static void twd_update_frequency(void *new_rate) -{ - twd_timer_rate = *((unsigned long *) new_rate); - - clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); -} - -static int twd_rate_change(struct notifier_block *nb, - unsigned long flags, void *data) -{ - struct clk_notifier_data *cnd = data; - - /* - * The twd clock events must be reprogrammed to account for the new - * frequency. The timer is local to a cpu, so cross-call to the - * changing cpu. - */ - if (flags == POST_RATE_CHANGE) - smp_call_function(twd_update_frequency, - (void *)&cnd->new_rate, 1); - - return NOTIFY_OK; -} - -static struct notifier_block twd_clk_nb = { - .notifier_call = twd_rate_change, -}; - -static int twd_clk_init(void) -{ - if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) - return clk_notifier_register(twd_clk, &twd_clk_nb); - - return 0; -} -core_initcall(twd_clk_init); - -#elif defined (CONFIG_CPU_FREQ) - -#include +#ifdef CONFIG_CPU_FREQ /* * Updates clockevent frequency when the cpu frequency changes. diff --git a/trunk/arch/arm/mach-imx/clk-imx25.c b/trunk/arch/arm/mach-imx/clk-imx25.c index d20d4795f4ea..4431a62fff5b 100644 --- a/trunk/arch/arm/mach-imx/clk-imx25.c +++ b/trunk/arch/arm/mach-imx/clk-imx25.c @@ -241,6 +241,6 @@ int __init mx25_clocks_init(void) clk_register_clkdev(clk[sdma_ahb], "ahb", "imx35-sdma"); clk_register_clkdev(clk[iim_ipg], "iim", NULL); - mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), MX25_INT_GPT1); + mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54); return 0; } diff --git a/trunk/arch/arm/mach-imx/mach-armadillo5x0.c b/trunk/arch/arm/mach-imx/mach-armadillo5x0.c index 5985ed1b8c98..2c6ab3273f9e 100644 --- a/trunk/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/trunk/arch/arm/mach-imx/mach-armadillo5x0.c @@ -526,8 +526,7 @@ static void __init armadillo5x0_init(void) imx31_add_mxc_nand(&armadillo5x0_nand_board_info); /* set NAND page size to 2k if not configured via boot mode pins */ - __raw_writel(__raw_readl(mx3_ccm_base + MXC_CCM_RCSR) | - (1 << 30), mx3_ccm_base + MXC_CCM_RCSR); + __raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR); /* RTC */ /* Get RTC IRQ and register the chip */ diff --git a/trunk/arch/arm/mach-mxs/mach-mxs.c b/trunk/arch/arm/mach-mxs/mach-mxs.c index ff886e01a0b0..8dabfe81d07c 100644 --- a/trunk/arch/arm/mach-mxs/mach-mxs.c +++ b/trunk/arch/arm/mach-mxs/mach-mxs.c @@ -261,7 +261,7 @@ static void __init apx4devkit_init(void) enable_clk_enet_out(); if (IS_BUILTIN(CONFIG_PHYLIB)) - phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, + phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK, apx4devkit_phy_fixup); mxsfb_pdata.mode_list = apx4devkit_video_modes; diff --git a/trunk/arch/arm/mach-orion5x/common.c b/trunk/arch/arm/mach-orion5x/common.c index a6cd14ab1e4e..410291c67666 100644 --- a/trunk/arch/arm/mach-orion5x/common.c +++ b/trunk/arch/arm/mach-orion5x/common.c @@ -204,13 +204,6 @@ void __init orion5x_wdt_init(void) void __init orion5x_init_early(void) { orion_time_set_base(TIMER_VIRT_BASE); - - /* - * Some Orion5x devices allocate their coherent buffers from atomic - * context. Increase size of atomic coherent pool to make sure such - * the allocations won't fail. - */ - init_dma_coherent_pool_size(SZ_1M); } int orion5x_tclk; diff --git a/trunk/arch/arm/mach-shmobile/board-kzm9g.c b/trunk/arch/arm/mach-shmobile/board-kzm9g.c index 3b8a0171c3cb..53b7ea92c32c 100644 --- a/trunk/arch/arm/mach-shmobile/board-kzm9g.c +++ b/trunk/arch/arm/mach-shmobile/board-kzm9g.c @@ -346,11 +346,11 @@ static struct resource sh_mmcif_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gic_spi(140), + .start = gic_spi(141), .flags = IORESOURCE_IRQ, }, [2] = { - .start = gic_spi(141), + .start = gic_spi(140), .flags = IORESOURCE_IRQ, }, }; diff --git a/trunk/arch/arm/mm/dma-mapping.c b/trunk/arch/arm/mm/dma-mapping.c index 13f555d62491..e59c4ab71bcb 100644 --- a/trunk/arch/arm/mm/dma-mapping.c +++ b/trunk/arch/arm/mm/dma-mapping.c @@ -346,8 +346,6 @@ static int __init atomic_pool_init(void) (unsigned)pool->size / 1024); return 0; } - - kfree(pages); no_pages: kfree(bitmap); no_bitmap: diff --git a/trunk/arch/arm/plat-mxc/include/mach/mx25.h b/trunk/arch/arm/plat-mxc/include/mach/mx25.h index ec466400a200..627d94f1b010 100644 --- a/trunk/arch/arm/plat-mxc/include/mach/mx25.h +++ b/trunk/arch/arm/plat-mxc/include/mach/mx25.h @@ -98,7 +98,6 @@ #define MX25_INT_UART1 (NR_IRQS_LEGACY + 45) #define MX25_INT_GPIO2 (NR_IRQS_LEGACY + 51) #define MX25_INT_GPIO1 (NR_IRQS_LEGACY + 52) -#define MX25_INT_GPT1 (NR_IRQS_LEGACY + 54) #define MX25_INT_FEC (NR_IRQS_LEGACY + 57) #define MX25_DMA_REQ_SSI2_RX1 22 diff --git a/trunk/arch/arm/plat-samsung/clock.c b/trunk/arch/arm/plat-samsung/clock.c index d1116e2dfbea..65c5eca475e7 100644 --- a/trunk/arch/arm/plat-samsung/clock.c +++ b/trunk/arch/arm/plat-samsung/clock.c @@ -144,7 +144,6 @@ long clk_round_rate(struct clk *clk, unsigned long rate) int clk_set_rate(struct clk *clk, unsigned long rate) { - unsigned long flags; int ret; if (IS_ERR(clk)) @@ -160,9 +159,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->ops == NULL || clk->ops->set_rate == NULL) return -EINVAL; - spin_lock_irqsave(&clocks_lock, flags); + spin_lock(&clocks_lock); ret = (clk->ops->set_rate)(clk, rate); - spin_unlock_irqrestore(&clocks_lock, flags); + spin_unlock(&clocks_lock); return ret; } @@ -174,18 +173,17 @@ struct clk *clk_get_parent(struct clk *clk) int clk_set_parent(struct clk *clk, struct clk *parent) { - unsigned long flags; int ret = 0; if (IS_ERR(clk)) return -EINVAL; - spin_lock_irqsave(&clocks_lock, flags); + spin_lock(&clocks_lock); if (clk->ops && clk->ops->set_parent) ret = (clk->ops->set_parent)(clk, parent); - spin_unlock_irqrestore(&clocks_lock, flags); + spin_unlock(&clocks_lock); return ret; } diff --git a/trunk/arch/c6x/include/asm/Kbuild b/trunk/arch/c6x/include/asm/Kbuild index f08e89183cda..3af601e31e66 100644 --- a/trunk/arch/c6x/include/asm/Kbuild +++ b/trunk/arch/c6x/include/asm/Kbuild @@ -2,7 +2,6 @@ include include/asm-generic/Kbuild.asm generic-y += atomic.h generic-y += auxvec.h -generic-y += barrier.h generic-y += bitsperlong.h generic-y += bugs.h generic-y += cputime.h diff --git a/trunk/arch/c6x/include/asm/barrier.h b/trunk/arch/c6x/include/asm/barrier.h new file mode 100644 index 000000000000..538240e85909 --- /dev/null +++ b/trunk/arch/c6x/include/asm/barrier.h @@ -0,0 +1,27 @@ +/* + * Port on Texas Instruments TMS320C6x architecture + * + * Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _ASM_C6X_BARRIER_H +#define _ASM_C6X_BARRIER_H + +#define nop() asm("NOP\n"); + +#define mb() barrier() +#define rmb() barrier() +#define wmb() barrier() +#define set_mb(var, value) do { var = value; mb(); } while (0) +#define set_wmb(var, value) do { var = value; wmb(); } while (0) + +#define smp_mb() barrier() +#define smp_rmb() barrier() +#define smp_wmb() barrier() +#define smp_read_barrier_depends() do { } while (0) + +#endif /* _ASM_C6X_BARRIER_H */ diff --git a/trunk/arch/m68k/platform/coldfire/clk.c b/trunk/arch/m68k/platform/coldfire/clk.c index 9cd13b4ce42b..75f9ee967ea7 100644 --- a/trunk/arch/m68k/platform/coldfire/clk.c +++ b/trunk/arch/m68k/platform/coldfire/clk.c @@ -146,3 +146,9 @@ struct clk_ops clk_ops1 = { }; #endif /* MCFPM_PPMCR1 */ #endif /* MCFPM_PPMCR0 */ + +struct clk *devm_clk_get(struct device *dev, const char *id) +{ + return NULL; +} +EXPORT_SYMBOL(devm_clk_get); diff --git a/trunk/arch/mips/kernel/smp-cmp.c b/trunk/arch/mips/kernel/smp-cmp.c index afc379ca3753..e7e03ecf5495 100644 --- a/trunk/arch/mips/kernel/smp-cmp.c +++ b/trunk/arch/mips/kernel/smp-cmp.c @@ -102,7 +102,7 @@ static void cmp_init_secondary(void) c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE; #endif #ifdef CONFIG_MIPS_MT_SMTC - c->tc_id = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT; + c->tc_id = (read_c0_tcbind() >> TCBIND_CURTC_SHIFT) & TCBIND_CURTC; #endif } diff --git a/trunk/arch/mips/mm/gup.c b/trunk/arch/mips/mm/gup.c index dcfd573871c1..33aadbcf170b 100644 --- a/trunk/arch/mips/mm/gup.c +++ b/trunk/arch/mips/mm/gup.c @@ -152,8 +152,6 @@ static int gup_huge_pud(pud_t pud, unsigned long addr, unsigned long end, do { VM_BUG_ON(compound_head(page) != head); pages[*nr] = page; - if (PageTail(page)) - get_huge_page_tail(page); (*nr)++; page++; refs++; diff --git a/trunk/arch/mips/mti-malta/malta-int.c b/trunk/arch/mips/mti-malta/malta-int.c index fea823f18479..7b13a4caeea4 100644 --- a/trunk/arch/mips/mti-malta/malta-int.c +++ b/trunk/arch/mips/mti-malta/malta-int.c @@ -273,19 +273,16 @@ asmlinkage void plat_irq_dispatch(void) unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; int irq; - if (unlikely(!pending)) { - spurious_interrupt(); - return; - } - irq = irq_ffs(pending); if (irq == MIPSCPU_INT_I8259A) malta_hw0_irqdispatch(); else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) malta_ipi_irqdispatch(); - else + else if (irq >= 0) do_IRQ(MIPS_CPU_IRQ_BASE + irq); + else + spurious_interrupt(); } #ifdef CONFIG_MIPS_MT_SMP diff --git a/trunk/arch/mips/mti-malta/malta-platform.c b/trunk/arch/mips/mti-malta/malta-platform.c index 80562b81f0f2..4c35301720e7 100644 --- a/trunk/arch/mips/mti-malta/malta-platform.c +++ b/trunk/arch/mips/mti-malta/malta-platform.c @@ -138,6 +138,11 @@ static int __init malta_add_devices(void) if (err) return err; + /* + * Set RTC to BCD mode to support current alarm code. + */ + CMOS_WRITE(CMOS_READ(RTC_CONTROL) & ~RTC_DM_BINARY, RTC_CONTROL); + return 0; } diff --git a/trunk/arch/s390/include/asm/hugetlb.h b/trunk/arch/s390/include/asm/hugetlb.h index 2d6e6e380564..799ed0f1643d 100644 --- a/trunk/arch/s390/include/asm/hugetlb.h +++ b/trunk/arch/s390/include/asm/hugetlb.h @@ -66,6 +66,16 @@ static inline pte_t huge_ptep_get(pte_t *ptep) return pte; } +static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + pte_t pte = huge_ptep_get(ptep); + + mm->context.flush_mm = 1; + pmd_clear((pmd_t *) ptep); + return pte; +} + static inline void __pmd_csp(pmd_t *pmdp) { register unsigned long reg2 asm("2") = pmd_val(*pmdp); @@ -107,15 +117,6 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm, __pmd_csp(pmdp); } -static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - pte_t pte = huge_ptep_get(ptep); - - huge_ptep_invalidate(mm, addr, ptep); - return pte; -} - #define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ ({ \ int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \ @@ -130,7 +131,10 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, ({ \ pte_t __pte = huge_ptep_get(__ptep); \ if (pte_write(__pte)) { \ - huge_ptep_invalidate(__mm, __addr, __ptep); \ + (__mm)->context.flush_mm = 1; \ + if (atomic_read(&(__mm)->context.attach_count) > 1 || \ + (__mm) != current->active_mm) \ + huge_ptep_invalidate(__mm, __addr, __ptep); \ set_huge_pte_at(__mm, __addr, __ptep, \ huge_pte_wrprotect(__pte)); \ } \ diff --git a/trunk/arch/s390/include/asm/tlbflush.h b/trunk/arch/s390/include/asm/tlbflush.h index 1d8fe2b17ef6..9fde315f3a7c 100644 --- a/trunk/arch/s390/include/asm/tlbflush.h +++ b/trunk/arch/s390/include/asm/tlbflush.h @@ -90,10 +90,12 @@ static inline void __tlb_flush_mm(struct mm_struct * mm) static inline void __tlb_flush_mm_cond(struct mm_struct * mm) { + spin_lock(&mm->page_table_lock); if (mm->context.flush_mm) { __tlb_flush_mm(mm); mm->context.flush_mm = 0; } + spin_unlock(&mm->page_table_lock); } /* diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index 40b57693de38..f86c81e13c37 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -974,13 +974,11 @@ static void __init setup_hwcaps(void) if (MACHINE_HAS_HPAGE) elf_hwcap |= HWCAP_S390_HPAGE; -#if defined(CONFIG_64BIT) /* * 64-bit register support for 31-bit processes * HWCAP_S390_HIGH_GPRS is bit 9. */ elf_hwcap |= HWCAP_S390_HIGH_GPRS; -#endif get_cpu_id(&cpu_id); switch (cpu_id.machine) { diff --git a/trunk/arch/s390/lib/uaccess_pt.c b/trunk/arch/s390/lib/uaccess_pt.c index 2d37bb861faf..60ee2b883797 100644 --- a/trunk/arch/s390/lib/uaccess_pt.c +++ b/trunk/arch/s390/lib/uaccess_pt.c @@ -2,82 +2,69 @@ * User access functions based on page table walks for enhanced * system layout without hardware support. * - * Copyright IBM Corp. 2006, 2012 + * Copyright IBM Corp. 2006 * Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com) */ #include #include #include -#include #include #include #include "uaccess.h" - -/* - * Returns kernel address for user virtual address. If the returned address is - * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address - * contains the (negative) exception code. - */ -static __always_inline unsigned long follow_table(struct mm_struct *mm, - unsigned long addr, int write) +static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; - pte_t *ptep; pgd = pgd_offset(mm, addr); if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) - return -0x3aUL; + return (pte_t *) 0x3a; pud = pud_offset(pgd, addr); if (pud_none(*pud) || unlikely(pud_bad(*pud))) - return -0x3bUL; + return (pte_t *) 0x3b; pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) - return -0x10UL; - if (pmd_huge(*pmd)) { - if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO)) - return -0x04UL; - return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK); - } - if (unlikely(pmd_bad(*pmd))) - return -0x10UL; - - ptep = pte_offset_map(pmd, addr); - if (!pte_present(*ptep)) - return -0x11UL; - if (write && !pte_write(*ptep)) - return -0x04UL; + if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) + return (pte_t *) 0x10; - return (pte_val(*ptep) & PAGE_MASK) + (addr & ~PAGE_MASK); + return pte_offset_map(pmd, addr); } static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, size_t n, int write_user) { struct mm_struct *mm = current->mm; - unsigned long offset, done, size, kaddr; + unsigned long offset, pfn, done, size; + pte_t *pte; void *from, *to; done = 0; retry: spin_lock(&mm->page_table_lock); do { - kaddr = follow_table(mm, uaddr, write_user); - if (IS_ERR_VALUE(kaddr)) + pte = follow_table(mm, uaddr); + if ((unsigned long) pte < 0x1000) goto fault; + if (!pte_present(*pte)) { + pte = (pte_t *) 0x11; + goto fault; + } else if (write_user && !pte_write(*pte)) { + pte = (pte_t *) 0x04; + goto fault; + } - offset = uaddr & ~PAGE_MASK; + pfn = pte_pfn(*pte); + offset = uaddr & (PAGE_SIZE - 1); size = min(n - done, PAGE_SIZE - offset); if (write_user) { - to = (void *) kaddr; + to = (void *)((pfn << PAGE_SHIFT) + offset); from = kptr + done; } else { - from = (void *) kaddr; + from = (void *)((pfn << PAGE_SHIFT) + offset); to = kptr + done; } memcpy(to, from, size); @@ -88,7 +75,7 @@ static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, return n - done; fault: spin_unlock(&mm->page_table_lock); - if (__handle_fault(uaddr, -kaddr, write_user)) + if (__handle_fault(uaddr, (unsigned long) pte, write_user)) return n - done; goto retry; } @@ -97,22 +84,27 @@ static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, * Do DAT for user address by page table walk, return kernel address. * This function needs to be called with current->mm->page_table_lock held. */ -static __always_inline unsigned long __dat_user_addr(unsigned long uaddr, - int write) +static __always_inline unsigned long __dat_user_addr(unsigned long uaddr) { struct mm_struct *mm = current->mm; - unsigned long kaddr; + unsigned long pfn; + pte_t *pte; int rc; retry: - kaddr = follow_table(mm, uaddr, write); - if (IS_ERR_VALUE(kaddr)) + pte = follow_table(mm, uaddr); + if ((unsigned long) pte < 0x1000) + goto fault; + if (!pte_present(*pte)) { + pte = (pte_t *) 0x11; goto fault; + } - return kaddr; + pfn = pte_pfn(*pte); + return (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1)); fault: spin_unlock(&mm->page_table_lock); - rc = __handle_fault(uaddr, -kaddr, write); + rc = __handle_fault(uaddr, (unsigned long) pte, 0); spin_lock(&mm->page_table_lock); if (!rc) goto retry; @@ -167,9 +159,11 @@ static size_t clear_user_pt(size_t n, void __user *to) static size_t strnlen_user_pt(size_t count, const char __user *src) { + char *addr; unsigned long uaddr = (unsigned long) src; struct mm_struct *mm = current->mm; - unsigned long offset, done, len, kaddr; + unsigned long offset, pfn, done, len; + pte_t *pte; size_t len_str; if (segment_eq(get_fs(), KERNEL_DS)) @@ -178,13 +172,19 @@ static size_t strnlen_user_pt(size_t count, const char __user *src) retry: spin_lock(&mm->page_table_lock); do { - kaddr = follow_table(mm, uaddr, 0); - if (IS_ERR_VALUE(kaddr)) + pte = follow_table(mm, uaddr); + if ((unsigned long) pte < 0x1000) + goto fault; + if (!pte_present(*pte)) { + pte = (pte_t *) 0x11; goto fault; + } - offset = uaddr & ~PAGE_MASK; + pfn = pte_pfn(*pte); + offset = uaddr & (PAGE_SIZE-1); + addr = (char *)(pfn << PAGE_SHIFT) + offset; len = min(count - done, PAGE_SIZE - offset); - len_str = strnlen((char *) kaddr, len); + len_str = strnlen(addr, len); done += len_str; uaddr += len_str; } while ((len_str == len) && (done < count)); @@ -192,7 +192,7 @@ static size_t strnlen_user_pt(size_t count, const char __user *src) return done + 1; fault: spin_unlock(&mm->page_table_lock); - if (__handle_fault(uaddr, -kaddr, 0)) + if (__handle_fault(uaddr, (unsigned long) pte, 0)) return 0; goto retry; } @@ -225,10 +225,11 @@ static size_t copy_in_user_pt(size_t n, void __user *to, const void __user *from) { struct mm_struct *mm = current->mm; - unsigned long offset_max, uaddr, done, size, error_code; + unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to, + uaddr, done, size, error_code; unsigned long uaddr_from = (unsigned long) from; unsigned long uaddr_to = (unsigned long) to; - unsigned long kaddr_to, kaddr_from; + pte_t *pte_from, *pte_to; int write_user; if (segment_eq(get_fs(), KERNEL_DS)) { @@ -241,23 +242,38 @@ static size_t copy_in_user_pt(size_t n, void __user *to, do { write_user = 0; uaddr = uaddr_from; - kaddr_from = follow_table(mm, uaddr_from, 0); - error_code = kaddr_from; - if (IS_ERR_VALUE(error_code)) + pte_from = follow_table(mm, uaddr_from); + error_code = (unsigned long) pte_from; + if (error_code < 0x1000) + goto fault; + if (!pte_present(*pte_from)) { + error_code = 0x11; goto fault; + } write_user = 1; uaddr = uaddr_to; - kaddr_to = follow_table(mm, uaddr_to, 1); - error_code = (unsigned long) kaddr_to; - if (IS_ERR_VALUE(error_code)) + pte_to = follow_table(mm, uaddr_to); + error_code = (unsigned long) pte_to; + if (error_code < 0x1000) + goto fault; + if (!pte_present(*pte_to)) { + error_code = 0x11; goto fault; + } else if (!pte_write(*pte_to)) { + error_code = 0x04; + goto fault; + } - offset_max = max(uaddr_from & ~PAGE_MASK, - uaddr_to & ~PAGE_MASK); + pfn_from = pte_pfn(*pte_from); + pfn_to = pte_pfn(*pte_to); + offset_from = uaddr_from & (PAGE_SIZE-1); + offset_to = uaddr_from & (PAGE_SIZE-1); + offset_max = max(offset_from, offset_to); size = min(n - done, PAGE_SIZE - offset_max); - memcpy((void *) kaddr_to, (void *) kaddr_from, size); + memcpy((void *)(pfn_to << PAGE_SHIFT) + offset_to, + (void *)(pfn_from << PAGE_SHIFT) + offset_from, size); done += size; uaddr_from += size; uaddr_to += size; @@ -266,7 +282,7 @@ static size_t copy_in_user_pt(size_t n, void __user *to, return n - done; fault: spin_unlock(&mm->page_table_lock); - if (__handle_fault(uaddr, -error_code, write_user)) + if (__handle_fault(uaddr, error_code, write_user)) return n - done; goto retry; } @@ -325,7 +341,7 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) return __futex_atomic_op_pt(op, uaddr, oparg, old); spin_lock(¤t->mm->page_table_lock); uaddr = (u32 __force __user *) - __dat_user_addr((__force unsigned long) uaddr, 1); + __dat_user_addr((__force unsigned long) uaddr); if (!uaddr) { spin_unlock(¤t->mm->page_table_lock); return -EFAULT; @@ -362,7 +378,7 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); spin_lock(¤t->mm->page_table_lock); uaddr = (u32 __force __user *) - __dat_user_addr((__force unsigned long) uaddr, 1); + __dat_user_addr((__force unsigned long) uaddr); if (!uaddr) { spin_unlock(¤t->mm->page_table_lock); return -EFAULT; diff --git a/trunk/arch/sh/kernel/cpu/sh5/entry.S b/trunk/arch/sh/kernel/cpu/sh5/entry.S index 7e605b95592a..b7cf6a547f11 100644 --- a/trunk/arch/sh/kernel/cpu/sh5/entry.S +++ b/trunk/arch/sh/kernel/cpu/sh5/entry.S @@ -933,7 +933,7 @@ ret_with_reschedule: pta restore_all, tr1 - movi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), r8 + movi _TIF_SIGPENDING, r8 and r8, r7, r8 pta work_notifysig, tr0 bne r8, ZERO, tr0 diff --git a/trunk/arch/sh/kernel/entry-common.S b/trunk/arch/sh/kernel/entry-common.S index b96489d8b27d..f67601cb3f1f 100644 --- a/trunk/arch/sh/kernel/entry-common.S +++ b/trunk/arch/sh/kernel/entry-common.S @@ -139,7 +139,7 @@ work_pending: ! r8: current_thread_info ! t: result of "tst #_TIF_NEED_RESCHED, r0" bf/s work_resched - tst #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME), r0 + tst #_TIF_SIGPENDING, r0 work_notifysig: bt/s __restore_all mov r15, r4 diff --git a/trunk/arch/sparc/kernel/module.c b/trunk/arch/sparc/kernel/module.c index f1ddc0d23679..15e0a1693976 100644 --- a/trunk/arch/sparc/kernel/module.c +++ b/trunk/arch/sparc/kernel/module.c @@ -48,7 +48,9 @@ void *module_alloc(unsigned long size) return NULL; ret = module_map(size); - if (ret) + if (!ret) + ret = ERR_PTR(-ENOMEM); + else memset(ret, 0, size); return ret; @@ -114,10 +116,6 @@ int apply_relocate_add(Elf_Shdr *sechdrs, v = sym->st_value + rel[i].r_addend; switch (ELF_R_TYPE(rel[i].r_info) & 0xff) { - case R_SPARC_DISP32: - v -= (Elf_Addr) location; - *loc32 = v; - break; #ifdef CONFIG_SPARC64 case R_SPARC_64: location[0] = v >> 56; @@ -130,6 +128,11 @@ int apply_relocate_add(Elf_Shdr *sechdrs, location[7] = v >> 0; break; + case R_SPARC_DISP32: + v -= (Elf_Addr) location; + *loc32 = v; + break; + case R_SPARC_WDISP19: v -= (Elf_Addr) location; *loc32 = (*loc32 & ~0x7ffff) | diff --git a/trunk/arch/sparc/net/bpf_jit_comp.c b/trunk/arch/sparc/net/bpf_jit_comp.c index 28368701ef79..e9073e9501b3 100644 --- a/trunk/arch/sparc/net/bpf_jit_comp.c +++ b/trunk/arch/sparc/net/bpf_jit_comp.c @@ -464,12 +464,8 @@ void bpf_jit_compile(struct sk_filter *fp) emit_alu_K(OR, K); break; case BPF_S_ANC_ALU_XOR_X: /* A ^= X; */ - case BPF_S_ALU_XOR_X: emit_alu_X(XOR); break; - case BPF_S_ALU_XOR_K: /* A ^= K */ - emit_alu_K(XOR, K); - break; case BPF_S_ALU_LSH_X: /* A <<= X */ emit_alu_X(SLL); break; diff --git a/trunk/arch/tile/include/gxio/iorpc_trio.h b/trunk/arch/tile/include/gxio/iorpc_trio.h index 58105c31228b..15fb77992083 100644 --- a/trunk/arch/tile/include/gxio/iorpc_trio.h +++ b/trunk/arch/tile/include/gxio/iorpc_trio.h @@ -25,23 +25,21 @@ #include #include -#define GXIO_TRIO_OP_DEALLOC_ASID IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400) -#define GXIO_TRIO_OP_ALLOC_ASIDS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1401) +#define GXIO_TRIO_OP_ALLOC_ASIDS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400) -#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404) +#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402) -#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1412) +#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e) +#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f) -#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1414) +#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1417) +#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418) +#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1419) +#define GXIO_TRIO_OP_CONFIG_MSI_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a) -#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e) -#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141f) -#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1420) -#define GXIO_TRIO_OP_CONFIG_MSI_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1421) - -#define GXIO_TRIO_OP_SET_MPS_MRS IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1423) -#define GXIO_TRIO_OP_FORCE_RC_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1424) -#define GXIO_TRIO_OP_FORCE_EP_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1425) +#define GXIO_TRIO_OP_SET_MPS_MRS IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141c) +#define GXIO_TRIO_OP_FORCE_RC_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d) +#define GXIO_TRIO_OP_FORCE_EP_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e) #define GXIO_TRIO_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000) #define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001) diff --git a/trunk/arch/um/include/asm/processor-generic.h b/trunk/arch/um/include/asm/processor-generic.h index 33a6a2423bd2..69f1c57a8d0d 100644 --- a/trunk/arch/um/include/asm/processor-generic.h +++ b/trunk/arch/um/include/asm/processor-generic.h @@ -20,6 +20,14 @@ struct mm_struct; struct thread_struct { struct task_struct *saved_task; + /* + * This flag is set to 1 before calling do_fork (and analyzed in + * copy_thread) to mark that we are begin called from userspace (fork / + * vfork / clone), and reset to 0 after. It is left to 0 when called + * from kernelspace (i.e. kernel_thread() or fork_idle(), + * as of 2.6.11). + */ + int forking; struct pt_regs regs; int singlestep_syscall; void *fault_addr; @@ -50,6 +58,7 @@ struct thread_struct { #define INIT_THREAD \ { \ + .forking = 0, \ .regs = EMPTY_REGS, \ .fault_addr = NULL, \ .prev_sched = NULL, \ diff --git a/trunk/arch/um/include/shared/common-offsets.h b/trunk/arch/um/include/shared/common-offsets.h index 2df313b6a586..40db8f71deae 100644 --- a/trunk/arch/um/include/shared/common-offsets.h +++ b/trunk/arch/um/include/shared/common-offsets.h @@ -7,6 +7,16 @@ DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); +DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); +DEFINE_STR(UM_KERN_ALERT, KERN_ALERT); +DEFINE_STR(UM_KERN_CRIT, KERN_CRIT); +DEFINE_STR(UM_KERN_ERR, KERN_ERR); +DEFINE_STR(UM_KERN_WARNING, KERN_WARNING); +DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE); +DEFINE_STR(UM_KERN_INFO, KERN_INFO); +DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); +DEFINE_STR(UM_KERN_CONT, KERN_CONT); + DEFINE(UM_ELF_CLASS, ELF_CLASS); DEFINE(UM_ELFCLASS32, ELFCLASS32); DEFINE(UM_ELFCLASS64, ELFCLASS64); diff --git a/trunk/arch/um/include/shared/user.h b/trunk/arch/um/include/shared/user.h index cef068563336..4fa82c055aab 100644 --- a/trunk/arch/um/include/shared/user.h +++ b/trunk/arch/um/include/shared/user.h @@ -26,17 +26,6 @@ extern void panic(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -/* Requires preincluding include/linux/kern_levels.h */ -#define UM_KERN_EMERG KERN_EMERG -#define UM_KERN_ALERT KERN_ALERT -#define UM_KERN_CRIT KERN_CRIT -#define UM_KERN_ERR KERN_ERR -#define UM_KERN_WARNING KERN_WARNING -#define UM_KERN_NOTICE KERN_NOTICE -#define UM_KERN_INFO KERN_INFO -#define UM_KERN_DEBUG KERN_DEBUG -#define UM_KERN_CONT KERN_CONT - #ifdef UML_CONFIG_PRINTK extern int printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); diff --git a/trunk/arch/um/kernel/exec.c b/trunk/arch/um/kernel/exec.c index 8c82786da823..6cade9366364 100644 --- a/trunk/arch/um/kernel/exec.c +++ b/trunk/arch/um/kernel/exec.c @@ -39,21 +39,34 @@ void flush_thread(void) void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) { - get_safe_registers(regs->regs.gp, regs->regs.fp); PT_REGS_IP(regs) = eip; PT_REGS_SP(regs) = esp; - current->ptrace &= ~PT_DTRACE; +} +EXPORT_SYMBOL(start_thread); + +static long execve1(const char *file, + const char __user *const __user *argv, + const char __user *const __user *env) +{ + long error; + + error = do_execve(file, argv, env, ¤t->thread.regs); + if (error == 0) { + task_lock(current); + current->ptrace &= ~PT_DTRACE; #ifdef SUBARCH_EXECVE1 - SUBARCH_EXECVE1(regs->regs); + SUBARCH_EXECVE1(¤t->thread.regs.regs); #endif + task_unlock(current); + } + return error; } -EXPORT_SYMBOL(start_thread); long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) { long err; - err = do_execve(file, argv, env, ¤t->thread.regs); + err = execve1(file, argv, env); if (!err) UML_LONGJMP(current->thread.exec_buf, 1); return err; @@ -68,7 +81,7 @@ long sys_execve(const char __user *file, const char __user *const __user *argv, filename = getname(file); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - error = do_execve(filename, argv, env, ¤t->thread.regs); + error = execve1(filename, argv, env); putname(filename); out: return error; diff --git a/trunk/arch/um/kernel/process.c b/trunk/arch/um/kernel/process.c index c5f5afa50745..57fc7028714a 100644 --- a/trunk/arch/um/kernel/process.c +++ b/trunk/arch/um/kernel/process.c @@ -181,12 +181,11 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, struct pt_regs *regs) { void (*handler)(void); - int kthread = current->flags & PF_KTHREAD; int ret = 0; p->thread = (struct thread_struct) INIT_THREAD; - if (!kthread) { + if (current->thread.forking) { memcpy(&p->thread.regs.regs, ®s->regs, sizeof(p->thread.regs.regs)); PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); @@ -196,7 +195,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, handler = fork_handler; arch_copy_thread(¤t->thread.arch, &p->thread.arch); - } else { + } + else { get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); p->thread.request.u.thread = current->thread.request.u.thread; handler = new_thread_handler; @@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, new_thread(task_stack_page(p), &p->thread.switch_buf, handler); - if (!kthread) { + if (current->thread.forking) { clear_flushed_tls(p); /* diff --git a/trunk/arch/um/kernel/signal.c b/trunk/arch/um/kernel/signal.c index cc9c2350e417..7362d58efc29 100644 --- a/trunk/arch/um/kernel/signal.c +++ b/trunk/arch/um/kernel/signal.c @@ -22,13 +22,9 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, struct k_sigaction *ka, siginfo_t *info) { sigset_t *oldset = sigmask_to_save(); - int singlestep = 0; unsigned long sp; int err; - if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) - singlestep = 1; - /* Did we come from a system call? */ if (PT_REGS_SYSCALL_NR(regs) >= 0) { /* If so, check system call restarting.. */ @@ -65,7 +61,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, if (err) force_sigsegv(signr, current); else - signal_delivered(signr, info, ka, regs, singlestep); + signal_delivered(signr, info, ka, regs, 0); } static int kern_do_signal(struct pt_regs *regs) diff --git a/trunk/arch/um/kernel/syscall.c b/trunk/arch/um/kernel/syscall.c index a4c6d8eee74c..f958cb876ee3 100644 --- a/trunk/arch/um/kernel/syscall.c +++ b/trunk/arch/um/kernel/syscall.c @@ -17,25 +17,25 @@ long sys_fork(void) { - return do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), + long ret; + + current->thread.forking = 1; + ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), ¤t->thread.regs, 0, NULL, NULL); + current->thread.forking = 0; + return ret; } long sys_vfork(void) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, + long ret; + + current->thread.forking = 1; + ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, UPT_SP(¤t->thread.regs.regs), ¤t->thread.regs, 0, NULL, NULL); -} - -long sys_clone(unsigned long clone_flags, unsigned long newsp, - void __user *parent_tid, void __user *child_tid) -{ - if (!newsp) - newsp = UPT_SP(¤t->thread.regs.regs); - - return do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, - child_tid); + current->thread.forking = 0; + return ret; } long old_mmap(unsigned long addr, unsigned long len, diff --git a/trunk/arch/um/scripts/Makefile.rules b/trunk/arch/um/scripts/Makefile.rules index 15889df9b466..d50270d26b42 100644 --- a/trunk/arch/um/scripts/Makefile.rules +++ b/trunk/arch/um/scripts/Makefile.rules @@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS:.o=.%): \ - c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include $(srctree)/include/linux/kern_levels.h -include user.h $(CFLAGS_$(basetarget).o) + c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o) # These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of # using it directly. diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 50a1d1f9b6d3..8ec3a1aa4abd 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -746,10 +746,10 @@ config SWIOTLB def_bool y if X86_64 ---help--- Support for software bounce buffers used on x86-64 systems - which don't have a hardware IOMMU. Using this PCI devices - which can only access 32-bits of memory can be used on systems - with more than 3 GB of memory. - If unsure, say Y. + which don't have a hardware IOMMU (e.g. the current generation + of Intel's x86-64 CPUs). Using this PCI devices which can only + access 32-bits of memory can be used on systems with more than + 3 GB of memory. If unsure, say Y. config IOMMU_HELPER def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU) diff --git a/trunk/arch/x86/Makefile b/trunk/arch/x86/Makefile index 474ca35b1bce..682e9c210baa 100644 --- a/trunk/arch/x86/Makefile +++ b/trunk/arch/x86/Makefile @@ -142,7 +142,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,) KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y) -archscripts: scripts_basic +archscripts: $(Q)$(MAKE) $(build)=arch/x86/tools relocs ### diff --git a/trunk/arch/x86/include/asm/xen/page.h b/trunk/arch/x86/include/asm/xen/page.h index 472b9b783019..93971e841dd5 100644 --- a/trunk/arch/x86/include/asm/xen/page.h +++ b/trunk/arch/x86/include/asm/xen/page.h @@ -51,8 +51,7 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s, extern int m2p_add_override(unsigned long mfn, struct page *page, struct gnttab_map_grant_ref *kmap_op); -extern int m2p_remove_override(struct page *page, - struct gnttab_map_grant_ref *kmap_op); +extern int m2p_remove_override(struct page *page, bool clear_pte); extern struct page *m2p_find_override(unsigned long mfn); extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); diff --git a/trunk/arch/x86/kernel/cpu/perf_event.h b/trunk/arch/x86/kernel/cpu/perf_event.h index 8b6defe7eefc..6605a81ba339 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.h +++ b/trunk/arch/x86/kernel/cpu/perf_event.h @@ -586,8 +586,6 @@ extern struct event_constraint intel_westmere_pebs_event_constraints[]; extern struct event_constraint intel_snb_pebs_event_constraints[]; -extern struct event_constraint intel_ivb_pebs_event_constraints[]; - struct event_constraint *intel_pebs_constraints(struct perf_event *event); void intel_pmu_pebs_enable(struct perf_event *event); diff --git a/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c index eebd5ffe1bba..7bfb5bec8630 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -209,15 +209,6 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config) return -EOPNOTSUPP; } -static const struct perf_event_attr ibs_notsupp = { - .exclude_user = 1, - .exclude_kernel = 1, - .exclude_hv = 1, - .exclude_idle = 1, - .exclude_host = 1, - .exclude_guest = 1, -}; - static int perf_ibs_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; @@ -238,9 +229,6 @@ static int perf_ibs_init(struct perf_event *event) if (event->pmu != &perf_ibs->pmu) return -ENOENT; - if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp)) - return -EINVAL; - if (config & ~perf_ibs->config_mask) return -EINVAL; diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel.c b/trunk/arch/x86/kernel/cpu/perf_event_intel.c index 6bca492b8547..0d3d63afa76a 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel.c @@ -2048,6 +2048,7 @@ __init int intel_pmu_init(void) case 42: /* SandyBridge */ case 45: /* SandyBridge, "Romely-EP" */ x86_add_quirk(intel_sandybridge_quirk); + case 58: /* IvyBridge */ memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, @@ -2072,29 +2073,6 @@ __init int intel_pmu_init(void) pr_cont("SandyBridge events, "); break; - case 58: /* IvyBridge */ - memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, - sizeof(hw_cache_event_ids)); - memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, - sizeof(hw_cache_extra_regs)); - - intel_pmu_lbr_init_snb(); - - x86_pmu.event_constraints = intel_snb_event_constraints; - x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints; - x86_pmu.pebs_aliases = intel_pebs_aliases_snb; - x86_pmu.extra_regs = intel_snb_extra_regs; - /* all extra regs are per-cpu when HT is on */ - x86_pmu.er_flags |= ERF_HAS_RSP_1; - x86_pmu.er_flags |= ERF_NO_HT_SHARING; - - /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */ - intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = - X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1); - - pr_cont("IvyBridge events, "); - break; - default: switch (x86_pmu.version) { diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c index 826054a4f2ee..e38d97bf4259 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -407,20 +407,6 @@ struct event_constraint intel_snb_pebs_event_constraints[] = { EVENT_CONSTRAINT_END }; -struct event_constraint intel_ivb_pebs_event_constraints[] = { - INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ - INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ - INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */ - INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */ - EVENT_CONSTRAINT_END -}; - struct event_constraint *intel_pebs_constraints(struct perf_event *event) { struct event_constraint *c; diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 38e4894165b9..0a5571080e74 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -661,11 +661,6 @@ static void snb_uncore_msr_init_box(struct intel_uncore_box *box) } } -static struct uncore_event_desc snb_uncore_events[] = { - INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"), - { /* end: all zeroes */ }, -}; - static struct attribute *snb_uncore_formats_attr[] = { &format_attr_event.attr, &format_attr_umask.attr, @@ -709,7 +704,6 @@ static struct intel_uncore_type snb_uncore_cbox = { .constraints = snb_uncore_cbox_constraints, .ops = &snb_uncore_msr_ops, .format_group = &snb_uncore_format_group, - .event_descs = snb_uncore_events, }; static struct intel_uncore_type *snb_msr_uncores[] = { diff --git a/trunk/arch/x86/mm/init.c b/trunk/arch/x86/mm/init.c index ab1f6a93b527..e0e6990723e9 100644 --- a/trunk/arch/x86/mm/init.c +++ b/trunk/arch/x86/mm/init.c @@ -319,7 +319,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, */ int devmem_is_allowed(unsigned long pagenr) { - if (pagenr < 256) + if (pagenr <= 256) return 1; if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) return 0; diff --git a/trunk/arch/x86/net/bpf_jit_comp.c b/trunk/arch/x86/net/bpf_jit_comp.c index 520d2bd0b9c5..106c57829120 100644 --- a/trunk/arch/x86/net/bpf_jit_comp.c +++ b/trunk/arch/x86/net/bpf_jit_comp.c @@ -335,18 +335,9 @@ void bpf_jit_compile(struct sk_filter *fp) EMIT1_off32(0x0d, K); /* or imm32,%eax */ break; case BPF_S_ANC_ALU_XOR_X: /* A ^= X; */ - case BPF_S_ALU_XOR_X: seen |= SEEN_XREG; EMIT2(0x31, 0xd8); /* xor %ebx,%eax */ break; - case BPF_S_ALU_XOR_K: /* A ^= K; */ - if (K == 0) - break; - if (is_imm8(K)) - EMIT3(0x83, 0xf0, K); /* xor imm8,%eax */ - else - EMIT1_off32(0x35, K); /* xor imm32,%eax */ - break; case BPF_S_ALU_LSH_X: /* A <<= X; */ seen |= SEEN_XREG; EMIT4(0x89, 0xd9, 0xd3, 0xe0); /* mov %ebx,%ecx; shl %cl,%eax */ diff --git a/trunk/arch/x86/um/Kconfig b/trunk/arch/x86/um/Kconfig index aeaff8bef2f1..9926e11a772d 100644 --- a/trunk/arch/x86/um/Kconfig +++ b/trunk/arch/x86/um/Kconfig @@ -21,7 +21,6 @@ config 64BIT config X86_32 def_bool !64BIT select HAVE_AOUT - select ARCH_WANT_IPC_PARSE_VERSION config X86_64 def_bool 64BIT diff --git a/trunk/arch/x86/um/shared/sysdep/kernel-offsets.h b/trunk/arch/x86/um/shared/sysdep/kernel-offsets.h index 46a9df99f3c5..5868526b5eef 100644 --- a/trunk/arch/x86/um/shared/sysdep/kernel-offsets.h +++ b/trunk/arch/x86/um/shared/sysdep/kernel-offsets.h @@ -7,6 +7,9 @@ #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) +#define STR(x) #x +#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : ) + #define BLANK() asm volatile("\n->" : : ) #define OFFSET(sym, str, mem) \ diff --git a/trunk/arch/x86/um/shared/sysdep/syscalls.h b/trunk/arch/x86/um/shared/sysdep/syscalls.h index ca255a805ed9..bd9a89b67e41 100644 --- a/trunk/arch/x86/um/shared/sysdep/syscalls.h +++ b/trunk/arch/x86/um/shared/sysdep/syscalls.h @@ -1,5 +1,3 @@ -extern long sys_clone(unsigned long clone_flags, unsigned long newsp, - void __user *parent_tid, void __user *child_tid); #ifdef __i386__ #include "syscalls_32.h" #else diff --git a/trunk/arch/x86/um/signal.c b/trunk/arch/x86/um/signal.c index ba7363ecf896..a508cea13503 100644 --- a/trunk/arch/x86/um/signal.c +++ b/trunk/arch/x86/um/signal.c @@ -416,6 +416,9 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, PT_REGS_AX(regs) = (unsigned long) sig; PT_REGS_DX(regs) = (unsigned long) 0; PT_REGS_CX(regs) = (unsigned long) 0; + + if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) + ptrace_notify(SIGTRAP); return 0; } @@ -463,6 +466,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, PT_REGS_AX(regs) = (unsigned long) sig; PT_REGS_DX(regs) = (unsigned long) &frame->info; PT_REGS_CX(regs) = (unsigned long) &frame->uc; + + if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) + ptrace_notify(SIGTRAP); return 0; } diff --git a/trunk/arch/x86/um/sys_call_table_32.c b/trunk/arch/x86/um/sys_call_table_32.c index b5408cecac6c..68d1dc91b37b 100644 --- a/trunk/arch/x86/um/sys_call_table_32.c +++ b/trunk/arch/x86/um/sys_call_table_32.c @@ -28,7 +28,7 @@ #define ptregs_execve sys_execve #define ptregs_iopl sys_iopl #define ptregs_vm86old sys_vm86old -#define ptregs_clone i386_clone +#define ptregs_clone sys_clone #define ptregs_vm86 sys_vm86 #define ptregs_sigaltstack sys_sigaltstack #define ptregs_vfork sys_vfork diff --git a/trunk/arch/x86/um/syscalls_32.c b/trunk/arch/x86/um/syscalls_32.c index db444c7218fe..b853e8600b9d 100644 --- a/trunk/arch/x86/um/syscalls_32.c +++ b/trunk/arch/x86/um/syscalls_32.c @@ -3,23 +3,36 @@ * Licensed under the GPL */ -#include -#include +#include "linux/sched.h" +#include "linux/shm.h" +#include "linux/ipc.h" +#include "linux/syscalls.h" +#include "asm/mman.h" +#include "asm/uaccess.h" +#include "asm/unistd.h" /* * The prototype on i386 is: * - * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls + * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr) * * and the "newtls" arg. on i386 is read by copy_thread directly from the * register saved on the stack. */ -long i386_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tid, void *newtls, int __user *child_tid) +long sys_clone(unsigned long clone_flags, unsigned long newsp, + int __user *parent_tid, void *newtls, int __user *child_tid) { - return sys_clone(clone_flags, newsp, parent_tid, child_tid); -} + long ret; + + if (!newsp) + newsp = UPT_SP(¤t->thread.regs.regs); + current->thread.forking = 1; + ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, + child_tid); + current->thread.forking = 0; + return ret; +} long sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) diff --git a/trunk/arch/x86/um/syscalls_64.c b/trunk/arch/x86/um/syscalls_64.c index adb08eb5c22a..f3d82bb6e15a 100644 --- a/trunk/arch/x86/um/syscalls_64.c +++ b/trunk/arch/x86/um/syscalls_64.c @@ -5,9 +5,12 @@ * Licensed under the GPL */ -#include -#include /* XXX This should get the constants from libc */ -#include +#include "linux/linkage.h" +#include "linux/personality.h" +#include "linux/utsname.h" +#include "asm/prctl.h" /* XXX This should get the constants from libc */ +#include "asm/uaccess.h" +#include "os.h" long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) { @@ -76,6 +79,20 @@ long sys_arch_prctl(int code, unsigned long addr) return arch_prctl(current, code, (unsigned long __user *) addr); } +long sys_clone(unsigned long clone_flags, unsigned long newsp, + void __user *parent_tid, void __user *child_tid) +{ + long ret; + + if (!newsp) + newsp = UPT_SP(¤t->thread.regs.regs); + current->thread.forking = 1; + ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, + child_tid); + current->thread.forking = 0; + return ret; +} + void arch_switch_to(struct task_struct *to) { if ((to->thread.arch.fs == 0) || (to->mm == NULL)) diff --git a/trunk/arch/x86/xen/enlighten.c b/trunk/arch/x86/xen/enlighten.c index 1fbe75a95f15..9642d4a38602 100644 --- a/trunk/arch/x86/xen/enlighten.c +++ b/trunk/arch/x86/xen/enlighten.c @@ -1452,10 +1452,6 @@ asmlinkage void __init xen_start_kernel(void) pci_request_acs(); xen_acpi_sleep_register(); - - /* Avoid searching for BIOS MP tables */ - x86_init.mpparse.find_smp_config = x86_init_noop; - x86_init.mpparse.get_smp_config = x86_init_uint_noop; } #ifdef CONFIG_PCI /* PCI BIOS service won't work from a PV guest. */ diff --git a/trunk/arch/x86/xen/p2m.c b/trunk/arch/x86/xen/p2m.c index 72213da605f5..76ba0e97e530 100644 --- a/trunk/arch/x86/xen/p2m.c +++ b/trunk/arch/x86/xen/p2m.c @@ -828,6 +828,9 @@ int m2p_add_override(unsigned long mfn, struct page *page, xen_mc_issue(PARAVIRT_LAZY_MMU); } + /* let's use dev_bus_addr to record the old mfn instead */ + kmap_op->dev_bus_addr = page->index; + page->index = (unsigned long) kmap_op; } spin_lock_irqsave(&m2p_override_lock, flags); list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); @@ -854,8 +857,7 @@ int m2p_add_override(unsigned long mfn, struct page *page, return 0; } EXPORT_SYMBOL_GPL(m2p_add_override); -int m2p_remove_override(struct page *page, - struct gnttab_map_grant_ref *kmap_op) +int m2p_remove_override(struct page *page, bool clear_pte) { unsigned long flags; unsigned long mfn; @@ -885,8 +887,10 @@ int m2p_remove_override(struct page *page, WARN_ON(!PagePrivate(page)); ClearPagePrivate(page); - set_phys_to_machine(pfn, page->index); - if (kmap_op != NULL) { + if (clear_pte) { + struct gnttab_map_grant_ref *map_op = + (struct gnttab_map_grant_ref *) page->index; + set_phys_to_machine(pfn, map_op->dev_bus_addr); if (!PageHighMem(page)) { struct multicall_space mcs; struct gnttab_unmap_grant_ref *unmap_op; @@ -898,13 +902,13 @@ int m2p_remove_override(struct page *page, * issued. In this case handle is going to -1 because * it hasn't been modified yet. */ - if (kmap_op->handle == -1) + if (map_op->handle == -1) xen_mc_flush(); /* - * Now if kmap_op->handle is negative it means that the + * Now if map_op->handle is negative it means that the * hypercall actually returned an error. */ - if (kmap_op->handle == GNTST_general_error) { + if (map_op->handle == GNTST_general_error) { printk(KERN_WARNING "m2p_remove_override: " "pfn %lx mfn %lx, failed to modify kernel mappings", pfn, mfn); @@ -914,8 +918,8 @@ int m2p_remove_override(struct page *page, mcs = xen_mc_entry( sizeof(struct gnttab_unmap_grant_ref)); unmap_op = mcs.args; - unmap_op->host_addr = kmap_op->host_addr; - unmap_op->handle = kmap_op->handle; + unmap_op->host_addr = map_op->host_addr; + unmap_op->handle = map_op->handle; unmap_op->dev_bus_addr = 0; MULTI_grant_table_op(mcs.mc, @@ -926,9 +930,10 @@ int m2p_remove_override(struct page *page, set_pte_at(&init_mm, address, ptep, pfn_pte(pfn, PAGE_KERNEL)); __flush_tlb_single(address); - kmap_op->host_addr = 0; + map_op->host_addr = 0; } - } + } else + set_phys_to_machine(pfn, page->index); /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present * somewhere in this domain, even before being added to the diff --git a/trunk/arch/x86/xen/setup.c b/trunk/arch/x86/xen/setup.c index e2d62d697b5d..d11ca11d14fc 100644 --- a/trunk/arch/x86/xen/setup.c +++ b/trunk/arch/x86/xen/setup.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -545,7 +544,4 @@ void __init xen_arch_setup(void) disable_cpufreq(); WARN_ON(set_pm_idle_to_default()); fiddle_vdso(); -#ifdef CONFIG_NUMA - numa_off = 1; -#endif } diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index ee3cb3a5e278..4b4dbdfbca89 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -2254,11 +2254,9 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) error_type = "I/O"; break; } - printk_ratelimited(KERN_ERR "end_request: %s error, dev %s, sector %llu\n", - error_type, req->rq_disk ? - req->rq_disk->disk_name : "?", - (unsigned long long)blk_rq_pos(req)); - + printk(KERN_ERR "end_request: %s error, dev %s, sector %llu\n", + error_type, req->rq_disk ? req->rq_disk->disk_name : "?", + (unsigned long long)blk_rq_pos(req)); } blk_account_io_completion(req, nr_bytes); diff --git a/trunk/block/ioctl.c b/trunk/block/ioctl.c index 4a85096f5410..4476e0e85d16 100644 --- a/trunk/block/ioctl.c +++ b/trunk/block/ioctl.c @@ -41,7 +41,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user sizeof(long long) > sizeof(long)) { long pstart = start, plength = length; if (pstart != start || plength != length - || pstart < 0 || plength < 0 || partno > 65535) + || pstart < 0 || plength < 0) return -EINVAL; } diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index e0596954290b..9628652e080c 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -237,16 +237,6 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state) } else if (result == ACPI_STATE_D3_HOT) { result = ACPI_STATE_D3; } - - /* - * If we were unsure about the device parent's power state up to this - * point, the fact that the device is in D0 implies that the parent has - * to be in D0 too. - */ - if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN - && result == ACPI_STATE_D0) - device->parent->power.state = ACPI_STATE_D0; - *state = result; out: diff --git a/trunk/drivers/acpi/power.c b/trunk/drivers/acpi/power.c index 40e38a06ba85..fc1803414629 100644 --- a/trunk/drivers/acpi/power.c +++ b/trunk/drivers/acpi/power.c @@ -107,7 +107,6 @@ struct acpi_power_resource { /* List of devices relying on this power resource */ struct acpi_power_resource_device *devices; - struct mutex devices_lock; }; static struct list_head acpi_power_resource_list; @@ -226,6 +225,7 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device) static int __acpi_power_on(struct acpi_power_resource *resource) { + struct acpi_power_resource_device *device_list = resource->devices; acpi_status status = AE_OK; status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); @@ -238,15 +238,19 @@ static int __acpi_power_on(struct acpi_power_resource *resource) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", resource->name)); + while (device_list) { + acpi_power_on_device(device_list->device); + + device_list = device_list->next; + } + return 0; } static int acpi_power_on(acpi_handle handle) { int result = 0; - bool resume_device = false; struct acpi_power_resource *resource = NULL; - struct acpi_power_resource_device *device_list; result = acpi_power_get_context(handle, &resource); if (result) @@ -262,25 +266,10 @@ static int acpi_power_on(acpi_handle handle) result = __acpi_power_on(resource); if (result) resource->ref_count--; - else - resume_device = true; } mutex_unlock(&resource->resource_lock); - if (!resume_device) - return result; - - mutex_lock(&resource->devices_lock); - - device_list = resource->devices; - while (device_list) { - acpi_power_on_device(device_list->device); - device_list = device_list->next; - } - - mutex_unlock(&resource->devices_lock); - return result; } @@ -366,7 +355,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, if (acpi_power_get_context(res_handle, &resource)) return; - mutex_lock(&resource->devices_lock); + mutex_lock(&resource->resource_lock); prev = NULL; curr = resource->devices; while (curr) { @@ -383,7 +372,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, prev = curr; curr = curr->next; } - mutex_unlock(&resource->devices_lock); + mutex_unlock(&resource->resource_lock); } /* Unlink dev from all power resources in _PR0 */ @@ -425,10 +414,10 @@ static int __acpi_power_resource_register_device( power_resource_device->device = powered_device; - mutex_lock(&resource->devices_lock); + mutex_lock(&resource->resource_lock); power_resource_device->next = resource->devices; resource->devices = power_resource_device; - mutex_unlock(&resource->devices_lock); + mutex_unlock(&resource->resource_lock); return 0; } @@ -473,7 +462,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) return ret; no_power_resource: - printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!"); + printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); return -ENODEV; } EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); @@ -732,7 +721,6 @@ static int acpi_power_add(struct acpi_device *device) resource->device = device; mutex_init(&resource->resource_lock); - mutex_init(&resource->devices_lock); strcpy(resource->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); diff --git a/trunk/drivers/bcma/core.c b/trunk/drivers/bcma/core.c index 03bbe104338f..63c8b470536f 100644 --- a/trunk/drivers/bcma/core.c +++ b/trunk/drivers/bcma/core.c @@ -65,7 +65,7 @@ void bcma_core_set_clockmode(struct bcma_device *core, switch (clkmode) { case BCMA_CLKMODE_FAST: bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT); - usleep_range(64, 300); + udelay(64); for (i = 0; i < 1500; i++) { if (bcma_read32(core, BCMA_CLKCTLST) & BCMA_CLKCTLST_HAVEHT) { diff --git a/trunk/drivers/bcma/driver_chipcommon_pmu.c b/trunk/drivers/bcma/driver_chipcommon_pmu.c index 201faf106b3f..8b8f2f3862a2 100644 --- a/trunk/drivers/bcma/driver_chipcommon_pmu.c +++ b/trunk/drivers/bcma/driver_chipcommon_pmu.c @@ -76,10 +76,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) if (max_msk) bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); - /* - * Add some delay; allow resources to come up and settle. - * Delay is required for SoC (early init). - */ + /* Add some delay; allow resources to come up and settle. */ mdelay(2); } diff --git a/trunk/drivers/bcma/driver_pci.c b/trunk/drivers/bcma/driver_pci.c index c39ee6d45850..c32ebd537abe 100644 --- a/trunk/drivers/bcma/driver_pci.c +++ b/trunk/drivers/bcma/driver_pci.c @@ -51,7 +51,7 @@ static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) break; - usleep_range(1000, 2000); + msleep(1); } } @@ -92,7 +92,7 @@ static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA); break; } - usleep_range(1000, 2000); + msleep(1); } pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); return ret; @@ -132,7 +132,7 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) break; - usleep_range(1000, 2000); + msleep(1); } pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); } diff --git a/trunk/drivers/bcma/driver_pci_host.c b/trunk/drivers/bcma/driver_pci_host.c index 9baf886e82df..cbae2c231336 100644 --- a/trunk/drivers/bcma/driver_pci_host.c +++ b/trunk/drivers/bcma/driver_pci_host.c @@ -425,9 +425,9 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; /* Reset RC */ - usleep_range(3000, 5000); + udelay(3000); pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); - usleep_range(1000, 2000); + udelay(1000); pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | BCMA_CORE_PCI_CTL_RST_OE); @@ -481,7 +481,7 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) * before issuing configuration requests to PCI Express * devices. */ - msleep(100); + udelay(100000); bcma_core_pci_enable_crs(pc); @@ -501,7 +501,7 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) set_io_port_base(pc_host->pci_controller.io_map_base); /* Give some time to the PCI controller to configure itself with the new * values. Not waiting at this point causes crashes of the machine. */ - usleep_range(10000, 15000); + mdelay(10); register_pci_controller(&pc_host->pci_controller); return; } diff --git a/trunk/drivers/bcma/host_pci.c b/trunk/drivers/bcma/host_pci.c index b6b4b5ebd4c2..f7b0af7100cd 100644 --- a/trunk/drivers/bcma/host_pci.c +++ b/trunk/drivers/bcma/host_pci.c @@ -273,7 +273,6 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { 0, }, diff --git a/trunk/drivers/bcma/sprom.c b/trunk/drivers/bcma/sprom.c index 0d546b64be34..9ea4627dc0c2 100644 --- a/trunk/drivers/bcma/sprom.c +++ b/trunk/drivers/bcma/sprom.c @@ -507,9 +507,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) /* for these chips OTP is always available */ present = true; break; - case BCMA_CHIP_ID_BCM43227: case BCMA_CHIP_ID_BCM43228: - case BCMA_CHIP_ID_BCM43428: present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT; break; default: diff --git a/trunk/drivers/block/aoe/aoecmd.c b/trunk/drivers/block/aoe/aoecmd.c index 887f68f6d79a..de0435e63b02 100644 --- a/trunk/drivers/block/aoe/aoecmd.c +++ b/trunk/drivers/block/aoe/aoecmd.c @@ -35,7 +35,6 @@ new_skb(ulong len) skb_reset_mac_header(skb); skb_reset_network_header(skb); skb->protocol = __constant_htons(ETH_P_AOE); - skb_checksum_none_assert(skb); } return skb; } diff --git a/trunk/drivers/block/cciss_scsi.c b/trunk/drivers/block/cciss_scsi.c index da3311129a0c..38aa6dda6b81 100644 --- a/trunk/drivers/block/cciss_scsi.c +++ b/trunk/drivers/block/cciss_scsi.c @@ -795,7 +795,6 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, } break; case CMD_PROTOCOL_ERR: - cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "%p has protocol error\n", c); break; diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.c b/trunk/drivers/block/mtip32xx/mtip32xx.c index f946d31d6917..a8fddeb3d638 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.c +++ b/trunk/drivers/block/mtip32xx/mtip32xx.c @@ -1148,15 +1148,11 @@ static bool mtip_pause_ncq(struct mtip_port *port, reply = port->rxfis + RX_FIS_D2H_REG; task_file_data = readl(port->mmio+PORT_TFDATA); - if (fis->command == ATA_CMD_SEC_ERASE_UNIT) - clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag); - - if ((task_file_data & 1)) + if ((task_file_data & 1) || (fis->command == ATA_CMD_SEC_ERASE_UNIT)) return false; if (fis->command == ATA_CMD_SEC_ERASE_PREP) { set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); - set_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag); port->ic_pause_timer = jiffies; return true; } else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) && @@ -1904,7 +1900,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, int rv = 0, xfer_sz = command[3]; if (xfer_sz) { - if (!user_buffer) + if (user_buffer) return -EFAULT; buf = dmam_alloc_coherent(&port->dd->pdev->dev, @@ -2047,7 +2043,7 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) *timeout = 240000; /* 4 minutes */ break; case ATA_CMD_STANDBYNOW1: - *timeout = 120000; /* 2 minutes */ + *timeout = 10000; /* 10 seconds */ break; case 0xF7: case 0xFA: @@ -2592,6 +2588,9 @@ static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf, if (!len || size) return 0; + if (size < 0) + return -EINVAL; + size += sprintf(&buf[size], "H/ S ACTive : [ 0x"); for (n = dd->slot_groups-1; n >= 0; n--) @@ -2661,6 +2660,9 @@ static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf, if (!len || size) return 0; + if (size < 0) + return -EINVAL; + size += sprintf(&buf[size], "Flag-port : [ %08lX ]\n", dd->port->flags); size += sprintf(&buf[size], "Flag-dd : [ %08lX ]\n", @@ -3212,8 +3214,8 @@ static int mtip_hw_init(struct driver_data *dd) "Unable to check write protect progress\n"); else dev_info(&dd->pdev->dev, - "Write protect progress: %u%% (%u blocks)\n", - attr242.cur, le32_to_cpu(attr242.data)); + "Write protect progress: %d%% (%d blocks)\n", + attr242.cur, attr242.data); return rv; out3: @@ -3617,10 +3619,6 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) bio_endio(bio, -ENODATA); return; } - if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))) { - bio_endio(bio, -ENODATA); - return; - } } if (unlikely(!bio_has_data(bio))) { @@ -4170,13 +4168,7 @@ static void mtip_pci_shutdown(struct pci_dev *pdev) /* Table of device ids supported by this driver. */ static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = { - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320H_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320M_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320S_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P325M_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420H_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420M_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P425M_DEVICE_ID) }, + { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320_DEVICE_ID) }, { 0 } }; @@ -4207,12 +4199,12 @@ static int __init mtip_init(void) { int error; - pr_info(MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n"); + printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n"); /* Allocate a major block device number to use with this driver. */ error = register_blkdev(0, MTIP_DRV_NAME); if (error <= 0) { - pr_err("Unable to register block device (%d)\n", + printk(KERN_ERR "Unable to register block device (%d)\n", error); return -EBUSY; } @@ -4221,7 +4213,7 @@ static int __init mtip_init(void) if (!dfs_parent) { dfs_parent = debugfs_create_dir("rssd", NULL); if (IS_ERR_OR_NULL(dfs_parent)) { - pr_warn("Error creating debugfs parent\n"); + printk(KERN_WARNING "Error creating debugfs parent\n"); dfs_parent = NULL; } } diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.h b/trunk/drivers/block/mtip32xx/mtip32xx.h index 18627a1d04c5..f51fc23d17bb 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.h +++ b/trunk/drivers/block/mtip32xx/mtip32xx.h @@ -76,13 +76,7 @@ /* Micron Vendor ID & P320x SSD Device ID */ #define PCI_VENDOR_ID_MICRON 0x1344 -#define P320H_DEVICE_ID 0x5150 -#define P320M_DEVICE_ID 0x5151 -#define P320S_DEVICE_ID 0x5152 -#define P325M_DEVICE_ID 0x5153 -#define P420H_DEVICE_ID 0x5160 -#define P420M_DEVICE_ID 0x5161 -#define P425M_DEVICE_ID 0x5163 +#define P320_DEVICE_ID 0x5150 /* Driver name and version strings */ #define MTIP_DRV_NAME "mtip32xx" @@ -137,12 +131,10 @@ enum { MTIP_PF_SVC_THD_STOP_BIT = 8, /* below are bit numbers in 'dd_flag' defined in driver_data */ - MTIP_DDF_SEC_LOCK_BIT = 0, MTIP_DDF_REMOVE_PENDING_BIT = 1, MTIP_DDF_OVER_TEMP_BIT = 2, MTIP_DDF_WRITE_PROTECT_BIT = 3, MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \ - (1 << MTIP_DDF_SEC_LOCK_BIT) | \ (1 << MTIP_DDF_OVER_TEMP_BIT) | \ (1 << MTIP_DDF_WRITE_PROTECT_BIT)), diff --git a/trunk/drivers/block/nbd.c b/trunk/drivers/block/nbd.c index 0c03411c59eb..d07c9f7fded6 100644 --- a/trunk/drivers/block/nbd.c +++ b/trunk/drivers/block/nbd.c @@ -449,14 +449,6 @@ static void nbd_clear_que(struct nbd_device *nbd) req->errors++; nbd_end_request(req); } - - while (!list_empty(&nbd->waiting_queue)) { - req = list_entry(nbd->waiting_queue.next, struct request, - queuelist); - list_del_init(&req->queuelist); - req->errors++; - nbd_end_request(req); - } } @@ -606,7 +598,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, nbd->file = NULL; nbd_clear_que(nbd); BUG_ON(!list_empty(&nbd->queue_head)); - BUG_ON(!list_empty(&nbd->waiting_queue)); if (file) fput(file); return 0; diff --git a/trunk/drivers/block/rbd.c b/trunk/drivers/block/rbd.c index 54a55f03115d..9917943a3572 100644 --- a/trunk/drivers/block/rbd.c +++ b/trunk/drivers/block/rbd.c @@ -246,12 +246,13 @@ static int rbd_open(struct block_device *bdev, fmode_t mode) { struct rbd_device *rbd_dev = bdev->bd_disk->private_data; - if ((mode & FMODE_WRITE) && rbd_dev->read_only) - return -EROFS; - rbd_get_dev(rbd_dev); + set_device_ro(bdev, rbd_dev->read_only); + if ((mode & FMODE_WRITE) && rbd_dev->read_only) + return -EROFS; + return 0; } diff --git a/trunk/drivers/block/xen-blkback/blkback.c b/trunk/drivers/block/xen-blkback/blkback.c index c6decb901e5e..73f196ca713f 100644 --- a/trunk/drivers/block/xen-blkback/blkback.c +++ b/trunk/drivers/block/xen-blkback/blkback.c @@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req) invcount++; } - ret = gnttab_unmap_refs(unmap, NULL, pages, invcount); + ret = gnttab_unmap_refs(unmap, pages, invcount, false); BUG_ON(ret); } diff --git a/trunk/drivers/bluetooth/bluecard_cs.c b/trunk/drivers/bluetooth/bluecard_cs.c index 0d26851d6e49..0c0838d9b56c 100644 --- a/trunk/drivers/bluetooth/bluecard_cs.c +++ b/trunk/drivers/bluetooth/bluecard_cs.c @@ -681,7 +681,7 @@ static int bluecard_hci_send_frame(struct sk_buff *skb) case HCI_SCODATA_PKT: hdev->stat.sco_tx++; break; - } + }; /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); diff --git a/trunk/drivers/bluetooth/btmrvl_sdio.c b/trunk/drivers/bluetooth/btmrvl_sdio.c index 3f4bfc814dc7..03b3acba6143 100644 --- a/trunk/drivers/bluetooth/btmrvl_sdio.c +++ b/trunk/drivers/bluetooth/btmrvl_sdio.c @@ -600,7 +600,8 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) exit: if (ret) { hdev->stat.err_rx++; - kfree_skb(skb); + if (skb) + kfree_skb(skb); } return ret; diff --git a/trunk/drivers/bluetooth/btuart_cs.c b/trunk/drivers/bluetooth/btuart_cs.c index 35a553a90616..2f510a87b28f 100644 --- a/trunk/drivers/bluetooth/btuart_cs.c +++ b/trunk/drivers/bluetooth/btuart_cs.c @@ -446,7 +446,7 @@ static int btuart_hci_send_frame(struct sk_buff *skb) case HCI_SCODATA_PKT: hdev->stat.sco_tx++; break; - } + }; /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); diff --git a/trunk/drivers/bluetooth/btusb.c b/trunk/drivers/bluetooth/btusb.c index debda27df9b0..e5921d681ddb 100644 --- a/trunk/drivers/bluetooth/btusb.c +++ b/trunk/drivers/bluetooth/btusb.c @@ -96,12 +96,11 @@ static struct usb_device_id btusb_table[] = { { USB_DEVICE(0x0c10, 0x0000) }, /* Broadcom BCM20702A0 */ - { USB_DEVICE(0x04ca, 0x2003) }, { USB_DEVICE(0x0489, 0xe042) }, { USB_DEVICE(0x413c, 0x8197) }, /* Foxconn - Hon Hai */ - { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) }, + { USB_DEVICE(0x0489, 0xe033) }, /*Broadcom devices with vendor specific id */ { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, diff --git a/trunk/drivers/bluetooth/btwilink.c b/trunk/drivers/bluetooth/btwilink.c index 60abf596f60e..4ad7b35cfc0e 100644 --- a/trunk/drivers/bluetooth/btwilink.c +++ b/trunk/drivers/bluetooth/btwilink.c @@ -358,7 +358,21 @@ static struct platform_driver btwilink_driver = { }, }; -module_platform_driver(btwilink_driver); +/* ------- Module Init/Exit interfaces ------ */ +static int __init btwilink_init(void) +{ + BT_INFO("Bluetooth Driver for TI WiLink - Version %s", VERSION); + + return platform_driver_register(&btwilink_driver); +} + +static void __exit btwilink_exit(void) +{ + platform_driver_unregister(&btwilink_driver); +} + +module_init(btwilink_init); +module_exit(btwilink_exit); /* ------ Module Info ------ */ diff --git a/trunk/drivers/bluetooth/hci_ldisc.c b/trunk/drivers/bluetooth/hci_ldisc.c index c8abce3d2d9c..74e0966b3ead 100644 --- a/trunk/drivers/bluetooth/hci_ldisc.c +++ b/trunk/drivers/bluetooth/hci_ldisc.c @@ -531,7 +531,7 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, default: err = n_tty_ioctl_helper(tty, file, cmd, arg); break; - } + }; return err; } diff --git a/trunk/drivers/bluetooth/hci_ll.c b/trunk/drivers/bluetooth/hci_ll.c index cfc767938589..ff6d589c34a5 100644 --- a/trunk/drivers/bluetooth/hci_ll.c +++ b/trunk/drivers/bluetooth/hci_ll.c @@ -481,7 +481,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) hu->hdev->stat.err_rx++; ptr++; count--; continue; - } + }; ptr++; count--; diff --git a/trunk/drivers/bluetooth/hci_vhci.c b/trunk/drivers/bluetooth/hci_vhci.c index d8b7aed6e4a9..3f72595a6017 100644 --- a/trunk/drivers/bluetooth/hci_vhci.c +++ b/trunk/drivers/bluetooth/hci_vhci.c @@ -156,7 +156,7 @@ static inline ssize_t vhci_put_user(struct vhci_data *data, case HCI_SCODATA_PKT: data->hdev->stat.sco_tx++; break; - } + }; return total; } diff --git a/trunk/drivers/clk/Makefile b/trunk/drivers/clk/Makefile index 72ce247a0e8d..5869ea387054 100644 --- a/trunk/drivers/clk/Makefile +++ b/trunk/drivers/clk/Makefile @@ -1,5 +1,4 @@ # common clock types -obj-$(CONFIG_HAVE_CLK) += clk-devres.o obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ clk-mux.o clk-divider.o clk-fixed-factor.o diff --git a/trunk/drivers/clk/clk-devres.c b/trunk/drivers/clk/clk-devres.c deleted file mode 100644 index 8f571548870f..000000000000 --- a/trunk/drivers/clk/clk-devres.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -static void devm_clk_release(struct device *dev, void *res) -{ - clk_put(*(struct clk **)res); -} - -struct clk *devm_clk_get(struct device *dev, const char *id) -{ - struct clk **ptr, *clk; - - ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); - - clk = clk_get(dev, id); - if (!IS_ERR(clk)) { - *ptr = clk; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } - - return clk; -} -EXPORT_SYMBOL(devm_clk_get); - -static int devm_clk_match(struct device *dev, void *res, void *data) -{ - struct clk **c = res; - if (!c || !*c) { - WARN_ON(!c || !*c); - return 0; - } - return *c == data; -} - -void devm_clk_put(struct device *dev, struct clk *clk) -{ - int ret; - - ret = devres_release(dev, devm_clk_release, devm_clk_match, clk); - - WARN_ON(ret); -} -EXPORT_SYMBOL(devm_clk_put); diff --git a/trunk/drivers/clk/clkdev.c b/trunk/drivers/clk/clkdev.c index 442a31363873..d423c9bdd71a 100644 --- a/trunk/drivers/clk/clkdev.c +++ b/trunk/drivers/clk/clkdev.c @@ -171,6 +171,51 @@ void clk_put(struct clk *clk) } EXPORT_SYMBOL(clk_put); +static void devm_clk_release(struct device *dev, void *res) +{ + clk_put(*(struct clk **)res); +} + +struct clk *devm_clk_get(struct device *dev, const char *id) +{ + struct clk **ptr, *clk; + + ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + clk = clk_get(dev, id); + if (!IS_ERR(clk)) { + *ptr = clk; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return clk; +} +EXPORT_SYMBOL(devm_clk_get); + +static int devm_clk_match(struct device *dev, void *res, void *data) +{ + struct clk **c = res; + if (!c || !*c) { + WARN_ON(!c || !*c); + return 0; + } + return *c == data; +} + +void devm_clk_put(struct device *dev, struct clk *clk) +{ + int ret; + + ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk); + + WARN_ON(ret); +} +EXPORT_SYMBOL(devm_clk_put); + void clkdev_add(struct clk_lookup *cl) { mutex_lock(&clocks_mutex); diff --git a/trunk/drivers/cpufreq/powernow-k8.c b/trunk/drivers/cpufreq/powernow-k8.c index 1a40935c85fd..c0e816468e30 100644 --- a/trunk/drivers/cpufreq/powernow-k8.c +++ b/trunk/drivers/cpufreq/powernow-k8.c @@ -35,6 +35,7 @@ #include #include #include +#include /* for current / set_cpus_allowed() */ #include #include @@ -1138,23 +1139,16 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, return res; } -struct powernowk8_target_arg { - struct cpufreq_policy *pol; - unsigned targfreq; - unsigned relation; -}; - -static long powernowk8_target_fn(void *arg) +/* Driver entry point to switch to the target frequency */ +static int powernowk8_target(struct cpufreq_policy *pol, + unsigned targfreq, unsigned relation) { - struct powernowk8_target_arg *pta = arg; - struct cpufreq_policy *pol = pta->pol; - unsigned targfreq = pta->targfreq; - unsigned relation = pta->relation; + cpumask_var_t oldmask; struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); u32 checkfid; u32 checkvid; unsigned int newstate; - int ret; + int ret = -EIO; if (!data) return -EINVAL; @@ -1162,16 +1156,29 @@ static long powernowk8_target_fn(void *arg) checkfid = data->currfid; checkvid = data->currvid; + /* only run on specific CPU from here on. */ + /* This is poor form: use a workqueue or smp_call_function_single */ + if (!alloc_cpumask_var(&oldmask, GFP_KERNEL)) + return -ENOMEM; + + cpumask_copy(oldmask, tsk_cpus_allowed(current)); + set_cpus_allowed_ptr(current, cpumask_of(pol->cpu)); + + if (smp_processor_id() != pol->cpu) { + printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); + goto err_out; + } + if (pending_bit_stuck()) { printk(KERN_ERR PFX "failing targ, change pending bit set\n"); - return -EIO; + goto err_out; } pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", pol->cpu, targfreq, pol->min, pol->max, relation); if (query_current_values_with_pending_wait(data)) - return -EIO; + goto err_out; if (cpu_family != CPU_HW_PSTATE) { pr_debug("targ: curr fid 0x%x, vid 0x%x\n", @@ -1189,7 +1196,7 @@ static long powernowk8_target_fn(void *arg) if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) - return -EIO; + goto err_out; mutex_lock(&fidvid_mutex); @@ -1202,8 +1209,9 @@ static long powernowk8_target_fn(void *arg) ret = transition_frequency_fidvid(data, newstate); if (ret) { printk(KERN_ERR PFX "transition frequency failed\n"); + ret = 1; mutex_unlock(&fidvid_mutex); - return 1; + goto err_out; } mutex_unlock(&fidvid_mutex); @@ -1212,25 +1220,12 @@ static long powernowk8_target_fn(void *arg) data->powernow_table[newstate].index); else pol->cur = find_khz_freq_from_fid(data->currfid); + ret = 0; - return 0; -} - -/* Driver entry point to switch to the target frequency */ -static int powernowk8_target(struct cpufreq_policy *pol, - unsigned targfreq, unsigned relation) -{ - struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, - .relation = relation }; - - /* - * Must run on @pol->cpu. cpufreq core is responsible for ensuring - * that we're bound to the current CPU and pol->cpu stays online. - */ - if (smp_processor_id() == pol->cpu) - return powernowk8_target_fn(&pta); - else - return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); +err_out: + set_cpus_allowed_ptr(current, oldmask); + free_cpumask_var(oldmask); + return ret; } /* Driver entry point to verify the policy and range of frequencies */ diff --git a/trunk/drivers/dma/at_hdmac.c b/trunk/drivers/dma/at_hdmac.c index 7ab6e26664a7..3934fcc4e00b 100644 --- a/trunk/drivers/dma/at_hdmac.c +++ b/trunk/drivers/dma/at_hdmac.c @@ -661,7 +661,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, flags); if (unlikely(!atslave || !sg_len)) { - dev_dbg(chan2dev(chan), "prep_slave_sg: sg length is zero!\n"); + dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n"); return NULL; } @@ -689,11 +689,6 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); - if (unlikely(!len)) { - dev_dbg(chan2dev(chan), - "prep_slave_sg: sg(%d) data length is zero\n", i); - goto err; - } mem_width = 2; if (unlikely(mem & 3 || len & 3)) mem_width = 0; @@ -729,11 +724,6 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); - if (unlikely(!len)) { - dev_dbg(chan2dev(chan), - "prep_slave_sg: sg(%d) data length is zero\n", i); - goto err; - } mem_width = 2; if (unlikely(mem & 3 || len & 3)) mem_width = 0; @@ -767,7 +757,6 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, err_desc_get: dev_err(chan2dev(chan), "not enough descriptors available\n"); -err: atc_desc_put(atchan, first); return NULL; } diff --git a/trunk/drivers/dma/pl330.c b/trunk/drivers/dma/pl330.c index f5843bc80baa..e4feba6b03c0 100644 --- a/trunk/drivers/dma/pl330.c +++ b/trunk/drivers/dma/pl330.c @@ -1567,19 +1567,17 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r) goto xfer_exit; } + /* Prefer Secure Channel */ + if (!_manager_ns(thrd)) + r->cfg->nonsecure = 0; + else + r->cfg->nonsecure = 1; /* Use last settings, if not provided */ - if (r->cfg) { - /* Prefer Secure Channel */ - if (!_manager_ns(thrd)) - r->cfg->nonsecure = 0; - else - r->cfg->nonsecure = 1; - + if (r->cfg) ccr = _prepare_ccr(r->cfg); - } else { + else ccr = readl(regs + CC(thrd->id)); - } /* If this req doesn't have valid xfer settings */ if (!_is_valid(ccr)) { @@ -2930,11 +2928,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan); pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); - if (!pdmac->peripherals) { - ret = -ENOMEM; - dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n"); - goto probe_err5; - } for (i = 0; i < num_chan; i++) { pch = &pdmac->peripherals[i]; diff --git a/trunk/drivers/edac/edac_mc.c b/trunk/drivers/edac/edac_mc.c index d5dc9da7f99f..616d90bcb3a4 100644 --- a/trunk/drivers/edac/edac_mc.c +++ b/trunk/drivers/edac/edac_mc.c @@ -199,36 +199,6 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems) return (void *)(((unsigned long)ptr) + align - r); } -static void _edac_mc_free(struct mem_ctl_info *mci) -{ - int i, chn, row; - struct csrow_info *csr; - const unsigned int tot_dimms = mci->tot_dimms; - const unsigned int tot_channels = mci->num_cschannel; - const unsigned int tot_csrows = mci->nr_csrows; - - if (mci->dimms) { - for (i = 0; i < tot_dimms; i++) - kfree(mci->dimms[i]); - kfree(mci->dimms); - } - if (mci->csrows) { - for (row = 0; row < tot_csrows; row++) { - csr = mci->csrows[row]; - if (csr) { - if (csr->channels) { - for (chn = 0; chn < tot_channels; chn++) - kfree(csr->channels[chn]); - kfree(csr->channels); - } - kfree(csr); - } - } - kfree(mci->csrows); - } - kfree(mci); -} - /** * edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure * @mc_num: Memory controller number @@ -443,7 +413,24 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, return mci; error: - _edac_mc_free(mci); + if (mci->dimms) { + for (i = 0; i < tot_dimms; i++) + kfree(mci->dimms[i]); + kfree(mci->dimms); + } + if (mci->csrows) { + for (chn = 0; chn < tot_channels; chn++) { + csr = mci->csrows[chn]; + if (csr) { + for (chn = 0; chn < tot_channels; chn++) + kfree(csr->channels[chn]); + kfree(csr); + } + kfree(mci->csrows[i]); + } + kfree(mci->csrows); + } + kfree(mci); return NULL; } @@ -458,14 +445,6 @@ void edac_mc_free(struct mem_ctl_info *mci) { edac_dbg(1, "\n"); - /* If we're not yet registered with sysfs free only what was allocated - * in edac_mc_alloc(). - */ - if (!device_is_registered(&mci->dev)) { - _edac_mc_free(mci); - return; - } - /* the mci instance is freed here, when the sysfs object is dropped */ edac_unregister_sysfs(mci); } diff --git a/trunk/drivers/edac/i3200_edac.c b/trunk/drivers/edac/i3200_edac.c index b6653a6fc5d5..47180a08edad 100644 --- a/trunk/drivers/edac/i3200_edac.c +++ b/trunk/drivers/edac/i3200_edac.c @@ -391,7 +391,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) for (j = 0; j < nr_channels; j++) { struct dimm_info *dimm = csrow->channels[j]->dimm; - dimm->nr_pages = nr_pages; + dimm->nr_pages = nr_pages / nr_channels; dimm->grain = nr_pages << PAGE_SHIFT; dimm->mtype = MEM_DDR2; dimm->dtype = DEV_UNKNOWN; diff --git a/trunk/drivers/edac/i5000_edac.c b/trunk/drivers/edac/i5000_edac.c index 6a49dd00b81b..39c63757c2a1 100644 --- a/trunk/drivers/edac/i5000_edac.c +++ b/trunk/drivers/edac/i5000_edac.c @@ -1012,10 +1012,6 @@ static void handle_channel(struct i5000_pvt *pvt, int slot, int channel, /* add the number of COLUMN bits */ addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); - /* Dual-rank memories have twice the size */ - if (dinfo->dual_rank) - addrBits++; - addrBits += 6; /* add 64 bits per DIMM */ addrBits -= 20; /* divide by 2^^20 */ addrBits -= 3; /* 8 bits per bytes */ diff --git a/trunk/drivers/edac/sb_edac.c b/trunk/drivers/edac/sb_edac.c index 5715b7c2c517..f3b1f9fafa4b 100644 --- a/trunk/drivers/edac/sb_edac.c +++ b/trunk/drivers/edac/sb_edac.c @@ -513,8 +513,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) { struct sbridge_pvt *pvt = mci->pvt_info; struct dimm_info *dimm; - unsigned i, j, banks, ranks, rows, cols, npages; - u64 size; + int i, j, banks, ranks, rows, cols, size, npages; u32 reg; enum edac_type mode; enum mem_type mtype; @@ -586,10 +585,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) cols = numcol(mtr); /* DDR3 has 8 I/O banks */ - size = ((u64)rows * cols * banks * ranks) >> (20 - 3); + size = (rows * cols * banks * ranks) >> (20 - 3); npages = MiB_TO_PAGES(size); - edac_dbg(0, "mc#%d: channel %d, dimm %d, %Ld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", + edac_dbg(0, "mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", pvt->sbridge_dev->mc, i, j, size, npages, banks, ranks, rows, cols); diff --git a/trunk/drivers/extcon/extcon-max77693.c b/trunk/drivers/extcon/extcon-max77693.c index 38f9e52f358b..920a609b2c35 100644 --- a/trunk/drivers/extcon/extcon-max77693.c +++ b/trunk/drivers/extcon/extcon-max77693.c @@ -669,18 +669,13 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) } info->dev = &pdev->dev; info->max77693 = max77693; - if (info->max77693->regmap_muic) - dev_dbg(&pdev->dev, "allocate register map\n"); - else { - info->max77693->regmap_muic = devm_regmap_init_i2c( - info->max77693->muic, - &max77693_muic_regmap_config); - if (IS_ERR(info->max77693->regmap_muic)) { - ret = PTR_ERR(info->max77693->regmap_muic); - dev_err(max77693->dev, - "failed to allocate register map: %d\n", ret); - goto err_regmap; - } + info->max77693->regmap_muic = regmap_init_i2c(info->max77693->muic, + &max77693_muic_regmap_config); + if (IS_ERR(info->max77693->regmap_muic)) { + ret = PTR_ERR(info->max77693->regmap_muic); + dev_err(max77693->dev, + "failed to allocate register map: %d\n", ret); + goto err_regmap; } platform_set_drvdata(pdev, info); mutex_init(&info->mutex); diff --git a/trunk/drivers/gpio/gpio-lpc32xx.c b/trunk/drivers/gpio/gpio-lpc32xx.c index ed94b4ea72e9..8a420f13905e 100644 --- a/trunk/drivers/gpio/gpio-lpc32xx.c +++ b/trunk/drivers/gpio/gpio-lpc32xx.c @@ -308,7 +308,6 @@ static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin, { struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - __set_gpio_level_p012(group, pin, value); __set_gpio_dir_p012(group, pin, 0); return 0; @@ -319,7 +318,6 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, { struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - __set_gpio_level_p3(group, pin, value); __set_gpio_dir_p3(group, pin, 0); return 0; @@ -328,9 +326,6 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin, int value) { - struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); - - __set_gpo_level_p3(group, pin, value); return 0; } diff --git a/trunk/drivers/gpu/drm/i915/i915_gem.c b/trunk/drivers/gpu/drm/i915/i915_gem.c index 274d25de521e..489e2b162b27 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem.c @@ -3242,8 +3242,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, { int ret; - if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) - return -EBUSY; + BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); if (obj->gtt_space != NULL) { if ((alignment && obj->gtt_offset & (alignment - 1)) || diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index c040aee1341c..bc2ad348e5d8 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -4191,6 +4191,12 @@ static void i8xx_update_pll(struct drm_crtc *crtc, POSTING_READ(DPLL(pipe)); udelay(150); + I915_WRITE(DPLL(pipe), dpll); + + /* Wait for the clocks to stabilize. */ + POSTING_READ(DPLL(pipe)); + udelay(150); + /* The LVDS pin pair needs to be on before the DPLLs are enabled. * This is an exception to the general rule that mode_set doesn't turn * things on. @@ -4198,12 +4204,6 @@ static void i8xx_update_pll(struct drm_crtc *crtc, if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) intel_update_lvds(crtc, clock, adjusted_mode); - I915_WRITE(DPLL(pipe), dpll); - - /* Wait for the clocks to stabilize. */ - POSTING_READ(DPLL(pipe)); - udelay(150); - /* The pixel multiplier can only be updated once the * DPLL is enabled and the clocks are stable. * diff --git a/trunk/drivers/gpu/drm/i915/intel_hdmi.c b/trunk/drivers/gpu/drm/i915/intel_hdmi.c index 12dc3308ab8c..98f602427eb8 100644 --- a/trunk/drivers/gpu/drm/i915/intel_hdmi.c +++ b/trunk/drivers/gpu/drm/i915/intel_hdmi.c @@ -609,7 +609,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) u32 temp; u32 enable_bits = SDVO_ENABLE; - if (intel_hdmi->has_audio || mode != DRM_MODE_DPMS_ON) + if (intel_hdmi->has_audio) enable_bits |= SDVO_AUDIO_ENABLE; temp = I915_READ(intel_hdmi->sdvox_reg); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c b/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c index 3ca240b4413d..ff23d88880e5 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -179,7 +179,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) return 0; } else if (init->class == 0x906e) { - NV_DEBUG(dev, "906e not supported yet\n"); + NV_ERROR(dev, "906e not supported yet\n"); return -EINVAL; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c b/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c index c399d510b27a..f03490534893 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_hw.h" @@ -111,25 +110,13 @@ nv50_gpio_isr(struct drm_device *dev) nv_wr32(dev, 0xe074, intr1); } -static struct dmi_system_id gpio_reset_ids[] = { - { - .ident = "Apple Macbook 10,1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), - } - }, - { } -}; - int nv50_gpio_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; /* initialise gpios and routing to vbios defaults */ - if (dmi_check_system(gpio_reset_ids)) - nouveau_gpio_reset(dev); + nouveau_gpio_reset(dev); /* disable, and ack any pending gpio interrupts */ nv_wr32(dev, 0xe050, 0x00000000); diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_fb.c b/trunk/drivers/gpu/drm/nouveau/nvc0_fb.c index f376c39310df..f704e942372e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_fb.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_fb.c @@ -124,7 +124,6 @@ nvc0_fb_init(struct drm_device *dev) priv = dev_priv->engine.fb.priv; nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); - nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */ return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_fifo.c b/trunk/drivers/gpu/drm/nouveau/nvc0_fifo.c index cd39eb99f5b1..7d85553d518c 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_fifo.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_fifo.c @@ -373,8 +373,7 @@ nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) static void nvc0_fifo_isr(struct drm_device *dev) { - u32 mask = nv_rd32(dev, 0x002140); - u32 stat = nv_rd32(dev, 0x002100) & mask; + u32 stat = nv_rd32(dev, 0x002100); if (stat & 0x00000100) { NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); diff --git a/trunk/drivers/gpu/drm/nouveau/nve0_fifo.c b/trunk/drivers/gpu/drm/nouveau/nve0_fifo.c index 281bece751b6..e98d144e6eb9 100644 --- a/trunk/drivers/gpu/drm/nouveau/nve0_fifo.c +++ b/trunk/drivers/gpu/drm/nouveau/nve0_fifo.c @@ -345,8 +345,7 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) static void nve0_fifo_isr(struct drm_device *dev) { - u32 mask = nv_rd32(dev, 0x002140); - u32 stat = nv_rd32(dev, 0x002100) & mask; + u32 stat = nv_rd32(dev, 0x002100); if (stat & 0x00000100) { NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); diff --git a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c index 2817101fb167..e721e3087b99 100644 --- a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1479,14 +1479,98 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc) } } +/** + * radeon_get_pll_use_mask - look up a mask of which pplls are in use + * + * @crtc: drm crtc + * + * Returns the mask of which PPLLs (Pixel PLLs) are in use. + */ +static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc *test_crtc; + struct radeon_crtc *radeon_test_crtc; + u32 pll_in_use = 0; + + list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { + if (crtc == test_crtc) + continue; + + radeon_test_crtc = to_radeon_crtc(test_crtc); + if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) + pll_in_use |= (1 << radeon_test_crtc->pll_id); + } + return pll_in_use; +} + +/** + * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is + * also in DP mode. For DP, a single PPLL can be used for all DP + * crtcs/encoders. + */ +static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_encoder *test_encoder; + struct radeon_crtc *radeon_test_crtc; + + list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { + if (test_encoder->crtc && (test_encoder->crtc != crtc)) { + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { + /* for DP use the same PLL for all */ + radeon_test_crtc = to_radeon_crtc(test_encoder->crtc); + if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) + return radeon_test_crtc->pll_id; + } + } + } + return ATOM_PPLL_INVALID; +} + +/** + * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc. + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) to be used by the crtc. For DP monitors + * a single PPLL can be used for all DP crtcs/encoders. For non-DP + * monitors a dedicated PPLL must be used. If a particular board has + * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming + * as there is no need to program the PLL itself. If we are not able to + * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to + * avoid messing up an existing monitor. + * + * Asic specific PLL information + * + * DCE 6.1 + * - PPLL2 is only available to UNIPHYA (both DP and non-DP) + * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP) + * + * DCE 6.0 + * - PPLL0 is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 5.0 + * - DCPLL is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 3.0/4.0/4.1 + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + */ static int radeon_atom_pick_pll(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct drm_encoder *test_encoder; - struct drm_crtc *test_crtc; - uint32_t pll_in_use = 0; + u32 pll_in_use; + int pll; if (ASIC_IS_DCE61(rdev)) { list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { @@ -1498,32 +1582,40 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) if ((test_radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && - (dig->linkb == false)) /* UNIPHY A uses PPLL2 */ + (dig->linkb == false)) + /* UNIPHY A uses PPLL2 */ return ATOM_PPLL2; + else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { + /* UNIPHY B/C/D/E/F */ + if (rdev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ + return ATOM_PPLL_INVALID; + else { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + } + break; } } /* UNIPHY B/C/D/E/F */ - list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_test_crtc; - - if (crtc == test_crtc) - continue; - - radeon_test_crtc = to_radeon_crtc(test_crtc); - if ((radeon_test_crtc->pll_id == ATOM_PPLL0) || - (radeon_test_crtc->pll_id == ATOM_PPLL1)) - pll_in_use |= (1 << radeon_test_crtc->pll_id); - } - if (!(pll_in_use & 4)) + pll_in_use = radeon_get_pll_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL0))) return ATOM_PPLL0; - return ATOM_PPLL1; + if (!(pll_in_use & (1 << ATOM_PPLL1))) + return ATOM_PPLL1; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; } else if (ASIC_IS_DCE4(rdev)) { list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { if (test_encoder->crtc && (test_encoder->crtc == crtc)) { /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, * depending on the asic: * DCE4: PPLL or ext clock - * DCE5: DCPLL or ext clock + * DCE5: PPLL, DCPLL, or ext clock + * DCE6: PPLL, PPLL0, or ext clock * * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip * PPLL/DCPLL programming and only program the DP DTO for the @@ -1531,31 +1623,34 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) */ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { if (rdev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ return ATOM_PPLL_INVALID; else if (ASIC_IS_DCE6(rdev)) + /* use PPLL0 for all DP */ return ATOM_PPLL0; else if (ASIC_IS_DCE5(rdev)) + /* use DCPLL for all DP */ return ATOM_DCPLL; + else { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } } + break; } } - - /* otherwise, pick one of the plls */ - list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_test_crtc; - - if (crtc == test_crtc) - continue; - - radeon_test_crtc = to_radeon_crtc(test_crtc); - if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) && - (radeon_test_crtc->pll_id <= ATOM_PPLL2)) - pll_in_use |= (1 << radeon_test_crtc->pll_id); - } - if (!(pll_in_use & 1)) + /* all other cases */ + pll_in_use = radeon_get_pll_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; + if (!(pll_in_use & (1 << ATOM_PPLL1))) return ATOM_PPLL1; - return ATOM_PPLL2; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; } else + /* use PPLL1 or PPLL2 */ return radeon_crtc->crtc_id; } @@ -1697,7 +1792,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) break; } done: - radeon_crtc->pll_id = -1; + radeon_crtc->pll_id = ATOM_PPLL_INVALID; } static const struct drm_crtc_helper_funcs atombios_helper_funcs = { @@ -1746,6 +1841,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev, else radeon_crtc->crtc_offset = 0; } - radeon_crtc->pll_id = -1; + radeon_crtc->pll_id = ATOM_PPLL_INVALID; drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); } diff --git a/trunk/drivers/gpu/drm/radeon/r100.c b/trunk/drivers/gpu/drm/radeon/r100.c index 8d7e33a0b243..8acb34fd3fd5 100644 --- a/trunk/drivers/gpu/drm/radeon/r100.c +++ b/trunk/drivers/gpu/drm/radeon/r100.c @@ -1182,8 +1182,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) ring->ready = true; radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); - if (!ring->rptr_save_reg /* not resuming from suspend */ - && radeon_ring_supports_scratch_reg(rdev, ring)) { + if (radeon_ring_supports_scratch_reg(rdev, ring)) { r = radeon_scratch_get(rdev, &ring->rptr_save_reg); if (r) { DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); diff --git a/trunk/drivers/gpu/drm/udl/udl_connector.c b/trunk/drivers/gpu/drm/udl/udl_connector.c index 8d9dc44f1f94..ba055e9ca007 100644 --- a/trunk/drivers/gpu/drm/udl/udl_connector.c +++ b/trunk/drivers/gpu/drm/udl/udl_connector.c @@ -69,13 +69,6 @@ static int udl_get_modes(struct drm_connector *connector) static int udl_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct udl_device *udl = connector->dev->dev_private; - if (!udl->sku_pixel_limit) - return 0; - - if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit) - return MODE_VIRTUAL_Y; - return 0; } diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 7e0743358dff..f2fb8f15e2f1 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -1018,7 +1018,7 @@ int vmw_event_fence_action_create(struct drm_file *file_priv, } - event = kzalloc(sizeof(*event), GFP_KERNEL); + event = kzalloc(sizeof(event->event), GFP_KERNEL); if (unlikely(event == NULL)) { DRM_ERROR("Failed to allocate an event.\n"); ret = -ENOMEM; diff --git a/trunk/drivers/hid/hid-lenovo-tpkbd.c b/trunk/drivers/hid/hid-lenovo-tpkbd.c index 60c4e1e85913..77d2df04c97b 100644 --- a/trunk/drivers/hid/hid-lenovo-tpkbd.c +++ b/trunk/drivers/hid/hid-lenovo-tpkbd.c @@ -519,8 +519,6 @@ static void tpkbd_remove_tp(struct hid_device *hdev) led_classdev_unregister(&data_pointer->led_mute); hid_set_drvdata(hdev, NULL); - kfree(data_pointer->led_micmute.name); - kfree(data_pointer->led_mute.name); kfree(data_pointer); } diff --git a/trunk/drivers/hid/hid-logitech-dj.c b/trunk/drivers/hid/hid-logitech-dj.c index 9500f2f3f8fe..4d524b5f52f5 100644 --- a/trunk/drivers/hid/hid-logitech-dj.c +++ b/trunk/drivers/hid/hid-logitech-dj.c @@ -193,7 +193,6 @@ static struct hid_ll_driver logi_dj_ll_driver; static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, size_t count, unsigned char report_type); -static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) @@ -234,7 +233,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & SPFUNCTION_DEVICE_LIST_EMPTY) { dbg_hid("%s: device list is empty\n", __func__); - djrcv_dev->querying_devices = false; return; } @@ -245,12 +243,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, return; } - if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { - /* The device is already known. No need to reallocate it. */ - dbg_hid("%s: device is already known\n", __func__); - return; - } - dj_hiddev = hid_allocate_device(); if (IS_ERR(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", @@ -314,7 +306,6 @@ static void delayedwork_callback(struct work_struct *work) struct dj_report dj_report; unsigned long flags; int count; - int retval; dbg_hid("%s\n", __func__); @@ -347,25 +338,6 @@ static void delayedwork_callback(struct work_struct *work) logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); break; default: - /* A normal report (i. e. not belonging to a pair/unpair notification) - * arriving here, means that the report arrived but we did not have a - * paired dj_device associated to the report's device_index, this - * means that the original "device paired" notification corresponding - * to this dj_device never arrived to this driver. The reason is that - * hid-core discards all packets coming from a device while probe() is - * executing. */ - if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { - /* ok, we don't know the device, just re-ask the - * receiver for the list of connected devices. */ - retval = logi_dj_recv_query_paired_devices(djrcv_dev); - if (!retval) { - /* everything went fine, so just leave */ - break; - } - dev_err(&djrcv_dev->hdev->dev, - "%s:logi_dj_recv_query_paired_devices " - "error:%d\n", __func__, retval); - } dbg_hid("%s: unexpected report type\n", __func__); } } @@ -396,12 +368,6 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, if (!djdev) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); - kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); - - if (schedule_work(&djrcv_dev->work) == 0) { - dbg_hid("%s: did not schedule the work item, was already " - "queued\n", __func__); - } return; } @@ -432,12 +398,6 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, if (dj_device == NULL) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); - kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); - - if (schedule_work(&djrcv_dev->work) == 0) { - dbg_hid("%s: did not schedule the work item, was already " - "queued\n", __func__); - } return; } @@ -479,10 +439,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) struct dj_report *dj_report; int retval; - /* no need to protect djrcv_dev->querying_devices */ - if (djrcv_dev->querying_devices) - return 0; - dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; @@ -494,7 +450,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) return retval; } - static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, unsigned timeout) { diff --git a/trunk/drivers/hid/hid-logitech-dj.h b/trunk/drivers/hid/hid-logitech-dj.h index 4a4000340ce1..fd28a5e0ca3b 100644 --- a/trunk/drivers/hid/hid-logitech-dj.h +++ b/trunk/drivers/hid/hid-logitech-dj.h @@ -101,7 +101,6 @@ struct dj_receiver_dev { struct work_struct work; struct kfifo notif_fifo; spinlock_t lock; - bool querying_devices; }; struct dj_device { diff --git a/trunk/drivers/hwmon/ad7314.c b/trunk/drivers/hwmon/ad7314.c index f915eb1c29f7..cfec802cf9ca 100644 --- a/trunk/drivers/hwmon/ad7314.c +++ b/trunk/drivers/hwmon/ad7314.c @@ -87,18 +87,10 @@ static ssize_t ad7314_show_temperature(struct device *dev, } } -static ssize_t ad7314_show_name(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); -} - -static DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ad7314_show_temperature, NULL, 0); static struct attribute *ad7314_attributes[] = { - &dev_attr_name.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, NULL, }; diff --git a/trunk/drivers/hwmon/ads7871.c b/trunk/drivers/hwmon/ads7871.c index 7bf4ce3d405e..e65c6e45d36b 100644 --- a/trunk/drivers/hwmon/ads7871.c +++ b/trunk/drivers/hwmon/ads7871.c @@ -139,12 +139,6 @@ static ssize_t show_voltage(struct device *dev, } } -static ssize_t ads7871_show_name(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); -} - static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0); static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1); static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2); @@ -154,8 +148,6 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5); static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6); static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7); -static DEVICE_ATTR(name, S_IRUGO, ads7871_show_name, NULL); - static struct attribute *ads7871_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -165,7 +157,6 @@ static struct attribute *ads7871_attributes[] = { &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in7_input.dev_attr.attr, - &dev_attr_name.attr, NULL }; diff --git a/trunk/drivers/hwmon/applesmc.c b/trunk/drivers/hwmon/applesmc.c index 8f3f6f2c45fd..282708860517 100644 --- a/trunk/drivers/hwmon/applesmc.c +++ b/trunk/drivers/hwmon/applesmc.c @@ -53,10 +53,10 @@ #define APPLESMC_MAX_DATA_LENGTH 32 -/* wait up to 128 ms for a status change. */ +/* wait up to 32 ms for a status change. */ #define APPLESMC_MIN_WAIT 0x0010 #define APPLESMC_RETRY_WAIT 0x0100 -#define APPLESMC_MAX_WAIT 0x20000 +#define APPLESMC_MAX_WAIT 0x8000 #define APPLESMC_READ_CMD 0x10 #define APPLESMC_WRITE_CMD 0x11 diff --git a/trunk/drivers/hwmon/coretemp.c b/trunk/drivers/hwmon/coretemp.c index 984a3f13923b..0fa356fe82cc 100644 --- a/trunk/drivers/hwmon/coretemp.c +++ b/trunk/drivers/hwmon/coretemp.c @@ -815,20 +815,17 @@ static int __init coretemp_init(void) if (err) goto exit; - get_online_cpus(); for_each_online_cpu(i) get_core_online(i); #ifndef CONFIG_HOTPLUG_CPU if (list_empty(&pdev_list)) { - put_online_cpus(); err = -ENODEV; goto exit_driver_unreg; } #endif register_hotcpu_notifier(&coretemp_cpu_notifier); - put_online_cpus(); return 0; #ifndef CONFIG_HOTPLUG_CPU @@ -843,7 +840,6 @@ static void __exit coretemp_exit(void) { struct pdev_entry *p, *n; - get_online_cpus(); unregister_hotcpu_notifier(&coretemp_cpu_notifier); mutex_lock(&pdev_list_mutex); list_for_each_entry_safe(p, n, &pdev_list, list) { @@ -852,7 +848,6 @@ static void __exit coretemp_exit(void) kfree(p); } mutex_unlock(&pdev_list_mutex); - put_online_cpus(); platform_driver_unregister(&coretemp_driver); } diff --git a/trunk/drivers/hwmon/fam15h_power.c b/trunk/drivers/hwmon/fam15h_power.c index af69073b3fe8..2764b78a784b 100644 --- a/trunk/drivers/hwmon/fam15h_power.c +++ b/trunk/drivers/hwmon/fam15h_power.c @@ -129,12 +129,12 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4) * counter saturations resulting in bogus power readings. * We correct this value ourselves to cope with older BIOSes. */ -static const struct pci_device_id affected_device[] = { +static DEFINE_PCI_DEVICE_TABLE(affected_device) = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, { 0 } }; -static void tweak_runavg_range(struct pci_dev *pdev) +static void __devinit tweak_runavg_range(struct pci_dev *pdev) { u32 val; @@ -158,16 +158,6 @@ static void tweak_runavg_range(struct pci_dev *pdev) REG_TDP_RUNNING_AVERAGE, val); } -#ifdef CONFIG_PM -static int fam15h_power_resume(struct pci_dev *pdev) -{ - tweak_runavg_range(pdev); - return 0; -} -#else -#define fam15h_power_resume NULL -#endif - static void __devinit fam15h_power_init_data(struct pci_dev *f4, struct fam15h_power_data *data) { @@ -266,7 +256,6 @@ static struct pci_driver fam15h_power_driver = { .id_table = fam15h_power_id_table, .probe = fam15h_power_probe, .remove = __devexit_p(fam15h_power_remove), - .resume = fam15h_power_resume, }; module_pci_driver(fam15h_power_driver); diff --git a/trunk/drivers/hwmon/via-cputemp.c b/trunk/drivers/hwmon/via-cputemp.c index 2e56c6ce9fb6..ee4ebc198a94 100644 --- a/trunk/drivers/hwmon/via-cputemp.c +++ b/trunk/drivers/hwmon/via-cputemp.c @@ -328,7 +328,6 @@ static int __init via_cputemp_init(void) if (err) goto exit; - get_online_cpus(); for_each_online_cpu(i) { struct cpuinfo_x86 *c = &cpu_data(i); @@ -348,14 +347,12 @@ static int __init via_cputemp_init(void) #ifndef CONFIG_HOTPLUG_CPU if (list_empty(&pdev_list)) { - put_online_cpus(); err = -ENODEV; goto exit_driver_unreg; } #endif register_hotcpu_notifier(&via_cputemp_cpu_notifier); - put_online_cpus(); return 0; #ifndef CONFIG_HOTPLUG_CPU @@ -370,7 +367,6 @@ static void __exit via_cputemp_exit(void) { struct pdev_entry *p, *n; - get_online_cpus(); unregister_hotcpu_notifier(&via_cputemp_cpu_notifier); mutex_lock(&pdev_list_mutex); list_for_each_entry_safe(p, n, &pdev_list, list) { @@ -379,7 +375,6 @@ static void __exit via_cputemp_exit(void) kfree(p); } mutex_unlock(&pdev_list_mutex); - put_online_cpus(); platform_driver_unregister(&via_cputemp_driver); } diff --git a/trunk/drivers/hwspinlock/hwspinlock_core.c b/trunk/drivers/hwspinlock/hwspinlock_core.c index db713c0dfba4..1201a15784c3 100644 --- a/trunk/drivers/hwspinlock/hwspinlock_core.c +++ b/trunk/drivers/hwspinlock/hwspinlock_core.c @@ -552,7 +552,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request_specific); */ int hwspin_lock_free(struct hwspinlock *hwlock) { - struct device *dev; + struct device *dev = hwlock->bank->dev; struct hwspinlock *tmp; int ret; @@ -561,7 +561,6 @@ int hwspin_lock_free(struct hwspinlock *hwlock) return -EINVAL; } - dev = hwlock->bank->dev; mutex_lock(&hwspinlock_tree_lock); /* make sure the hwspinlock is used */ diff --git a/trunk/drivers/infiniband/hw/cxgb4/cm.c b/trunk/drivers/infiniband/hw/cxgb4/cm.c index 6cfd4d8fd0bd..51f42061dae9 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/cm.c +++ b/trunk/drivers/infiniband/hw/cxgb4/cm.c @@ -1361,11 +1361,11 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb) struct tid_info *t = dev->rdev.lldi.tids; ep = lookup_tid(t, tid); + PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); if (!ep) { printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n"); return 0; } - PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); mutex_lock(&ep->com.mutex); switch (ep->com.state) { case ABORTING: diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index b29a4246ef41..cb5b7f7d4d38 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -2219,6 +2219,7 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp, u32 wqe_idx; if (!qp->wqe_wr_id_tbl[tail].signaled) { + expand = true; /* CQE cannot be consumed yet */ *polled = false; /* WC cannot be consumed yet */ } else { ibwc->status = IB_WC_SUCCESS; @@ -2226,11 +2227,10 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp, ibwc->qp = &qp->ibqp; ocrdma_update_wc(qp, ibwc, tail); *polled = true; + wqe_idx = le32_to_cpu(cqe->wq.wqeidx) & OCRDMA_CQE_WQEIDX_MASK; + if (tail != wqe_idx) + expand = true; /* Coalesced CQE can't be consumed yet */ } - wqe_idx = le32_to_cpu(cqe->wq.wqeidx) & OCRDMA_CQE_WQEIDX_MASK; - if (tail != wqe_idx) - expand = true; /* Coalesced CQE can't be consumed yet */ - ocrdma_hwq_inc_tail(&qp->sq); return expand; } diff --git a/trunk/drivers/infiniband/hw/qib/qib_mad.c b/trunk/drivers/infiniband/hw/qib/qib_mad.c index ccb119143d20..19f1e6c45fb6 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_mad.c +++ b/trunk/drivers/infiniband/hw/qib/qib_mad.c @@ -471,10 +471,9 @@ static int subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev, if (port_num != port) { ibp = to_iport(ibdev, port_num); ret = check_mkey(ibp, smp, 0); - if (ret) { + if (ret) ret = IB_MAD_RESULT_FAILURE; goto bail; - } } } diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h index 196eb52f0035..381f51b2ed61 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h @@ -266,10 +266,7 @@ struct ipoib_ethtool_st { u16 max_coalesced_frames; }; -struct ipoib_neigh_table; - struct ipoib_neigh_hash { - struct ipoib_neigh_table *ntbl; struct ipoib_neigh __rcu **buckets; struct rcu_head rcu; u32 mask; @@ -278,9 +275,9 @@ struct ipoib_neigh_hash { struct ipoib_neigh_table { struct ipoib_neigh_hash __rcu *htbl; + rwlock_t rwlock; atomic_t entries; struct completion flushed; - struct completion deleted; }; /* @@ -523,9 +520,6 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, int __init ipoib_netlink_init(void); void __exit ipoib_netlink_fini(void); -void ipoib_set_umcast(struct net_device *ndev, int umcast_val); -int ipoib_set_mode(struct net_device *dev, const char *buf); - void ipoib_setup(struct net_device *dev); void ipoib_pkey_poll(struct work_struct *work); diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 175581cf478c..24683fda8e21 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1448,10 +1448,15 @@ static ssize_t show_mode(struct device *d, struct device_attribute *attr, return sprintf(buf, "datagram\n"); } -int ipoib_set_mode(struct net_device *dev, const char *buf) +static ssize_t set_mode(struct device *d, struct device_attribute *attr, + const char *buf, size_t count) { + struct net_device *dev = to_net_dev(d); struct ipoib_dev_priv *priv = netdev_priv(dev); + if (!rtnl_trylock()) + return restart_syscall(); + /* flush paths if we switch modes so that connections are restarted */ if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); @@ -1462,8 +1467,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf) priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; ipoib_flush_paths(dev); - rtnl_lock(); - return 0; + return count; } if (!strcmp(buf, "datagram\n")) { @@ -1472,30 +1476,12 @@ int ipoib_set_mode(struct net_device *dev, const char *buf) dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); rtnl_unlock(); ipoib_flush_paths(dev); - rtnl_lock(); - return 0; - } - return -EINVAL; -} - -static ssize_t set_mode(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct net_device *dev = to_net_dev(d); - int ret; - - if (!rtnl_trylock()) - return restart_syscall(); - - ret = ipoib_set_mode(dev, buf); - - rtnl_unlock(); - - if (!ret) return count; + } + rtnl_unlock(); - return ret; + return -EINVAL; } static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode); diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c index 3f9a9ba2f9ec..b3e97096c446 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -551,15 +551,15 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr, struct ipoib_neigh *neigh; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); neigh = ipoib_neigh_alloc(daddr, dev); if (!neigh) { - spin_unlock_irqrestore(&priv->lock, flags); ++dev->stats.tx_dropped; dev_kfree_skb_any(skb); return; } + spin_lock_irqsave(&priv->lock, flags); + path = __path_find(dev, daddr + 4); if (!path) { path = path_rec_create(dev, daddr + 4); @@ -868,10 +868,10 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) return; - spin_lock_irqsave(&priv->lock, flags); + write_lock_bh(&ntbl->rwlock); htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) goto out_unlock; @@ -888,14 +888,16 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) struct ipoib_neigh __rcu **np = &htbl->buckets[i]; while ((neigh = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock))) != NULL) { + lockdep_is_held(&ntbl->rwlock))) != NULL) { /* was the neigh idle for two GC periods */ if (time_after(neigh_obsolete, neigh->alive)) { rcu_assign_pointer(*np, rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); /* remove from path/mc list */ + spin_lock_irqsave(&priv->lock, flags); list_del(&neigh->list); + spin_unlock_irqrestore(&priv->lock, flags); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); } else { np = &neigh->hnext; @@ -905,7 +907,7 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) } out_unlock: - spin_unlock_irqrestore(&priv->lock, flags); + write_unlock_bh(&ntbl->rwlock); } static void ipoib_reap_neigh(struct work_struct *work) @@ -950,8 +952,10 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr, struct ipoib_neigh *neigh; u32 hash_val; + write_lock_bh(&ntbl->rwlock); + htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) { neigh = NULL; goto out_unlock; @@ -962,10 +966,10 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr, */ hash_val = ipoib_addr_hash(htbl, daddr); for (neigh = rcu_dereference_protected(htbl->buckets[hash_val], - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); neigh != NULL; neigh = rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))) { + lockdep_is_held(&ntbl->rwlock))) { if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) { /* found, take one ref on behalf of the caller */ if (!atomic_inc_not_zero(&neigh->refcnt)) { @@ -988,11 +992,12 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr, /* put in hash */ rcu_assign_pointer(neigh->hnext, rcu_dereference_protected(htbl->buckets[hash_val], - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); rcu_assign_pointer(htbl->buckets[hash_val], neigh); atomic_inc(&ntbl->entries); out_unlock: + write_unlock_bh(&ntbl->rwlock); return neigh; } @@ -1040,29 +1045,35 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh) struct ipoib_neigh *n; u32 hash_val; + write_lock_bh(&ntbl->rwlock); + htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) - return; + goto out_unlock; hash_val = ipoib_addr_hash(htbl, neigh->daddr); np = &htbl->buckets[hash_val]; for (n = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); n != NULL; n = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock))) { + lockdep_is_held(&ntbl->rwlock))) { if (n == neigh) { /* found */ rcu_assign_pointer(*np, rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); - return; + goto out_unlock; } else { np = &n->hnext; } } + +out_unlock: + write_unlock_bh(&ntbl->rwlock); + } static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) @@ -1074,6 +1085,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); ntbl->htbl = NULL; + rwlock_init(&ntbl->rwlock); htbl = kzalloc(sizeof(*htbl), GFP_KERNEL); if (!htbl) return -ENOMEM; @@ -1088,7 +1100,6 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) htbl->mask = (size - 1); htbl->buckets = buckets; ntbl->htbl = htbl; - htbl->ntbl = ntbl; atomic_set(&ntbl->entries, 0); /* start garbage collection */ @@ -1105,11 +1116,9 @@ static void neigh_hash_free_rcu(struct rcu_head *head) struct ipoib_neigh_hash, rcu); struct ipoib_neigh __rcu **buckets = htbl->buckets; - struct ipoib_neigh_table *ntbl = htbl->ntbl; kfree(buckets); kfree(htbl); - complete(&ntbl->deleted); } void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) @@ -1121,10 +1130,10 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) int i; /* remove all neigh connected to a given path or mcast */ - spin_lock_irqsave(&priv->lock, flags); + write_lock_bh(&ntbl->rwlock); htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) goto out_unlock; @@ -1134,14 +1143,16 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) struct ipoib_neigh __rcu **np = &htbl->buckets[i]; while ((neigh = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock))) != NULL) { + lockdep_is_held(&ntbl->rwlock))) != NULL) { /* delete neighs belong to this parent */ if (!memcmp(gid, neigh->daddr + 4, sizeof (union ib_gid))) { rcu_assign_pointer(*np, rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); /* remove from parent list */ + spin_lock_irqsave(&priv->lock, flags); list_del(&neigh->list); + spin_unlock_irqrestore(&priv->lock, flags); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); } else { np = &neigh->hnext; @@ -1150,7 +1161,7 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) } } out_unlock: - spin_unlock_irqrestore(&priv->lock, flags); + write_unlock_bh(&ntbl->rwlock); } static void ipoib_flush_neighs(struct ipoib_dev_priv *priv) @@ -1158,44 +1169,37 @@ static void ipoib_flush_neighs(struct ipoib_dev_priv *priv) struct ipoib_neigh_table *ntbl = &priv->ntbl; struct ipoib_neigh_hash *htbl; unsigned long flags; - int i, wait_flushed = 0; - - init_completion(&priv->ntbl.flushed); + int i; - spin_lock_irqsave(&priv->lock, flags); + write_lock_bh(&ntbl->rwlock); htbl = rcu_dereference_protected(ntbl->htbl, - lockdep_is_held(&priv->lock)); + lockdep_is_held(&ntbl->rwlock)); if (!htbl) goto out_unlock; - wait_flushed = atomic_read(&priv->ntbl.entries); - if (!wait_flushed) - goto free_htbl; - for (i = 0; i < htbl->size; i++) { struct ipoib_neigh *neigh; struct ipoib_neigh __rcu **np = &htbl->buckets[i]; while ((neigh = rcu_dereference_protected(*np, - lockdep_is_held(&priv->lock))) != NULL) { + lockdep_is_held(&ntbl->rwlock))) != NULL) { rcu_assign_pointer(*np, rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); + lockdep_is_held(&ntbl->rwlock))); /* remove from path/mc list */ + spin_lock_irqsave(&priv->lock, flags); list_del(&neigh->list); + spin_unlock_irqrestore(&priv->lock, flags); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); } } -free_htbl: rcu_assign_pointer(ntbl->htbl, NULL); call_rcu(&htbl->rcu, neigh_hash_free_rcu); out_unlock: - spin_unlock_irqrestore(&priv->lock, flags); - if (wait_flushed) - wait_for_completion(&priv->ntbl.flushed); + write_unlock_bh(&ntbl->rwlock); } static void ipoib_neigh_hash_uninit(struct net_device *dev) @@ -1204,7 +1208,7 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev) int stopped; ipoib_dbg(priv, "ipoib_neigh_hash_uninit\n"); - init_completion(&priv->ntbl.deleted); + init_completion(&priv->ntbl.flushed); set_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); /* Stop GC if called at init fail need to cancel work */ @@ -1212,9 +1216,10 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev) if (!stopped) cancel_delayed_work(&priv->neigh_reap_task); - ipoib_flush_neighs(priv); - - wait_for_completion(&priv->ntbl.deleted); + if (atomic_read(&priv->ntbl.entries)) { + ipoib_flush_neighs(priv); + wait_for_completion(&priv->ntbl.flushed); + } } @@ -1381,9 +1386,12 @@ static ssize_t show_umcast(struct device *dev, return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags)); } -void ipoib_set_umcast(struct net_device *ndev, int umcast_val) +static ssize_t set_umcast(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - struct ipoib_dev_priv *priv = netdev_priv(ndev); + struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); + unsigned long umcast_val = simple_strtoul(buf, NULL, 0); if (umcast_val > 0) { set_bit(IPOIB_FLAG_UMCAST, &priv->flags); @@ -1391,15 +1399,6 @@ void ipoib_set_umcast(struct net_device *ndev, int umcast_val) "by userspace\n"); } else clear_bit(IPOIB_FLAG_UMCAST, &priv->flags); -} - -static ssize_t set_umcast(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long umcast_val = simple_strtoul(buf, NULL, 0); - - ipoib_set_umcast(to_net_dev(dev), umcast_val); return count; } diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 75367249f447..13f4aa7593c8 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -707,7 +707,9 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb) neigh = ipoib_neigh_get(dev, daddr); spin_lock_irqsave(&priv->lock, flags); if (!neigh) { + spin_unlock_irqrestore(&priv->lock, flags); neigh = ipoib_neigh_alloc(daddr, dev); + spin_lock_irqsave(&priv->lock, flags); if (neigh) { kref_get(&mcast->ah->ref); neigh->ah = mcast->ah; diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_netlink.c index 74685936c948..a7dc5ea8370e 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_netlink.c @@ -37,60 +37,8 @@ static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = { [IFLA_IPOIB_PKEY] = { .type = NLA_U16 }, - [IFLA_IPOIB_MODE] = { .type = NLA_U16 }, - [IFLA_IPOIB_UMCAST] = { .type = NLA_U16 }, }; -static int ipoib_fill_info(struct sk_buff *skb, const struct net_device *dev) -{ - struct ipoib_dev_priv *priv = netdev_priv(dev); - u16 val; - - if (nla_put_u16(skb, IFLA_IPOIB_PKEY, priv->pkey)) - goto nla_put_failure; - - val = test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); - if (nla_put_u16(skb, IFLA_IPOIB_MODE, val)) - goto nla_put_failure; - - val = test_bit(IPOIB_FLAG_UMCAST, &priv->flags); - if (nla_put_u16(skb, IFLA_IPOIB_UMCAST, val)) - goto nla_put_failure; - - return 0; - -nla_put_failure: - return -EMSGSIZE; -} - -static int ipoib_changelink(struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[]) -{ - u16 mode, umcast; - int ret = 0; - - if (data[IFLA_IPOIB_MODE]) { - mode = nla_get_u16(data[IFLA_IPOIB_MODE]); - if (mode == IPOIB_MODE_DATAGRAM) - ret = ipoib_set_mode(dev, "datagram\n"); - else if (mode == IPOIB_MODE_CONNECTED) - ret = ipoib_set_mode(dev, "connected\n"); - else - ret = -EINVAL; - - if (ret < 0) - goto out_err; - } - - if (data[IFLA_IPOIB_UMCAST]) { - umcast = nla_get_u16(data[IFLA_IPOIB_UMCAST]); - ipoib_set_umcast(dev, umcast); - } - -out_err: - return ret; -} - static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { @@ -121,8 +69,6 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD); - if (!err && data) - err = ipoib_changelink(dev, tb, data); return err; } @@ -141,9 +87,7 @@ static void ipoib_unregister_child_dev(struct net_device *dev, struct list_head static size_t ipoib_get_size(const struct net_device *dev) { - return nla_total_size(2) + /* IFLA_IPOIB_PKEY */ - nla_total_size(2) + /* IFLA_IPOIB_MODE */ - nla_total_size(2); /* IFLA_IPOIB_UMCAST */ + return nla_total_size(2); /* IFLA_IPOIB_PKEY */ } static struct rtnl_link_ops ipoib_link_ops __read_mostly = { @@ -153,10 +97,8 @@ static struct rtnl_link_ops ipoib_link_ops __read_mostly = { .priv_size = sizeof(struct ipoib_dev_priv), .setup = ipoib_setup, .newlink = ipoib_new_child_link, - .changelink = ipoib_changelink, .dellink = ipoib_unregister_child_dev, .get_size = ipoib_get_size, - .fill_info = ipoib_fill_info, }; int __init ipoib_netlink_init(void) diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 8292554bccb5..238bbf9b2bea 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -88,21 +88,17 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, ipoib_create_debug_files(priv->dev); - /* RTNL childs don't need proprietary sysfs entries */ - if (type == IPOIB_LEGACY_CHILD) { - if (ipoib_cm_add_mode_attr(priv->dev)) - goto sysfs_failed; - if (ipoib_add_pkey_attr(priv->dev)) - goto sysfs_failed; - if (ipoib_add_umcast_attr(priv->dev)) - goto sysfs_failed; - - if (device_create_file(&priv->dev->dev, &dev_attr_parent)) - goto sysfs_failed; - } + if (ipoib_cm_add_mode_attr(priv->dev)) + goto sysfs_failed; + if (ipoib_add_pkey_attr(priv->dev)) + goto sysfs_failed; + if (ipoib_add_umcast_attr(priv->dev)) + goto sysfs_failed; + + if (device_create_file(&priv->dev->dev, &dev_attr_parent)) + goto sysfs_failed; - priv->child_type = type; - priv->dev->iflink = ppriv->dev->ifindex; + priv->child_type = type; list_add_tail(&priv->list, &ppriv->child_intfs); return 0; diff --git a/trunk/drivers/input/keyboard/imx_keypad.c b/trunk/drivers/input/keyboard/imx_keypad.c index cdc252612c0b..ce68e361558c 100644 --- a/trunk/drivers/input/keyboard/imx_keypad.c +++ b/trunk/drivers/input/keyboard/imx_keypad.c @@ -516,9 +516,9 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) input_set_drvdata(input_dev, keypad); /* Ensure that the keypad will stay dormant until opened */ - clk_prepare_enable(keypad->clk); + clk_enable(keypad->clk); imx_keypad_inhibit(keypad); - clk_disable_unprepare(keypad->clk); + clk_disable(keypad->clk); error = request_irq(irq, imx_keypad_irq_handler, 0, pdev->name, keypad); diff --git a/trunk/drivers/input/misc/ab8500-ponkey.c b/trunk/drivers/input/misc/ab8500-ponkey.c index 84ec691c05aa..f06231b7cab1 100644 --- a/trunk/drivers/input/misc/ab8500-ponkey.c +++ b/trunk/drivers/input/misc/ab8500-ponkey.c @@ -74,8 +74,8 @@ static int __devinit ab8500_ponkey_probe(struct platform_device *pdev) ponkey->idev = input; ponkey->ab8500 = ab8500; - ponkey->irq_dbf = irq_dbf; - ponkey->irq_dbr = irq_dbr; + ponkey->irq_dbf = ab8500_irq_get_virq(ab8500, irq_dbf); + ponkey->irq_dbr = ab8500_irq_get_virq(ab8500, irq_dbr); input->name = "AB8500 POn(PowerOn) Key"; input->dev.parent = &pdev->dev; diff --git a/trunk/drivers/input/mouse/sentelic.c b/trunk/drivers/input/mouse/sentelic.c index a261d8576919..3f5649f19082 100644 --- a/trunk/drivers/input/mouse/sentelic.c +++ b/trunk/drivers/input/mouse/sentelic.c @@ -721,17 +721,6 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { case FSP_PKT_TYPE_ABS: - - if ((packet[0] == 0x48 || packet[0] == 0x49) && - packet[1] == 0 && packet[2] == 0) { - /* - * Ignore coordinate noise when finger leaving the - * surface, otherwise cursor may jump to upper-left - * corner. - */ - packet[3] &= 0xf0; - } - abs_x = GET_ABS_X(packet); abs_y = GET_ABS_Y(packet); diff --git a/trunk/drivers/input/serio/ambakmi.c b/trunk/drivers/input/serio/ambakmi.c index 2e77246c2e5a..2ffd110bd5bc 100644 --- a/trunk/drivers/input/serio/ambakmi.c +++ b/trunk/drivers/input/serio/ambakmi.c @@ -72,7 +72,7 @@ static int amba_kmi_open(struct serio *io) unsigned int divisor; int ret; - ret = clk_prepare_enable(kmi->clk); + ret = clk_enable(kmi->clk); if (ret) goto out; @@ -92,7 +92,7 @@ static int amba_kmi_open(struct serio *io) return 0; clk_disable: - clk_disable_unprepare(kmi->clk); + clk_disable(kmi->clk); out: return ret; } @@ -104,7 +104,7 @@ static void amba_kmi_close(struct serio *io) writeb(0, KMICR); free_irq(kmi->irq, kmi); - clk_disable_unprepare(kmi->clk); + clk_disable(kmi->clk); } static int __devinit amba_kmi_probe(struct amba_device *dev, diff --git a/trunk/drivers/input/serio/i8042-x86ia64io.h b/trunk/drivers/input/serio/i8042-x86ia64io.h index d6cc77a53c7e..6918773ce024 100644 --- a/trunk/drivers/input/serio/i8042-x86ia64io.h +++ b/trunk/drivers/input/serio/i8042-x86ia64io.h @@ -333,12 +333,6 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), }, }, - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"), - }, - }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), diff --git a/trunk/drivers/input/touchscreen/edt-ft5x06.c b/trunk/drivers/input/touchscreen/edt-ft5x06.c index 64957770b522..b06a5e3a665e 100644 --- a/trunk/drivers/input/touchscreen/edt-ft5x06.c +++ b/trunk/drivers/input/touchscreen/edt-ft5x06.c @@ -566,12 +566,9 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file, } read = min_t(size_t, count, tsdata->raw_bufsize - *off); - if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) { - error = -EFAULT; - goto out; - } - - *off += read; + error = copy_to_user(buf, tsdata->raw_buffer + *off, read); + if (!error) + *off += read; out: mutex_unlock(&tsdata->mutex); return error ?: read; diff --git a/trunk/drivers/input/touchscreen/usbtouchscreen.c b/trunk/drivers/input/touchscreen/usbtouchscreen.c index 721fdb3597ca..e32709e0dd65 100644 --- a/trunk/drivers/input/touchscreen/usbtouchscreen.c +++ b/trunk/drivers/input/touchscreen/usbtouchscreen.c @@ -304,45 +304,6 @@ static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) #define EGALAX_PKT_TYPE_REPT 0x80 #define EGALAX_PKT_TYPE_DIAG 0x0A -static int egalax_init(struct usbtouch_usb *usbtouch) -{ - int ret, i; - unsigned char *buf; - struct usb_device *udev = interface_to_usbdev(usbtouch->interface); - - /* - * An eGalax diagnostic packet kicks the device into using the right - * protocol. We send a "check active" packet. The response will be - * read later and ignored. - */ - - buf = kmalloc(3, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - buf[0] = EGALAX_PKT_TYPE_DIAG; - buf[1] = 1; /* length */ - buf[2] = 'A'; /* command - check active */ - - for (i = 0; i < 3; i++) { - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, buf, 3, - USB_CTRL_SET_TIMEOUT); - if (ret >= 0) { - ret = 0; - break; - } - if (ret != -EPIPE) - break; - } - - kfree(buf); - - return ret; -} - static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) { if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) @@ -1095,7 +1056,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { .process_pkt = usbtouch_process_multi, .get_pkt_len = egalax_get_pkt_len, .read_data = egalax_read_data, - .init = egalax_init, }, #endif diff --git a/trunk/drivers/md/dm-mpath.c b/trunk/drivers/md/dm-mpath.c index 034233eefc82..d8abb90a6c2f 100644 --- a/trunk/drivers/md/dm-mpath.c +++ b/trunk/drivers/md/dm-mpath.c @@ -1555,7 +1555,6 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) { struct multipath *m = ti->private; - struct pgpath *pgpath; struct block_device *bdev; fmode_t mode; unsigned long flags; @@ -1571,14 +1570,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, if (!m->current_pgpath) __choose_pgpath(m, 0); - pgpath = m->current_pgpath; - - if (pgpath) { - bdev = pgpath->path.dev->bdev; - mode = pgpath->path.dev->mode; + if (m->current_pgpath) { + bdev = m->current_pgpath->path.dev->bdev; + mode = m->current_pgpath->path.dev->mode; } - if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path)) + if (m->queue_io) r = -EAGAIN; else if (!bdev) r = -EIO; diff --git a/trunk/drivers/md/dm-table.c b/trunk/drivers/md/dm-table.c index 100368eb7991..f90069029aae 100644 --- a/trunk/drivers/md/dm-table.c +++ b/trunk/drivers/md/dm-table.c @@ -1212,41 +1212,6 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector) return &t->targets[(KEYS_PER_NODE * n) + k]; } -static int count_device(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) -{ - unsigned *num_devices = data; - - (*num_devices)++; - - return 0; -} - -/* - * Check whether a table has no data devices attached using each - * target's iterate_devices method. - * Returns false if the result is unknown because a target doesn't - * support iterate_devices. - */ -bool dm_table_has_no_data_devices(struct dm_table *table) -{ - struct dm_target *uninitialized_var(ti); - unsigned i = 0, num_devices = 0; - - while (i < dm_table_get_num_targets(table)) { - ti = dm_table_get_target(table, i++); - - if (!ti->type->iterate_devices) - return false; - - ti->type->iterate_devices(ti, count_device, &num_devices); - if (num_devices) - return false; - } - - return true; -} - /* * Establish the new table's queue_limits and validate them. */ @@ -1389,25 +1354,17 @@ static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev, return q && blk_queue_nonrot(q); } -static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) -{ - struct request_queue *q = bdev_get_queue(dev->bdev); - - return q && !blk_queue_add_random(q); -} - -static bool dm_table_all_devices_attribute(struct dm_table *t, - iterate_devices_callout_fn func) +static bool dm_table_is_nonrot(struct dm_table *t) { struct dm_target *ti; unsigned i = 0; + /* Ensure that all underlying device are non-rotational. */ while (i < dm_table_get_num_targets(t)) { ti = dm_table_get_target(t, i++); if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, func, NULL)) + !ti->type->iterate_devices(ti, device_is_nonrot, NULL)) return 0; } @@ -1439,23 +1396,13 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, if (!dm_table_discard_zeroes_data(t)) q->limits.discard_zeroes_data = 0; - /* Ensure that all underlying devices are non-rotational. */ - if (dm_table_all_devices_attribute(t, device_is_nonrot)) + if (dm_table_is_nonrot(t)) queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); else queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); dm_table_set_integrity(t); - /* - * Determine whether or not this queue's I/O timings contribute - * to the entropy pool, Only request-based targets use this. - * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not - * have it set. - */ - if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random)) - queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q); - /* * QUEUE_FLAG_STACKABLE must be set after all queue settings are * visible to other CPUs because, once the flag is set, incoming bios diff --git a/trunk/drivers/md/dm-thin.c b/trunk/drivers/md/dm-thin.c index c29410af1e22..af1fc3b2c2ad 100644 --- a/trunk/drivers/md/dm-thin.c +++ b/trunk/drivers/md/dm-thin.c @@ -509,9 +509,9 @@ enum pool_mode { struct pool_features { enum pool_mode mode; - bool zero_new_blocks:1; - bool discard_enabled:1; - bool discard_passdown:1; + unsigned zero_new_blocks:1; + unsigned discard_enabled:1; + unsigned discard_passdown:1; }; struct thin_c; @@ -580,8 +580,7 @@ struct pool_c { struct dm_target_callbacks callbacks; dm_block_t low_water_blocks; - struct pool_features requested_pf; /* Features requested during table load */ - struct pool_features adjusted_pf; /* Features used after adjusting for constituent devices */ + struct pool_features pf; }; /* @@ -1840,47 +1839,6 @@ static void __requeue_bios(struct pool *pool) /*---------------------------------------------------------------- * Binding of control targets to a pool object *--------------------------------------------------------------*/ -static bool data_dev_supports_discard(struct pool_c *pt) -{ - struct request_queue *q = bdev_get_queue(pt->data_dev->bdev); - - return q && blk_queue_discard(q); -} - -/* - * If discard_passdown was enabled verify that the data device - * supports discards. Disable discard_passdown if not. - */ -static void disable_passdown_if_not_supported(struct pool_c *pt) -{ - struct pool *pool = pt->pool; - struct block_device *data_bdev = pt->data_dev->bdev; - struct queue_limits *data_limits = &bdev_get_queue(data_bdev)->limits; - sector_t block_size = pool->sectors_per_block << SECTOR_SHIFT; - const char *reason = NULL; - char buf[BDEVNAME_SIZE]; - - if (!pt->adjusted_pf.discard_passdown) - return; - - if (!data_dev_supports_discard(pt)) - reason = "discard unsupported"; - - else if (data_limits->max_discard_sectors < pool->sectors_per_block) - reason = "max discard sectors smaller than a block"; - - else if (data_limits->discard_granularity > block_size) - reason = "discard granularity larger than a block"; - - else if (block_size & (data_limits->discard_granularity - 1)) - reason = "discard granularity not a factor of block size"; - - if (reason) { - DMWARN("Data device (%s) %s: Disabling discard passdown.", bdevname(data_bdev, buf), reason); - pt->adjusted_pf.discard_passdown = false; - } -} - static int bind_control_target(struct pool *pool, struct dm_target *ti) { struct pool_c *pt = ti->private; @@ -1889,17 +1847,32 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti) * We want to make sure that degraded pools are never upgraded. */ enum pool_mode old_mode = pool->pf.mode; - enum pool_mode new_mode = pt->adjusted_pf.mode; + enum pool_mode new_mode = pt->pf.mode; if (old_mode > new_mode) new_mode = old_mode; pool->ti = ti; pool->low_water_blocks = pt->low_water_blocks; - pool->pf = pt->adjusted_pf; - + pool->pf = pt->pf; set_pool_mode(pool, new_mode); + /* + * If discard_passdown was enabled verify that the data device + * supports discards. Disable discard_passdown if not; otherwise + * -EOPNOTSUPP will be returned. + */ + /* FIXME: pull this out into a sep fn. */ + if (pt->pf.discard_passdown) { + struct request_queue *q = bdev_get_queue(pt->data_dev->bdev); + if (!q || !blk_queue_discard(q)) { + char buf[BDEVNAME_SIZE]; + DMWARN("Discard unsupported by data device (%s): Disabling discard passdown.", + bdevname(pt->data_dev->bdev, buf)); + pool->pf.discard_passdown = 0; + } + } + return 0; } @@ -1916,9 +1889,9 @@ static void unbind_control_target(struct pool *pool, struct dm_target *ti) static void pool_features_init(struct pool_features *pf) { pf->mode = PM_WRITE; - pf->zero_new_blocks = true; - pf->discard_enabled = true; - pf->discard_passdown = true; + pf->zero_new_blocks = 1; + pf->discard_enabled = 1; + pf->discard_passdown = 1; } static void __pool_destroy(struct pool *pool) @@ -2146,13 +2119,13 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf, argc--; if (!strcasecmp(arg_name, "skip_block_zeroing")) - pf->zero_new_blocks = false; + pf->zero_new_blocks = 0; else if (!strcasecmp(arg_name, "ignore_discard")) - pf->discard_enabled = false; + pf->discard_enabled = 0; else if (!strcasecmp(arg_name, "no_discard_passdown")) - pf->discard_passdown = false; + pf->discard_passdown = 0; else if (!strcasecmp(arg_name, "read_only")) pf->mode = PM_READ_ONLY; @@ -2286,9 +2259,8 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) pt->metadata_dev = metadata_dev; pt->data_dev = data_dev; pt->low_water_blocks = low_water_blocks; - pt->adjusted_pf = pt->requested_pf = pf; + pt->pf = pf; ti->num_flush_requests = 1; - /* * Only need to enable discards if the pool should pass * them down to the data device. The thin device's discard @@ -2296,14 +2268,12 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) */ if (pf.discard_enabled && pf.discard_passdown) { ti->num_discard_requests = 1; - /* * Setting 'discards_supported' circumvents the normal * stacking of discard limits (this keeps the pool and * thin devices' discard limits consistent). */ ti->discards_supported = true; - ti->discard_zeroes_data_unsupported = true; } ti->private = pt; @@ -2733,7 +2703,7 @@ static int pool_status(struct dm_target *ti, status_type_t type, format_dev_t(buf2, pt->data_dev->bdev->bd_dev), (unsigned long)pool->sectors_per_block, (unsigned long long)pt->low_water_blocks); - emit_flags(&pt->requested_pf, result, sz, maxlen); + emit_flags(&pt->pf, result, sz, maxlen); break; } @@ -2762,21 +2732,20 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm, return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); } -static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits) +static void set_discard_limits(struct pool *pool, struct queue_limits *limits) { - struct pool *pool = pt->pool; - struct queue_limits *data_limits; - + /* + * FIXME: these limits may be incompatible with the pool's data device + */ limits->max_discard_sectors = pool->sectors_per_block; /* - * discard_granularity is just a hint, and not enforced. + * This is just a hint, and not enforced. We have to cope with + * bios that cover a block partially. A discard that spans a block + * boundary is not sent to this target. */ - if (pt->adjusted_pf.discard_passdown) { - data_limits = &bdev_get_queue(pt->data_dev->bdev)->limits; - limits->discard_granularity = data_limits->discard_granularity; - } else - limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; + limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; + limits->discard_zeroes_data = pool->pf.zero_new_blocks; } static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits) @@ -2786,25 +2755,15 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits) blk_limits_io_min(limits, 0); blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT); - - /* - * pt->adjusted_pf is a staging area for the actual features to use. - * They get transferred to the live pool in bind_control_target() - * called from pool_preresume(). - */ - if (!pt->adjusted_pf.discard_enabled) - return; - - disable_passdown_if_not_supported(pt); - - set_discard_limits(pt, limits); + if (pool->pf.discard_enabled) + set_discard_limits(pool, limits); } static struct target_type pool_target = { .name = "thin-pool", .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | DM_TARGET_IMMUTABLE, - .version = {1, 4, 0}, + .version = {1, 3, 0}, .module = THIS_MODULE, .ctr = pool_ctr, .dtr = pool_dtr, @@ -3083,19 +3042,19 @@ static int thin_iterate_devices(struct dm_target *ti, return 0; } -/* - * A thin device always inherits its queue limits from its pool. - */ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) { struct thin_c *tc = ti->private; + struct pool *pool = tc->pool; - *limits = bdev_get_queue(tc->pool_dev->bdev)->limits; + blk_limits_io_min(limits, 0); + blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT); + set_discard_limits(pool, limits); } static struct target_type thin_target = { .name = "thin", - .version = {1, 4, 0}, + .version = {1, 3, 0}, .module = THIS_MODULE, .ctr = thin_ctr, .dtr = thin_dtr, diff --git a/trunk/drivers/md/dm-verity.c b/trunk/drivers/md/dm-verity.c index 892ae2766aa6..254d19268ad2 100644 --- a/trunk/drivers/md/dm-verity.c +++ b/trunk/drivers/md/dm-verity.c @@ -718,8 +718,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) v->hash_dev_block_bits = ffs(num) - 1; if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 || - (sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) - >> (v->data_dev_block_bits - SECTOR_SHIFT) != num_ll) { + num_ll << (v->data_dev_block_bits - SECTOR_SHIFT) != + (sector_t)num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) { ti->error = "Invalid data blocks"; r = -EINVAL; goto bad; @@ -733,8 +733,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) } if (sscanf(argv[6], "%llu%c", &num_ll, &dummy) != 1 || - (sector_t)(num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) - >> (v->hash_dev_block_bits - SECTOR_SHIFT) != num_ll) { + num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT) != + (sector_t)num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) { ti->error = "Invalid hash start"; r = -EINVAL; goto bad; diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index 67ffa391edcf..4e09b6ff5b49 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -865,14 +865,10 @@ static void dm_done(struct request *clone, int error, bool mapped) { int r = error; struct dm_rq_target_io *tio = clone->end_io_data; - dm_request_endio_fn rq_end_io = NULL; + dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io; - if (tio->ti) { - rq_end_io = tio->ti->type->rq_end_io; - - if (mapped && rq_end_io) - r = rq_end_io(tio->ti, clone, error, &tio->info); - } + if (mapped && rq_end_io) + r = rq_end_io(tio->ti, clone, error, &tio->info); if (r <= 0) /* The target wants to complete the I/O */ @@ -1592,6 +1588,15 @@ static int map_request(struct dm_target *ti, struct request *clone, int r, requeued = 0; struct dm_rq_target_io *tio = clone->end_io_data; + /* + * Hold the md reference here for the in-flight I/O. + * We can't rely on the reference count by device opener, + * because the device may be closed during the request completion + * when all bios are completed. + * See the comment in rq_completed() too. + */ + dm_get(md); + tio->ti = ti; r = ti->type->map_rq(ti, clone, &tio->info); switch (r) { @@ -1623,26 +1628,6 @@ static int map_request(struct dm_target *ti, struct request *clone, return requeued; } -static struct request *dm_start_request(struct mapped_device *md, struct request *orig) -{ - struct request *clone; - - blk_start_request(orig); - clone = orig->special; - atomic_inc(&md->pending[rq_data_dir(clone)]); - - /* - * Hold the md reference here for the in-flight I/O. - * We can't rely on the reference count by device opener, - * because the device may be closed during the request completion - * when all bios are completed. - * See the comment in rq_completed() too. - */ - dm_get(md); - - return clone; -} - /* * q->request_fn for request-based dm. * Called with the queue lock held. @@ -1672,21 +1657,14 @@ static void dm_request_fn(struct request_queue *q) pos = blk_rq_pos(rq); ti = dm_table_find_target(map, pos); - if (!dm_target_is_valid(ti)) { - /* - * Must perform setup, that dm_done() requires, - * before calling dm_kill_unmapped_request - */ - DMERR_LIMIT("request attempted access beyond the end of device"); - clone = dm_start_request(md, rq); - dm_kill_unmapped_request(clone, -EIO); - continue; - } + BUG_ON(!dm_target_is_valid(ti)); if (ti->type->busy && ti->type->busy(ti)) goto delay_and_out; - clone = dm_start_request(md, rq); + blk_start_request(rq); + clone = rq->special; + atomic_inc(&md->pending[rq_data_dir(clone)]); spin_unlock(q->queue_lock); if (map_request(ti, clone, md)) @@ -1706,6 +1684,8 @@ static void dm_request_fn(struct request_queue *q) blk_delay_queue(q, HZ / 10); out: dm_table_put(map); + + return; } int dm_underlying_device_busy(struct request_queue *q) @@ -2429,7 +2409,7 @@ static void dm_queue_flush(struct mapped_device *md) */ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) { - struct dm_table *live_map, *map = ERR_PTR(-EINVAL); + struct dm_table *map = ERR_PTR(-EINVAL); struct queue_limits limits; int r; @@ -2439,19 +2419,6 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) if (!dm_suspended_md(md)) goto out; - /* - * If the new table has no data devices, retain the existing limits. - * This helps multipath with queue_if_no_path if all paths disappear, - * then new I/O is queued based on these limits, and then some paths - * reappear. - */ - if (dm_table_has_no_data_devices(table)) { - live_map = dm_get_live_table(md); - if (live_map) - limits = md->queue->limits; - dm_table_put(live_map); - } - r = dm_calculate_queue_limits(table, &limits); if (r) { map = ERR_PTR(r); diff --git a/trunk/drivers/md/dm.h b/trunk/drivers/md/dm.h index 6a99fefaa743..52eef493d266 100644 --- a/trunk/drivers/md/dm.h +++ b/trunk/drivers/md/dm.h @@ -54,7 +54,6 @@ void dm_table_event_callback(struct dm_table *t, void (*fn)(void *), void *context); struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index); struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector); -bool dm_table_has_no_data_devices(struct dm_table *table); int dm_calculate_queue_limits(struct dm_table *table, struct queue_limits *limits); void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 308e87b417e0..3f6203a4c7ea 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -7619,8 +7619,6 @@ static int remove_and_add_spares(struct mddev *mddev) } } } - if (removed) - set_bit(MD_CHANGE_DEVS, &mddev->flags); return spares; } @@ -7634,11 +7632,9 @@ static void reap_sync_thread(struct mddev *mddev) !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { /* success...*/ /* activate any spares */ - if (mddev->pers->spare_active(mddev)) { + if (mddev->pers->spare_active(mddev)) sysfs_notify(&mddev->kobj, NULL, "degraded"); - set_bit(MD_CHANGE_DEVS, &mddev->flags); - } } if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && mddev->pers->finish_reshape) diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index 0138a727c1f3..1c2eb38f3c51 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -1512,16 +1512,14 @@ static int _enough(struct r10conf *conf, struct geom *geo, int ignore) do { int n = conf->copies; int cnt = 0; - int this = first; while (n--) { - if (conf->mirrors[this].rdev && - this != ignore) + if (conf->mirrors[first].rdev && + first != ignore) cnt++; - this = (this+1) % geo->raid_disks; + first = (first+1) % geo->raid_disks; } if (cnt == 0) return 0; - first = (first + geo->near_copies) % geo->raid_disks; } while (first != 0); return 1; } diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 0689173fd9f5..adda94df5eb2 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -393,8 +393,6 @@ static int calc_degraded(struct r5conf *conf) degraded = 0; for (i = 0; i < conf->previous_raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && test_bit(Faulty, &rdev->flags)) - rdev = rcu_dereference(conf->disks[i].replacement); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded++; else if (test_bit(In_sync, &rdev->flags)) @@ -419,8 +417,6 @@ static int calc_degraded(struct r5conf *conf) degraded2 = 0; for (i = 0; i < conf->raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && test_bit(Faulty, &rdev->flags)) - rdev = rcu_dereference(conf->disks[i].replacement); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded2++; else if (test_bit(In_sync, &rdev->flags)) @@ -1591,7 +1587,6 @@ static int resize_stripes(struct r5conf *conf, int newsize) #ifdef CONFIG_MULTICORE_RAID456 init_waitqueue_head(&nsh->ops.wait_for_ops); #endif - spin_lock_init(&nsh->stripe_lock); list_add(&nsh->lru, &newstripes); } @@ -4197,7 +4192,7 @@ static void make_request(struct mddev *mddev, struct bio * bi) finish_wait(&conf->wait_for_overlap, &w); set_bit(STRIPE_HANDLE, &sh->state); clear_bit(STRIPE_DELAYED, &sh->state); - if ((bi->bi_rw & REQ_SYNC) && + if ((bi->bi_rw & REQ_NOIDLE) && !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) atomic_inc(&conf->preread_active_stripes); release_stripe_plug(mddev, sh); diff --git a/trunk/drivers/mfd/88pm800.c b/trunk/drivers/mfd/88pm800.c index ce229ea933d1..b67a3018b136 100644 --- a/trunk/drivers/mfd/88pm800.c +++ b/trunk/drivers/mfd/88pm800.c @@ -470,8 +470,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip, ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], - ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0, - NULL); + ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; @@ -482,7 +481,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip, rtc_devs[0].platform_data = pdata->rtc; rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata); ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], - ARRAY_SIZE(rtc_devs), NULL, 0, NULL); + ARRAY_SIZE(rtc_devs), NULL, 0); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out_dev; diff --git a/trunk/drivers/mfd/88pm805.c b/trunk/drivers/mfd/88pm805.c index c20a31136f04..6146583589f6 100644 --- a/trunk/drivers/mfd/88pm805.c +++ b/trunk/drivers/mfd/88pm805.c @@ -216,8 +216,7 @@ static int __devinit device_805_init(struct pm80x_chip *chip) } ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], - ARRAY_SIZE(codec_devs), &codec_resources[0], 0, - NULL); + ARRAY_SIZE(codec_devs), &codec_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add codec subdev\n"); goto out_codec; diff --git a/trunk/drivers/mfd/88pm860x-core.c b/trunk/drivers/mfd/88pm860x-core.c index b73f033b2c60..d09918cf1b15 100644 --- a/trunk/drivers/mfd/88pm860x-core.c +++ b/trunk/drivers/mfd/88pm860x-core.c @@ -637,7 +637,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip, bk_devs[i].resources = &bk_resources[j]; ret = mfd_add_devices(chip->dev, 0, &bk_devs[i], 1, - &bk_resources[j], 0, NULL); + &bk_resources[j], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add " "backlight subdev\n"); @@ -672,7 +672,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip, led_devs[i].resources = &led_resources[j], ret = mfd_add_devices(chip->dev, 0, &led_devs[i], 1, - &led_resources[j], 0, NULL); + &led_resources[j], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add " "led subdev\n"); @@ -709,7 +709,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip, regulator_devs[i].resources = ®ulator_resources[seq]; ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, - ®ulator_resources[seq], 0, NULL); + ®ulator_resources[seq], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add regulator subdev\n"); goto out; @@ -733,7 +733,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip, rtc_devs[0].resources = &rtc_resources[0]; ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), &rtc_resources[0], - chip->irq_base, NULL); + chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add rtc subdev\n"); } @@ -752,7 +752,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip, touch_devs[0].resources = &touch_resources[0]; ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], ARRAY_SIZE(touch_devs), &touch_resources[0], - chip->irq_base, NULL); + chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add touch subdev\n"); } @@ -770,7 +770,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[0].num_resources = ARRAY_SIZE(battery_resources); power_devs[0].resources = &battery_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, - &battery_resources[0], chip->irq_base, NULL); + &battery_resources[0], chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add battery subdev\n"); @@ -779,7 +779,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[1].num_resources = ARRAY_SIZE(charger_resources); power_devs[1].resources = &charger_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, - &charger_resources[0], chip->irq_base, NULL); + &charger_resources[0], chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add charger subdev\n"); @@ -788,7 +788,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[2].num_resources = ARRAY_SIZE(preg_resources); power_devs[2].resources = &preg_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, - &preg_resources[0], chip->irq_base, NULL); + &preg_resources[0], chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add preg subdev\n"); } @@ -802,7 +802,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip, onkey_devs[0].resources = &onkey_resources[0], ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], ARRAY_SIZE(onkey_devs), &onkey_resources[0], - chip->irq_base, NULL); + chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add onkey subdev\n"); } @@ -815,8 +815,7 @@ static void __devinit device_codec_init(struct pm860x_chip *chip, codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); codec_devs[0].resources = &codec_resources[0], ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], - ARRAY_SIZE(codec_devs), &codec_resources[0], 0, - NULL); + ARRAY_SIZE(codec_devs), &codec_resources[0], 0); if (ret < 0) dev_err(chip->dev, "Failed to add codec subdev\n"); } diff --git a/trunk/drivers/mfd/aat2870-core.c b/trunk/drivers/mfd/aat2870-core.c index f1beb4971f87..44a3fdbadef4 100644 --- a/trunk/drivers/mfd/aat2870-core.c +++ b/trunk/drivers/mfd/aat2870-core.c @@ -424,7 +424,7 @@ static int aat2870_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs, - ARRAY_SIZE(aat2870_devs), NULL, 0, NULL); + ARRAY_SIZE(aat2870_devs), NULL, 0); if (ret != 0) { dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret); goto out_disable; diff --git a/trunk/drivers/mfd/ab3100-core.c b/trunk/drivers/mfd/ab3100-core.c index 01781ae5d0d7..78fca2902c8d 100644 --- a/trunk/drivers/mfd/ab3100-core.c +++ b/trunk/drivers/mfd/ab3100-core.c @@ -946,7 +946,7 @@ static int __devinit ab3100_probe(struct i2c_client *client, } err = mfd_add_devices(&client->dev, 0, ab3100_devs, - ARRAY_SIZE(ab3100_devs), NULL, 0, NULL); + ARRAY_SIZE(ab3100_devs), NULL, 0); ab3100_setup_debugfs(ab3100); diff --git a/trunk/drivers/mfd/ab8500-core.c b/trunk/drivers/mfd/ab8500-core.c index 47adf800024e..626b4ecaf647 100644 --- a/trunk/drivers/mfd/ab8500-core.c +++ b/trunk/drivers/mfd/ab8500-core.c @@ -1418,25 +1418,25 @@ static int __devinit ab8500_probe(struct platform_device *pdev) ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, ARRAY_SIZE(abx500_common_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); if (ret) goto out_freeirq; if (is_ab9540(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, ARRAY_SIZE(ab9540_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); else ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, ARRAY_SIZE(ab8500_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); if (ret) goto out_freeirq; if (is_ab9540(ab8500) || is_ab8505(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, ARRAY_SIZE(ab9540_ab8505_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); if (ret) goto out_freeirq; @@ -1444,7 +1444,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev) /* Add battery management devices */ ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, ARRAY_SIZE(ab8500_bm_devs), NULL, - ab8500->irq_base, ab8500->domain); + ab8500->irq_base); if (ret) dev_err(ab8500->dev, "error adding bm devices\n"); } diff --git a/trunk/drivers/mfd/arizona-core.c b/trunk/drivers/mfd/arizona-core.c index 1b48f2094806..c7983e862549 100644 --- a/trunk/drivers/mfd/arizona-core.c +++ b/trunk/drivers/mfd/arizona-core.c @@ -316,7 +316,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) } ret = mfd_add_devices(arizona->dev, -1, early_devs, - ARRAY_SIZE(early_devs), NULL, 0, NULL); + ARRAY_SIZE(early_devs), NULL, 0); if (ret != 0) { dev_err(dev, "Failed to add early children: %d\n", ret); return ret; @@ -516,11 +516,11 @@ int __devinit arizona_dev_init(struct arizona *arizona) switch (arizona->type) { case WM5102: ret = mfd_add_devices(arizona->dev, -1, wm5102_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); + ARRAY_SIZE(wm5102_devs), NULL, 0); break; case WM5110: ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); + ARRAY_SIZE(wm5102_devs), NULL, 0); break; } diff --git a/trunk/drivers/mfd/asic3.c b/trunk/drivers/mfd/asic3.c index 62f0883a7630..683e18a23329 100644 --- a/trunk/drivers/mfd/asic3.c +++ b/trunk/drivers/mfd/asic3.c @@ -913,14 +913,14 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, if (pdata->clock_rate) { ds1wm_pdata.clock_rate = pdata->clock_rate; ret = mfd_add_devices(&pdev->dev, pdev->id, - &asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL); + &asic3_cell_ds1wm, 1, mem, asic->irq_base); if (ret < 0) goto out; } if (mem_sdio && (irq >= 0)) { ret = mfd_add_devices(&pdev->dev, pdev->id, - &asic3_cell_mmc, 1, mem_sdio, irq, NULL); + &asic3_cell_mmc, 1, mem_sdio, irq); if (ret < 0) goto out; } @@ -934,7 +934,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]); } ret = mfd_add_devices(&pdev->dev, 0, - asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL); + asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0); } out: diff --git a/trunk/drivers/mfd/cs5535-mfd.c b/trunk/drivers/mfd/cs5535-mfd.c index 2b282133c725..3419e726de47 100644 --- a/trunk/drivers/mfd/cs5535-mfd.c +++ b/trunk/drivers/mfd/cs5535-mfd.c @@ -149,7 +149,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev, } err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells, - ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL); + ARRAY_SIZE(cs5535_mfd_cells), NULL, 0); if (err) { dev_err(&pdev->dev, "MFD add devices failed: %d\n", err); goto err_disable; diff --git a/trunk/drivers/mfd/da9052-core.c b/trunk/drivers/mfd/da9052-core.c index a0a62b24621b..2544910e1fd6 100644 --- a/trunk/drivers/mfd/da9052-core.c +++ b/trunk/drivers/mfd/da9052-core.c @@ -803,7 +803,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret); ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info, - ARRAY_SIZE(da9052_subdev_info), NULL, 0, NULL); + ARRAY_SIZE(da9052_subdev_info), NULL, 0); if (ret) goto err; diff --git a/trunk/drivers/mfd/davinci_voicecodec.c b/trunk/drivers/mfd/davinci_voicecodec.c index 45e83a68641b..4e2af2cb2d26 100644 --- a/trunk/drivers/mfd/davinci_voicecodec.c +++ b/trunk/drivers/mfd/davinci_voicecodec.c @@ -129,7 +129,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev) cell->pdata_size = sizeof(*davinci_vc); ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, - DAVINCI_VC_CELLS, NULL, 0, NULL); + DAVINCI_VC_CELLS, NULL, 0); if (ret != 0) { dev_err(&pdev->dev, "fail to register client devices\n"); goto fail4; diff --git a/trunk/drivers/mfd/db8500-prcmu.c b/trunk/drivers/mfd/db8500-prcmu.c index 0e63cdd9b52a..7040a0081130 100644 --- a/trunk/drivers/mfd/db8500-prcmu.c +++ b/trunk/drivers/mfd/db8500-prcmu.c @@ -3010,7 +3010,7 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, - ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL); + ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); if (err) { pr_err("prcmu: Failed to add subdevices\n"); return err; diff --git a/trunk/drivers/mfd/htc-pasic3.c b/trunk/drivers/mfd/htc-pasic3.c index 9e5453d21a68..04c7093d6499 100644 --- a/trunk/drivers/mfd/htc-pasic3.c +++ b/trunk/drivers/mfd/htc-pasic3.c @@ -168,7 +168,7 @@ static int __init pasic3_probe(struct platform_device *pdev) /* the first 5 PASIC3 registers control the DS1WM */ ds1wm_resources[0].end = (5 << asic->bus_shift) - 1; ret = mfd_add_devices(&pdev->dev, pdev->id, - &ds1wm_cell, 1, r, irq, NULL); + &ds1wm_cell, 1, r, irq); if (ret < 0) dev_warn(dev, "failed to register DS1WM\n"); } @@ -176,8 +176,7 @@ static int __init pasic3_probe(struct platform_device *pdev) if (pdata && pdata->led_pdata) { led_cell.platform_data = pdata->led_pdata; led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo); - ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, - 0, NULL); + ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); if (ret < 0) dev_warn(dev, "failed to register LED device\n"); } diff --git a/trunk/drivers/mfd/intel_msic.c b/trunk/drivers/mfd/intel_msic.c index 266bdc5bd96d..59df5584cb58 100644 --- a/trunk/drivers/mfd/intel_msic.c +++ b/trunk/drivers/mfd/intel_msic.c @@ -344,13 +344,13 @@ static int __devinit intel_msic_init_devices(struct intel_msic *msic) continue; ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL, - pdata->irq[i], NULL); + pdata->irq[i]); if (ret) goto fail; } ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs, - ARRAY_SIZE(msic_other_devs), NULL, 0, NULL); + ARRAY_SIZE(msic_other_devs), NULL, 0); if (ret) goto fail; diff --git a/trunk/drivers/mfd/janz-cmodio.c b/trunk/drivers/mfd/janz-cmodio.c index 965c4801df8a..2ea99989551a 100644 --- a/trunk/drivers/mfd/janz-cmodio.c +++ b/trunk/drivers/mfd/janz-cmodio.c @@ -147,7 +147,7 @@ static int __devinit cmodio_probe_submodules(struct cmodio_device *priv) } return mfd_add_devices(&pdev->dev, 0, priv->cells, - num_probed, NULL, pdev->irq, NULL); + num_probed, NULL, pdev->irq); } /* diff --git a/trunk/drivers/mfd/jz4740-adc.c b/trunk/drivers/mfd/jz4740-adc.c index c6b6d7dda517..87662a17dec6 100644 --- a/trunk/drivers/mfd/jz4740-adc.c +++ b/trunk/drivers/mfd/jz4740-adc.c @@ -287,8 +287,7 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev) writeb(0xff, adc->base + JZ_REG_ADC_CTRL); ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, - ARRAY_SIZE(jz4740_adc_cells), mem_base, - irq_base, NULL); + ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base); if (ret < 0) goto err_clk_put; diff --git a/trunk/drivers/mfd/lm3533-core.c b/trunk/drivers/mfd/lm3533-core.c index 24212f45b201..0b2879b87fd9 100644 --- a/trunk/drivers/mfd/lm3533-core.c +++ b/trunk/drivers/mfd/lm3533-core.c @@ -393,8 +393,7 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533) lm3533_als_devs[0].platform_data = pdata->als; lm3533_als_devs[0].pdata_size = sizeof(*pdata->als); - ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, - 0, NULL); + ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, 0); if (ret) { dev_err(lm3533->dev, "failed to add ALS device\n"); return ret; @@ -423,7 +422,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533) } ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs, - pdata->num_backlights, NULL, 0, NULL); + pdata->num_backlights, NULL, 0); if (ret) { dev_err(lm3533->dev, "failed to add backlight devices\n"); return ret; @@ -452,7 +451,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533) } ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs, - pdata->num_leds, NULL, 0, NULL); + pdata->num_leds, NULL, 0); if (ret) { dev_err(lm3533->dev, "failed to add LED devices\n"); return ret; diff --git a/trunk/drivers/mfd/lpc_ich.c b/trunk/drivers/mfd/lpc_ich.c index 092ad4b44b6d..027cc8f86132 100644 --- a/trunk/drivers/mfd/lpc_ich.c +++ b/trunk/drivers/mfd/lpc_ich.c @@ -750,7 +750,7 @@ static int __devinit lpc_ich_init_gpio(struct pci_dev *dev, lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id); ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO], - 1, NULL, 0, NULL); + 1, NULL, 0); gpio_done: if (acpi_conflict) @@ -765,6 +765,7 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, u32 base_addr_cfg; u32 base_addr; int ret; + bool acpi_conflict = false; struct resource *res; /* Setup power management base register */ @@ -779,11 +780,20 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, res = wdt_io_res(ICH_RES_IO_TCO); res->start = base_addr + ACPIBASE_TCO_OFF; res->end = base_addr + ACPIBASE_TCO_END; + ret = acpi_check_resource_conflict(res); + if (ret) { + acpi_conflict = true; + goto wdt_done; + } res = wdt_io_res(ICH_RES_IO_SMI); res->start = base_addr + ACPIBASE_SMI_OFF; res->end = base_addr + ACPIBASE_SMI_END; - + ret = acpi_check_resource_conflict(res); + if (ret) { + acpi_conflict = true; + goto wdt_done; + } lpc_ich_enable_acpi_space(dev); /* @@ -803,13 +813,21 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, res = wdt_mem_res(ICH_RES_MEM_GCS); res->start = base_addr + ACPIBASE_GCS_OFF; res->end = base_addr + ACPIBASE_GCS_END; + ret = acpi_check_resource_conflict(res); + if (ret) { + acpi_conflict = true; + goto wdt_done; + } } lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], - 1, NULL, 0, NULL); + 1, NULL, 0); wdt_done: + if (acpi_conflict) + pr_warn("Resource conflict(s) found affecting %s\n", + lpc_ich_cells[LPC_WDT].name); return ret; } diff --git a/trunk/drivers/mfd/lpc_sch.c b/trunk/drivers/mfd/lpc_sch.c index f6b9c5c96b24..9f20abc5e393 100644 --- a/trunk/drivers/mfd/lpc_sch.c +++ b/trunk/drivers/mfd/lpc_sch.c @@ -127,8 +127,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, lpc_sch_cells[i].id = id->device; ret = mfd_add_devices(&dev->dev, 0, - lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, - 0, NULL); + lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); if (ret) goto out_dev; @@ -154,8 +153,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, tunnelcreek_cells[i].id = id->device; ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells, - ARRAY_SIZE(tunnelcreek_cells), NULL, - 0, NULL); + ARRAY_SIZE(tunnelcreek_cells), NULL, 0); } return ret; diff --git a/trunk/drivers/mfd/max77686.c b/trunk/drivers/mfd/max77686.c index d9e24c849a00..c03e12b51924 100644 --- a/trunk/drivers/mfd/max77686.c +++ b/trunk/drivers/mfd/max77686.c @@ -126,7 +126,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686_irq_init(max77686); ret = mfd_add_devices(max77686->dev, -1, max77686_devs, - ARRAY_SIZE(max77686_devs), NULL, 0, NULL); + ARRAY_SIZE(max77686_devs), NULL, 0); if (ret < 0) goto err_mfd; diff --git a/trunk/drivers/mfd/max77693-irq.c b/trunk/drivers/mfd/max77693-irq.c index 1029d018c739..2b403569e0a6 100644 --- a/trunk/drivers/mfd/max77693-irq.c +++ b/trunk/drivers/mfd/max77693-irq.c @@ -137,9 +137,6 @@ static void max77693_irq_mask(struct irq_data *data) const struct max77693_irq_data *irq_data = irq_to_max77693_irq(max77693, data->irq); - if (irq_data->group >= MAX77693_IRQ_GROUP_NR) - return; - if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask; else @@ -152,9 +149,6 @@ static void max77693_irq_unmask(struct irq_data *data) const struct max77693_irq_data *irq_data = irq_to_max77693_irq(max77693, data->irq); - if (irq_data->group >= MAX77693_IRQ_GROUP_NR) - return; - if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) max77693->irq_masks_cur[irq_data->group] |= irq_data->mask; else @@ -206,7 +200,7 @@ static irqreturn_t max77693_irq_thread(int irq, void *data) if (irq_src & MAX77693_IRQSRC_MUIC) /* MUIC INT1 ~ INT3 */ - max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1, + max77693_bulk_read(max77693->regmap, MAX77693_MUIC_REG_INT1, MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]); /* Apply masking */ @@ -261,8 +255,7 @@ int max77693_irq_init(struct max77693_dev *max77693) { struct irq_domain *domain; int i; - int ret = 0; - u8 intsrc_mask; + int ret; mutex_init(&max77693->irqlock); @@ -294,38 +287,19 @@ int max77693_irq_init(struct max77693_dev *max77693) &max77693_irq_domain_ops, max77693); if (!domain) { dev_err(max77693->dev, "could not create irq domain\n"); - ret = -ENODEV; - goto err_irq; + return -ENODEV; } max77693->irq_domain = domain; - /* Unmask max77693 interrupt */ - ret = max77693_read_reg(max77693->regmap, - MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask); - if (ret < 0) { - dev_err(max77693->dev, "fail to read PMIC register\n"); - goto err_irq; - } - - intsrc_mask &= ~(MAX77693_IRQSRC_CHG); - intsrc_mask &= ~(MAX77693_IRQSRC_FLASH); - intsrc_mask &= ~(MAX77693_IRQSRC_MUIC); - ret = max77693_write_reg(max77693->regmap, - MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask); - if (ret < 0) { - dev_err(max77693->dev, "fail to write PMIC register\n"); - goto err_irq; - } - ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "max77693-irq", max77693); + if (ret) dev_err(max77693->dev, "Failed to request IRQ %d: %d\n", max77693->irq, ret); -err_irq: - return ret; + return 0; } void max77693_irq_exit(struct max77693_dev *max77693) diff --git a/trunk/drivers/mfd/max77693.c b/trunk/drivers/mfd/max77693.c index cc5155e20494..a1811cb50ec7 100644 --- a/trunk/drivers/mfd/max77693.c +++ b/trunk/drivers/mfd/max77693.c @@ -152,20 +152,6 @@ static int max77693_i2c_probe(struct i2c_client *i2c, max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); i2c_set_clientdata(max77693->haptic, max77693); - /* - * Initialize register map for MUIC device because use regmap-muic - * instance of MUIC device when irq of max77693 is initialized - * before call max77693-muic probe() function. - */ - max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic, - &max77693_regmap_config); - if (IS_ERR(max77693->regmap_muic)) { - ret = PTR_ERR(max77693->regmap_muic); - dev_err(max77693->dev, - "failed to allocate register map: %d\n", ret); - goto err_regmap; - } - ret = max77693_irq_init(max77693); if (ret < 0) goto err_irq; @@ -173,7 +159,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, pm_runtime_set_active(max77693->dev); ret = mfd_add_devices(max77693->dev, -1, max77693_devs, - ARRAY_SIZE(max77693_devs), NULL, 0, NULL); + ARRAY_SIZE(max77693_devs), NULL, 0); if (ret < 0) goto err_mfd; diff --git a/trunk/drivers/mfd/max8925-core.c b/trunk/drivers/mfd/max8925-core.c index ee53757beca7..825a7f06d9ba 100644 --- a/trunk/drivers/mfd/max8925-core.c +++ b/trunk/drivers/mfd/max8925-core.c @@ -598,7 +598,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), - &rtc_resources[0], chip->irq_base, NULL); + &rtc_resources[0], chip->irq_base); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out; @@ -606,7 +606,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], ARRAY_SIZE(onkey_devs), - &onkey_resources[0], 0, NULL); + &onkey_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; @@ -615,7 +615,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata) { ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], ARRAY_SIZE(regulator_devs), - ®ulator_resources[0], 0, NULL); + ®ulator_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add regulator subdev\n"); goto out_dev; @@ -625,7 +625,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->backlight) { ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0], ARRAY_SIZE(backlight_devs), - &backlight_resources[0], 0, NULL); + &backlight_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add backlight subdev\n"); goto out_dev; @@ -635,7 +635,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->power) { ret = mfd_add_devices(chip->dev, 0, &power_devs[0], ARRAY_SIZE(power_devs), - &power_supply_resources[0], 0, NULL); + &power_supply_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add power supply " "subdev\n"); @@ -646,7 +646,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->touch) { ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], ARRAY_SIZE(touch_devs), - &touch_resources[0], 0, NULL); + &touch_resources[0], 0); if (ret < 0) { dev_err(chip->dev, "Failed to add touch subdev\n"); goto out_dev; diff --git a/trunk/drivers/mfd/max8997.c b/trunk/drivers/mfd/max8997.c index f123517065ec..10b629c245b6 100644 --- a/trunk/drivers/mfd/max8997.c +++ b/trunk/drivers/mfd/max8997.c @@ -160,7 +160,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c, mfd_add_devices(max8997->dev, -1, max8997_devs, ARRAY_SIZE(max8997_devs), - NULL, 0, NULL); + NULL, 0); /* * TODO: enable others (flash, muic, rtc, battery, ...) and diff --git a/trunk/drivers/mfd/max8998.c b/trunk/drivers/mfd/max8998.c index d7218cc90945..6ef56d28c056 100644 --- a/trunk/drivers/mfd/max8998.c +++ b/trunk/drivers/mfd/max8998.c @@ -161,13 +161,13 @@ static int max8998_i2c_probe(struct i2c_client *i2c, switch (id->driver_data) { case TYPE_LP3974: ret = mfd_add_devices(max8998->dev, -1, - lp3974_devs, ARRAY_SIZE(lp3974_devs), - NULL, 0, NULL); + lp3974_devs, ARRAY_SIZE(lp3974_devs), + NULL, 0); break; case TYPE_MAX8998: ret = mfd_add_devices(max8998->dev, -1, - max8998_devs, ARRAY_SIZE(max8998_devs), - NULL, 0, NULL); + max8998_devs, ARRAY_SIZE(max8998_devs), + NULL, 0); break; default: ret = -EINVAL; diff --git a/trunk/drivers/mfd/mc13xxx-core.c b/trunk/drivers/mfd/mc13xxx-core.c index 1ec79b54bd2f..b801dc72f041 100644 --- a/trunk/drivers/mfd/mc13xxx-core.c +++ b/trunk/drivers/mfd/mc13xxx-core.c @@ -612,7 +612,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, if (!cell.name) return -ENOMEM; - return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL); + return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0); } static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) diff --git a/trunk/drivers/mfd/mfd-core.c b/trunk/drivers/mfd/mfd-core.c index f8b77711ad2d..0c3a01cde2f7 100644 --- a/trunk/drivers/mfd/mfd-core.c +++ b/trunk/drivers/mfd/mfd-core.c @@ -74,11 +74,12 @@ static int mfd_platform_add_cell(struct platform_device *pdev, static int mfd_add_device(struct device *parent, int id, const struct mfd_cell *cell, struct resource *mem_base, - int irq_base, struct irq_domain *domain) + int irq_base) { struct resource *res; struct platform_device *pdev; struct device_node *np = NULL; + struct irq_domain *domain = NULL; int ret = -ENOMEM; int r; @@ -96,6 +97,7 @@ static int mfd_add_device(struct device *parent, int id, for_each_child_of_node(parent->of_node, np) { if (of_device_is_compatible(np, cell->of_compatible)) { pdev->dev.of_node = np; + domain = irq_find_host(parent->of_node); break; } } @@ -175,7 +177,7 @@ static int mfd_add_device(struct device *parent, int id, int mfd_add_devices(struct device *parent, int id, struct mfd_cell *cells, int n_devs, struct resource *mem_base, - int irq_base, struct irq_domain *domain) + int irq_base) { int i; int ret = 0; @@ -189,8 +191,7 @@ int mfd_add_devices(struct device *parent, int id, for (i = 0; i < n_devs; i++) { atomic_set(&cnts[i], 0); cells[i].usage_count = &cnts[i]; - ret = mfd_add_device(parent, id, cells + i, mem_base, - irq_base, domain); + ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base); if (ret) break; } @@ -246,8 +247,7 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) for (i = 0; i < n_clones; i++) { cell_entry.name = clones[i]; /* don't give up if a single call fails; just report error */ - if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0, - NULL)) + if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0)) dev_err(dev, "failed to create platform device '%s'\n", clones[i]); } diff --git a/trunk/drivers/mfd/palmas.c b/trunk/drivers/mfd/palmas.c index a345f9bb7b47..c4a69f193a1d 100644 --- a/trunk/drivers/mfd/palmas.c +++ b/trunk/drivers/mfd/palmas.c @@ -453,8 +453,7 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(palmas->dev, -1, children, ARRAY_SIZE(palmas_children), - NULL, regmap_irq_chip_get_base(palmas->irq_data), - NULL); + NULL, regmap_irq_chip_get_base(palmas->irq_data)); kfree(children); if (ret < 0) diff --git a/trunk/drivers/mfd/rc5t583.c b/trunk/drivers/mfd/rc5t583.c index 3a8fa88567b1..cdc1df7fa0e9 100644 --- a/trunk/drivers/mfd/rc5t583.c +++ b/trunk/drivers/mfd/rc5t583.c @@ -289,7 +289,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c, } ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs, - ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL); + ARRAY_SIZE(rc5t583_subdevs), NULL, 0); if (ret) { dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret); goto err_add_devs; diff --git a/trunk/drivers/mfd/rdc321x-southbridge.c b/trunk/drivers/mfd/rdc321x-southbridge.c index 0f70dce61160..685d61e431ad 100644 --- a/trunk/drivers/mfd/rdc321x-southbridge.c +++ b/trunk/drivers/mfd/rdc321x-southbridge.c @@ -87,8 +87,7 @@ static int __devinit rdc321x_sb_probe(struct pci_dev *pdev, rdc321x_wdt_pdata.sb_pdev = pdev; return mfd_add_devices(&pdev->dev, -1, - rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), - NULL, 0, NULL); + rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), NULL, 0); } static void __devexit rdc321x_sb_remove(struct pci_dev *pdev) diff --git a/trunk/drivers/mfd/sec-core.c b/trunk/drivers/mfd/sec-core.c index 49d361a618d0..2988efde11eb 100644 --- a/trunk/drivers/mfd/sec-core.c +++ b/trunk/drivers/mfd/sec-core.c @@ -141,19 +141,19 @@ static int sec_pmic_probe(struct i2c_client *i2c, switch (sec_pmic->device_type) { case S5M8751X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs, - ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL); + ARRAY_SIZE(s5m8751_devs), NULL, 0); break; case S5M8763X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs, - ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL); + ARRAY_SIZE(s5m8763_devs), NULL, 0); break; case S5M8767X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, - ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); + ARRAY_SIZE(s5m8767_devs), NULL, 0); break; case S2MPS11X: ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, - ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); + ARRAY_SIZE(s2mps11_devs), NULL, 0); break; default: /* If this happens the probe function is problem */ diff --git a/trunk/drivers/mfd/sta2x11-mfd.c b/trunk/drivers/mfd/sta2x11-mfd.c index d35da6820bea..d31fed07aefb 100644 --- a/trunk/drivers/mfd/sta2x11-mfd.c +++ b/trunk/drivers/mfd/sta2x11-mfd.c @@ -407,7 +407,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev, sta2x11_mfd_bar0, ARRAY_SIZE(sta2x11_mfd_bar0), &pdev->resource[0], - 0, NULL); + 0); if (err) { dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err); goto err_disable; @@ -417,7 +417,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev, sta2x11_mfd_bar1, ARRAY_SIZE(sta2x11_mfd_bar1), &pdev->resource[1], - 0, NULL); + 0); if (err) { dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err); goto err_disable; diff --git a/trunk/drivers/mfd/stmpe.c b/trunk/drivers/mfd/stmpe.c index c94f521f392c..2dd8d49cb30b 100644 --- a/trunk/drivers/mfd/stmpe.c +++ b/trunk/drivers/mfd/stmpe.c @@ -962,7 +962,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe, struct mfd_cell *cell, int irq) { return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, - NULL, stmpe->irq_base + irq, NULL); + NULL, stmpe->irq_base + irq); } static int __devinit stmpe_devices_init(struct stmpe *stmpe) diff --git a/trunk/drivers/mfd/t7l66xb.c b/trunk/drivers/mfd/t7l66xb.c index b32940ec9034..2d9e8799e733 100644 --- a/trunk/drivers/mfd/t7l66xb.c +++ b/trunk/drivers/mfd/t7l66xb.c @@ -388,7 +388,7 @@ static int t7l66xb_probe(struct platform_device *dev) ret = mfd_add_devices(&dev->dev, dev->id, t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), - iomem, t7l66xb->irq_base, NULL); + iomem, t7l66xb->irq_base); if (!ret) return 0; diff --git a/trunk/drivers/mfd/tc3589x.c b/trunk/drivers/mfd/tc3589x.c index b56ba6b43294..048bf0532a09 100644 --- a/trunk/drivers/mfd/tc3589x.c +++ b/trunk/drivers/mfd/tc3589x.c @@ -262,8 +262,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_GPIO) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, - ARRAY_SIZE(tc3589x_dev_gpio), NULL, - tc3589x->irq_base, NULL); + ARRAY_SIZE(tc3589x_dev_gpio), NULL, + tc3589x->irq_base); if (ret) { dev_err(tc3589x->dev, "failed to add gpio child\n"); return ret; @@ -273,8 +273,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_KEYPAD) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, - ARRAY_SIZE(tc3589x_dev_keypad), NULL, - tc3589x->irq_base, NULL); + ARRAY_SIZE(tc3589x_dev_keypad), NULL, + tc3589x->irq_base); if (ret) { dev_err(tc3589x->dev, "failed to keypad child\n"); return ret; diff --git a/trunk/drivers/mfd/tc6387xb.c b/trunk/drivers/mfd/tc6387xb.c index 413c891102f8..d20a284ad4ba 100644 --- a/trunk/drivers/mfd/tc6387xb.c +++ b/trunk/drivers/mfd/tc6387xb.c @@ -192,7 +192,7 @@ static int __devinit tc6387xb_probe(struct platform_device *dev) printk(KERN_INFO "Toshiba tc6387xb initialised\n"); ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells, - ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL); + ARRAY_SIZE(tc6387xb_cells), iomem, irq); if (!ret) return 0; diff --git a/trunk/drivers/mfd/tc6393xb.c b/trunk/drivers/mfd/tc6393xb.c index dcab026fcbb2..9612264f0e6d 100644 --- a/trunk/drivers/mfd/tc6393xb.c +++ b/trunk/drivers/mfd/tc6393xb.c @@ -700,8 +700,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data); ret = mfd_add_devices(&dev->dev, dev->id, - tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), - iomem, tcpd->irq_base, NULL); + tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), + iomem, tcpd->irq_base); if (!ret) return 0; diff --git a/trunk/drivers/mfd/ti-ssp.c b/trunk/drivers/mfd/ti-ssp.c index 7c3675a74f93..4fb0e6c8e8fe 100644 --- a/trunk/drivers/mfd/ti-ssp.c +++ b/trunk/drivers/mfd/ti-ssp.c @@ -412,7 +412,7 @@ static int __devinit ti_ssp_probe(struct platform_device *pdev) cells[id].data_size = data->pdata_size; } - error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL); + error = mfd_add_devices(dev, 0, cells, 2, NULL, 0); if (error < 0) { dev_err(dev, "cannot add mfd cells\n"); goto error_enable; diff --git a/trunk/drivers/mfd/timberdale.c b/trunk/drivers/mfd/timberdale.c index cccc626c83c8..a447f4ec11fb 100644 --- a/trunk/drivers/mfd/timberdale.c +++ b/trunk/drivers/mfd/timberdale.c @@ -757,25 +757,25 @@ static int __devinit timb_probe(struct pci_dev *dev, err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg0, ARRAY_SIZE(timberdale_cells_bar0_cfg0), - &dev->resource[0], msix_entries[0].vector, NULL); + &dev->resource[0], msix_entries[0].vector); break; case TIMB_HW_VER1: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg1, ARRAY_SIZE(timberdale_cells_bar0_cfg1), - &dev->resource[0], msix_entries[0].vector, NULL); + &dev->resource[0], msix_entries[0].vector); break; case TIMB_HW_VER2: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg2, ARRAY_SIZE(timberdale_cells_bar0_cfg2), - &dev->resource[0], msix_entries[0].vector, NULL); + &dev->resource[0], msix_entries[0].vector); break; case TIMB_HW_VER3: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg3, ARRAY_SIZE(timberdale_cells_bar0_cfg3), - &dev->resource[0], msix_entries[0].vector, NULL); + &dev->resource[0], msix_entries[0].vector); break; default: dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n", @@ -792,7 +792,7 @@ static int __devinit timb_probe(struct pci_dev *dev, err = mfd_add_devices(&dev->dev, 0, timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1), - &dev->resource[1], msix_entries[0].vector, NULL); + &dev->resource[1], msix_entries[0].vector); if (err) { dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); goto err_mfd2; @@ -803,7 +803,7 @@ static int __devinit timb_probe(struct pci_dev *dev, ((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) { err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2, ARRAY_SIZE(timberdale_cells_bar2), - &dev->resource[2], msix_entries[0].vector, NULL); + &dev->resource[2], msix_entries[0].vector); if (err) { dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); goto err_mfd2; diff --git a/trunk/drivers/mfd/tps6105x.c b/trunk/drivers/mfd/tps6105x.c index 14051bdc714b..a293b978e27c 100644 --- a/trunk/drivers/mfd/tps6105x.c +++ b/trunk/drivers/mfd/tps6105x.c @@ -188,7 +188,7 @@ static int __devinit tps6105x_probe(struct i2c_client *client, } ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, - ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL); + ARRAY_SIZE(tps6105x_cells), NULL, 0); if (ret) goto fail; diff --git a/trunk/drivers/mfd/tps6507x.c b/trunk/drivers/mfd/tps6507x.c index 1b203499c744..33ba7723c967 100644 --- a/trunk/drivers/mfd/tps6507x.c +++ b/trunk/drivers/mfd/tps6507x.c @@ -100,7 +100,7 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(tps6507x->dev, -1, tps6507x_devs, ARRAY_SIZE(tps6507x_devs), - NULL, 0, NULL); + NULL, 0); if (ret < 0) goto err; diff --git a/trunk/drivers/mfd/tps65090.c b/trunk/drivers/mfd/tps65090.c index 50fd87c87a1c..80e24f4b47bf 100644 --- a/trunk/drivers/mfd/tps65090.c +++ b/trunk/drivers/mfd/tps65090.c @@ -292,7 +292,7 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(tps65090->dev, -1, tps65090s, - ARRAY_SIZE(tps65090s), NULL, 0, NULL); + ARRAY_SIZE(tps65090s), NULL, 0); if (ret) { dev_err(&client->dev, "add mfd devices failed with err: %d\n", ret); diff --git a/trunk/drivers/mfd/tps65217.c b/trunk/drivers/mfd/tps65217.c index a95e9421b735..61c097a98f5d 100644 --- a/trunk/drivers/mfd/tps65217.c +++ b/trunk/drivers/mfd/tps65217.c @@ -24,18 +24,11 @@ #include #include #include -#include -#include +#include #include #include -static struct mfd_cell tps65217s[] = { - { - .name = "tps65217-pmic", - }, -}; - /** * tps65217_reg_read: Read a single tps65217 register. * @@ -140,48 +133,83 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, } EXPORT_SYMBOL_GPL(tps65217_clear_bits); +#ifdef CONFIG_OF +static struct of_regulator_match reg_matches[] = { + { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, + { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, + { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, + { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, + { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, + { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, + { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, +}; + +static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) +{ + struct device_node *node = client->dev.of_node; + struct tps65217_board *pdata; + struct device_node *regs; + int count = ARRAY_SIZE(reg_matches); + int ret, i; + + regs = of_find_node_by_name(node, "regulators"); + if (!regs) + return NULL; + + ret = of_regulator_match(&client->dev, regs, reg_matches, count); + of_node_put(regs); + if ((ret < 0) || (ret > count)) + return NULL; + + count = ret; + pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + for (i = 0; i < count; i++) { + if (!reg_matches[i].init_data || !reg_matches[i].of_node) + continue; + + pdata->tps65217_init_data[i] = reg_matches[i].init_data; + pdata->of_node[i] = reg_matches[i].of_node; + } + + return pdata; +} + +static struct of_device_id tps65217_of_match[] = { + { .compatible = "ti,tps65217", }, + { }, +}; +#else +static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) +{ + return NULL; +} +#endif + static struct regmap_config tps65217_regmap_config = { .reg_bits = 8, .val_bits = 8, }; -static const struct of_device_id tps65217_of_match[] = { - { .compatible = "ti,tps65217", .data = (void *)TPS65217 }, - { /* sentinel */ }, -}; - static int __devinit tps65217_probe(struct i2c_client *client, const struct i2c_device_id *ids) { struct tps65217 *tps; + struct regulator_init_data *reg_data; + struct tps65217_board *pdata = client->dev.platform_data; + int i, ret; unsigned int version; - unsigned int chip_id = ids->driver_data; - const struct of_device_id *match; - int ret; - if (client->dev.of_node) { - match = of_match_device(tps65217_of_match, &client->dev); - if (!match) { - dev_err(&client->dev, - "Failed to find matching dt id\n"); - return -EINVAL; - } - chip_id = (unsigned int)match->data; - } - - if (!chip_id) { - dev_err(&client->dev, "id is null.\n"); - return -ENODEV; - } + if (!pdata && client->dev.of_node) + pdata = tps65217_parse_dt(client); tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; - i2c_set_clientdata(client, tps); - tps->dev = &client->dev; - tps->id = chip_id; - + tps->pdata = pdata; tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); @@ -190,12 +218,8 @@ static int __devinit tps65217_probe(struct i2c_client *client, return ret; } - ret = mfd_add_devices(tps->dev, -1, tps65217s, - ARRAY_SIZE(tps65217s), NULL, 0, NULL); - if (ret < 0) { - dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); - return ret; - } + i2c_set_clientdata(client, tps); + tps->dev = &client->dev; ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version); if (ret < 0) { @@ -208,21 +232,41 @@ static int __devinit tps65217_probe(struct i2c_client *client, (version & TPS65217_CHIPID_CHIP_MASK) >> 4, version & TPS65217_CHIPID_REV_MASK); + for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { + struct platform_device *pdev; + + pdev = platform_device_alloc("tps65217-pmic", i); + if (!pdev) { + dev_err(tps->dev, "Cannot create regulator %d\n", i); + continue; + } + + pdev->dev.parent = tps->dev; + pdev->dev.of_node = pdata->of_node[i]; + reg_data = pdata->tps65217_init_data[i]; + platform_device_add_data(pdev, reg_data, sizeof(*reg_data)); + tps->regulator_pdev[i] = pdev; + + platform_device_add(pdev); + } + return 0; } static int __devexit tps65217_remove(struct i2c_client *client) { struct tps65217 *tps = i2c_get_clientdata(client); + int i; - mfd_remove_devices(tps->dev); + for (i = 0; i < TPS65217_NUM_REGULATOR; i++) + platform_device_unregister(tps->regulator_pdev[i]); return 0; } static const struct i2c_device_id tps65217_id_table[] = { - {"tps65217", TPS65217}, - { /* sentinel */ } + {"tps65217", 0xF0}, + {/* end of list */} }; MODULE_DEVICE_TABLE(i2c, tps65217_id_table); diff --git a/trunk/drivers/mfd/tps6586x.c b/trunk/drivers/mfd/tps6586x.c index 5f58370ccf55..353c34812120 100644 --- a/trunk/drivers/mfd/tps6586x.c +++ b/trunk/drivers/mfd/tps6586x.c @@ -493,8 +493,7 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(tps6586x->dev, -1, - tps6586x_cell, ARRAY_SIZE(tps6586x_cell), - NULL, 0, NULL); + tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0); if (ret < 0) { dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret); goto err_mfd_add; diff --git a/trunk/drivers/mfd/tps65910.c b/trunk/drivers/mfd/tps65910.c index d3ce4d569deb..1c563792c777 100644 --- a/trunk/drivers/mfd/tps65910.c +++ b/trunk/drivers/mfd/tps65910.c @@ -254,7 +254,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(tps65910->dev, -1, tps65910s, ARRAY_SIZE(tps65910s), - NULL, 0, NULL); + NULL, 0); if (ret < 0) { dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret); return ret; diff --git a/trunk/drivers/mfd/tps65912-core.c b/trunk/drivers/mfd/tps65912-core.c index 4658b5bdcd84..74fd8cb5f372 100644 --- a/trunk/drivers/mfd/tps65912-core.c +++ b/trunk/drivers/mfd/tps65912-core.c @@ -146,7 +146,7 @@ int tps65912_device_init(struct tps65912 *tps65912) ret = mfd_add_devices(tps65912->dev, -1, tps65912s, ARRAY_SIZE(tps65912s), - NULL, 0, NULL); + NULL, 0); if (ret < 0) goto err; diff --git a/trunk/drivers/mfd/twl4030-audio.c b/trunk/drivers/mfd/twl4030-audio.c index 77c9acb14583..838ce4eb444e 100644 --- a/trunk/drivers/mfd/twl4030-audio.c +++ b/trunk/drivers/mfd/twl4030-audio.c @@ -223,7 +223,7 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev) if (childs) ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells, - childs, NULL, 0, NULL); + childs, NULL, 0); else { dev_err(&pdev->dev, "No platform data found for childs\n"); ret = -ENODEV; diff --git a/trunk/drivers/mfd/twl6040-core.c b/trunk/drivers/mfd/twl6040-core.c index 3dca5c195a20..b0fad0ffca56 100644 --- a/trunk/drivers/mfd/twl6040-core.c +++ b/trunk/drivers/mfd/twl6040-core.c @@ -632,7 +632,7 @@ static int __devinit twl6040_probe(struct i2c_client *client, } ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, - NULL, 0, NULL); + NULL, 0); if (ret) goto mfd_err; diff --git a/trunk/drivers/mfd/vx855.c b/trunk/drivers/mfd/vx855.c index b9a636d44c7f..872aff21e4be 100644 --- a/trunk/drivers/mfd/vx855.c +++ b/trunk/drivers/mfd/vx855.c @@ -102,7 +102,7 @@ static __devinit int vx855_probe(struct pci_dev *pdev, vx855_gpio_resources[1].end = vx855_gpio_resources[1].start + 3; ret = mfd_add_devices(&pdev->dev, -1, vx855_cells, ARRAY_SIZE(vx855_cells), - NULL, 0, NULL); + NULL, 0); /* we always return -ENODEV here in order to enable other * drivers like old, not-yet-platform_device ported i2c-viapro */ diff --git a/trunk/drivers/mfd/wl1273-core.c b/trunk/drivers/mfd/wl1273-core.c index 86e0e4309fc2..f39b756df561 100644 --- a/trunk/drivers/mfd/wl1273-core.c +++ b/trunk/drivers/mfd/wl1273-core.c @@ -241,7 +241,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, __func__, children); r = mfd_add_devices(&client->dev, -1, core->cells, - children, NULL, 0, NULL); + children, NULL, 0); if (r) goto err; diff --git a/trunk/drivers/mfd/wm831x-core.c b/trunk/drivers/mfd/wm831x-core.c index 301731035940..946698fd2dc6 100644 --- a/trunk/drivers/mfd/wm831x-core.c +++ b/trunk/drivers/mfd/wm831x-core.c @@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8310: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8310_devs, ARRAY_SIZE(wm8310_devs), - NULL, 0, NULL); + NULL, 0); break; case WM8311: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8311_devs, ARRAY_SIZE(wm8311_devs), - NULL, 0, NULL); + NULL, 0); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, 0, NULL); + NULL, 0); break; case WM8312: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8312_devs, ARRAY_SIZE(wm8312_devs), - NULL, 0, NULL); + NULL, 0); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, 0, NULL); + NULL, 0); break; case WM8320: @@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8326: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8320_devs, ARRAY_SIZE(wm8320_devs), - NULL, 0, NULL); + NULL, 0); break; default: @@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) if (ret & WM831X_XTAL_ENA) { ret = mfd_add_devices(wm831x->dev, wm831x_num, rtc_devs, ARRAY_SIZE(rtc_devs), - NULL, 0, NULL); + NULL, 0); if (ret != 0) { dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret); goto err_irq; @@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) /* Treat errors as non-critical */ ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs, ARRAY_SIZE(backlight_devs), NULL, - 0, NULL); + 0); if (ret < 0) dev_err(wm831x->dev, "Failed to add backlight: %d\n", ret); diff --git a/trunk/drivers/mfd/wm8400-core.c b/trunk/drivers/mfd/wm8400-core.c index 639ca359242f..4b7d378551d5 100644 --- a/trunk/drivers/mfd/wm8400-core.c +++ b/trunk/drivers/mfd/wm8400-core.c @@ -70,7 +70,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400) .pdata_size = sizeof(*wm8400), }; - return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL); + return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); } /* diff --git a/trunk/drivers/mfd/wm8994-core.c b/trunk/drivers/mfd/wm8994-core.c index 2febf88cfce8..eec74aa55fdf 100644 --- a/trunk/drivers/mfd/wm8994-core.c +++ b/trunk/drivers/mfd/wm8994-core.c @@ -414,7 +414,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) ret = mfd_add_devices(wm8994->dev, -1, wm8994_regulator_devs, ARRAY_SIZE(wm8994_regulator_devs), - NULL, 0, NULL); + NULL, 0); if (ret != 0) { dev_err(wm8994->dev, "Failed to add children: %d\n", ret); goto err; @@ -648,7 +648,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) ret = mfd_add_devices(wm8994->dev, -1, wm8994_devs, ARRAY_SIZE(wm8994_devs), - NULL, 0, NULL); + NULL, 0); if (ret != 0) { dev_err(wm8994->dev, "Failed to add children: %d\n", ret); goto err_irq; diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index ed5041e96b2d..707ab7bd4ea5 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -149,19 +149,6 @@ config MACVTAP To compile this driver as a module, choose M here: the module will be called macvtap. -config VXLAN - tristate "Virtual eXtensible Local Area Network (VXLAN)" - depends on EXPERIMENTAL - ---help--- - This allows one to create vxlan virtual interfaces that provide - Layer 2 Networks over Layer 3 Networks. VXLAN is often used - to tunnel virtual network infrastructure in virtualized environments. - For more information see: - http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-02 - - To compile this driver as a module, choose M here: the module - will be called vxlan. - config NETCONSOLE tristate "Network console logging support" ---help--- diff --git a/trunk/drivers/net/Makefile b/trunk/drivers/net/Makefile index 335db78fd987..b682a1de7be8 100644 --- a/trunk/drivers/net/Makefile +++ b/trunk/drivers/net/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_NET_TEAM) += team/ obj-$(CONFIG_TUN) += tun.o obj-$(CONFIG_VETH) += veth.o obj-$(CONFIG_VIRTIO_NET) += virtio_net.o -obj-$(CONFIG_VXLAN) += vxlan.o # # Networking Drivers diff --git a/trunk/drivers/net/can/c_can/c_can.c b/trunk/drivers/net/can/c_can/c_can.c index e5180dfddba5..4c538e388655 100644 --- a/trunk/drivers/net/can/c_can/c_can.c +++ b/trunk/drivers/net/can/c_can/c_can.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -46,9 +45,6 @@ #define IF_ENUM_REG_LEN 11 #define C_CAN_IFACE(reg, iface) (C_CAN_IF1_##reg + (iface) * IF_ENUM_REG_LEN) -/* control extension register D_CAN specific */ -#define CONTROL_EX_PDR BIT(8) - /* control register */ #define CONTROL_TEST BIT(7) #define CONTROL_CCE BIT(6) @@ -68,7 +64,6 @@ #define TEST_BASIC BIT(2) /* status register */ -#define STATUS_PDA BIT(10) #define STATUS_BOFF BIT(7) #define STATUS_EWARN BIT(6) #define STATUS_EPASS BIT(5) @@ -168,9 +163,6 @@ /* minimum timeout for checking BUSY status */ #define MIN_TIMEOUT_VALUE 6 -/* Wait for ~1 sec for INIT bit */ -#define INIT_WAIT_MS 1000 - /* napi related */ #define C_CAN_NAPI_WEIGHT C_CAN_MSG_OBJ_RX_NUM @@ -209,30 +201,6 @@ static const struct can_bittiming_const c_can_bittiming_const = { .brp_inc = 1, }; -static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv) -{ - if (priv->device) - pm_runtime_enable(priv->device); -} - -static inline void c_can_pm_runtime_disable(const struct c_can_priv *priv) -{ - if (priv->device) - pm_runtime_disable(priv->device); -} - -static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv) -{ - if (priv->device) - pm_runtime_get_sync(priv->device); -} - -static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv) -{ - if (priv->device) - pm_runtime_put_sync(priv->device); -} - static inline int get_tx_next_msg_obj(const struct c_can_priv *priv) { return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) + @@ -705,15 +673,11 @@ static int c_can_get_berr_counter(const struct net_device *dev, unsigned int reg_err_counter; struct c_can_priv *priv = netdev_priv(dev); - c_can_pm_runtime_get_sync(priv); - reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >> ERR_CNT_REC_SHIFT; bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK; - c_can_pm_runtime_put_sync(priv); - return 0; } @@ -1089,13 +1053,11 @@ static int c_can_open(struct net_device *dev) int err; struct c_can_priv *priv = netdev_priv(dev); - c_can_pm_runtime_get_sync(priv); - /* open the can device */ err = open_candev(dev); if (err) { netdev_err(dev, "failed to open can device\n"); - goto exit_open_fail; + return err; } /* register interrupt handler */ @@ -1117,8 +1079,6 @@ static int c_can_open(struct net_device *dev) exit_irq_fail: close_candev(dev); -exit_open_fail: - c_can_pm_runtime_put_sync(priv); return err; } @@ -1131,7 +1091,6 @@ static int c_can_close(struct net_device *dev) c_can_stop(dev); free_irq(dev->irq, dev); close_candev(dev); - c_can_pm_runtime_put_sync(priv); return 0; } @@ -1160,77 +1119,6 @@ struct net_device *alloc_c_can_dev(void) } EXPORT_SYMBOL_GPL(alloc_c_can_dev); -#ifdef CONFIG_PM -int c_can_power_down(struct net_device *dev) -{ - u32 val; - unsigned long time_out; - struct c_can_priv *priv = netdev_priv(dev); - - if (!(dev->flags & IFF_UP)) - return 0; - - WARN_ON(priv->type != BOSCH_D_CAN); - - /* set PDR value so the device goes to power down mode */ - val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); - val |= CONTROL_EX_PDR; - priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); - - /* Wait for the PDA bit to get set */ - time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); - while (!(priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && - time_after(time_out, jiffies)) - cpu_relax(); - - if (time_after(jiffies, time_out)) - return -ETIMEDOUT; - - c_can_stop(dev); - - c_can_pm_runtime_put_sync(priv); - - return 0; -} -EXPORT_SYMBOL_GPL(c_can_power_down); - -int c_can_power_up(struct net_device *dev) -{ - u32 val; - unsigned long time_out; - struct c_can_priv *priv = netdev_priv(dev); - - if (!(dev->flags & IFF_UP)) - return 0; - - WARN_ON(priv->type != BOSCH_D_CAN); - - c_can_pm_runtime_get_sync(priv); - - /* Clear PDR and INIT bits */ - val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); - val &= ~CONTROL_EX_PDR; - priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); - val = priv->read_reg(priv, C_CAN_CTRL_REG); - val &= ~CONTROL_INIT; - priv->write_reg(priv, C_CAN_CTRL_REG, val); - - /* Wait for the PDA bit to get clear */ - time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); - while ((priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && - time_after(time_out, jiffies)) - cpu_relax(); - - if (time_after(jiffies, time_out)) - return -ETIMEDOUT; - - c_can_start(dev); - - return 0; -} -EXPORT_SYMBOL_GPL(c_can_power_up); -#endif - void free_c_can_dev(struct net_device *dev) { free_candev(dev); @@ -1245,19 +1133,10 @@ static const struct net_device_ops c_can_netdev_ops = { int register_c_can_dev(struct net_device *dev) { - struct c_can_priv *priv = netdev_priv(dev); - int err; - - c_can_pm_runtime_enable(priv); - dev->flags |= IFF_ECHO; /* we support local echo */ dev->netdev_ops = &c_can_netdev_ops; - err = register_candev(dev); - if (err) - c_can_pm_runtime_disable(priv); - - return err; + return register_candev(dev); } EXPORT_SYMBOL_GPL(register_c_can_dev); @@ -1265,9 +1144,10 @@ void unregister_c_can_dev(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); - unregister_candev(dev); + /* disable all interrupts */ + c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); - c_can_pm_runtime_disable(priv); + unregister_candev(dev); } EXPORT_SYMBOL_GPL(unregister_c_can_dev); diff --git a/trunk/drivers/net/can/c_can/c_can.h b/trunk/drivers/net/can/c_can/c_can.h index e5ed41dafa1b..01a7049ab990 100644 --- a/trunk/drivers/net/can/c_can/c_can.h +++ b/trunk/drivers/net/can/c_can/c_can.h @@ -24,7 +24,6 @@ enum reg { C_CAN_CTRL_REG = 0, - C_CAN_CTRL_EX_REG, C_CAN_STS_REG, C_CAN_ERR_CNT_REG, C_CAN_BTR_REG, @@ -105,7 +104,6 @@ static const u16 reg_map_c_can[] = { static const u16 reg_map_d_can[] = { [C_CAN_CTRL_REG] = 0x00, - [C_CAN_CTRL_EX_REG] = 0x02, [C_CAN_STS_REG] = 0x04, [C_CAN_ERR_CNT_REG] = 0x08, [C_CAN_BTR_REG] = 0x0C, @@ -145,9 +143,8 @@ static const u16 reg_map_d_can[] = { }; enum c_can_dev_id { - BOSCH_C_CAN_PLATFORM, - BOSCH_C_CAN, - BOSCH_D_CAN, + C_CAN_DEVTYPE, + D_CAN_DEVTYPE, }; /* c_can private data structure */ @@ -155,7 +152,6 @@ struct c_can_priv { struct can_priv can; /* must be the first member */ struct napi_struct napi; struct net_device *dev; - struct device *device; int tx_object; int current_status; int last_status; @@ -168,7 +164,6 @@ struct c_can_priv { unsigned int tx_echo; void *priv; /* for board-specific data */ u16 irqstatus; - enum c_can_dev_id type; }; struct net_device *alloc_c_can_dev(void); @@ -176,9 +171,4 @@ void free_c_can_dev(struct net_device *dev); int register_c_can_dev(struct net_device *dev); void unregister_c_can_dev(struct net_device *dev); -#ifdef CONFIG_PM -int c_can_power_up(struct net_device *dev); -int c_can_power_down(struct net_device *dev); -#endif - #endif /* C_CAN_H */ diff --git a/trunk/drivers/net/can/c_can/c_can_pci.c b/trunk/drivers/net/can/c_can/c_can_pci.c index 3d7830bcd2bf..1011146ea513 100644 --- a/trunk/drivers/net/can/c_can/c_can_pci.c +++ b/trunk/drivers/net/can/c_can/c_can_pci.c @@ -120,10 +120,10 @@ static int __devinit c_can_pci_probe(struct pci_dev *pdev, /* Configure CAN type */ switch (c_can_pci_data->type) { - case BOSCH_C_CAN: + case C_CAN_DEVTYPE: priv->regs = reg_map_c_can; break; - case BOSCH_D_CAN: + case D_CAN_DEVTYPE: priv->regs = reg_map_d_can; priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; break; @@ -192,7 +192,7 @@ static void __devexit c_can_pci_remove(struct pci_dev *pdev) } static struct c_can_pci_data c_can_sta2x11= { - .type = BOSCH_C_CAN, + .type = C_CAN_DEVTYPE, .reg_align = C_CAN_REG_ALIGN_32, .freq = 52000000, /* 52 Mhz */ }; diff --git a/trunk/drivers/net/can/c_can/c_can_platform.c b/trunk/drivers/net/can/c_can/c_can_platform.c index ee1416132aba..6ff7ad006c30 100644 --- a/trunk/drivers/net/can/c_can/c_can_platform.c +++ b/trunk/drivers/net/can/c_can/c_can_platform.c @@ -30,9 +30,6 @@ #include #include #include -#include -#include -#include #include @@ -68,58 +65,17 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv, writew(val, priv->base + 2 * priv->regs[index]); } -static struct platform_device_id c_can_id_table[] = { - [BOSCH_C_CAN_PLATFORM] = { - .name = KBUILD_MODNAME, - .driver_data = BOSCH_C_CAN, - }, - [BOSCH_C_CAN] = { - .name = "c_can", - .driver_data = BOSCH_C_CAN, - }, - [BOSCH_D_CAN] = { - .name = "d_can", - .driver_data = BOSCH_D_CAN, - }, { - } -}; - -static const struct of_device_id c_can_of_table[] = { - { .compatible = "bosch,c_can", .data = &c_can_id_table[BOSCH_C_CAN] }, - { .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] }, - { /* sentinel */ }, -}; - static int __devinit c_can_plat_probe(struct platform_device *pdev) { int ret; void __iomem *addr; struct net_device *dev; struct c_can_priv *priv; - const struct of_device_id *match; const struct platform_device_id *id; - struct pinctrl *pinctrl; struct resource *mem; int irq; struct clk *clk; - if (pdev->dev.of_node) { - match = of_match_device(c_can_of_table, &pdev->dev); - if (!match) { - dev_err(&pdev->dev, "Failed to find matching dt id\n"); - ret = -EINVAL; - goto exit; - } - id = match->data; - } else { - id = platform_get_device_id(pdev); - } - - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, - "failed to configure pins from driver\n"); - /* get the appropriate clk */ clk = clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { @@ -158,8 +114,9 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) } priv = netdev_priv(dev); + id = platform_get_device_id(pdev); switch (id->driver_data) { - case BOSCH_C_CAN: + case C_CAN_DEVTYPE: priv->regs = reg_map_c_can; switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) { case IORESOURCE_MEM_32BIT: @@ -173,7 +130,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) break; } break; - case BOSCH_D_CAN: + case D_CAN_DEVTYPE: priv->regs = reg_map_d_can; priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; priv->read_reg = c_can_plat_read_reg_aligned_to_16bit; @@ -186,10 +143,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) dev->irq = irq; priv->base = addr; - priv->device = &pdev->dev; priv->can.clock.freq = clk_get_rate(clk); priv->priv = clk; - priv->type = id->driver_data; platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); @@ -240,75 +195,27 @@ static int __devexit c_can_plat_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int c_can_suspend(struct platform_device *pdev, pm_message_t state) -{ - int ret; - struct net_device *ndev = platform_get_drvdata(pdev); - struct c_can_priv *priv = netdev_priv(ndev); - - if (priv->type != BOSCH_D_CAN) { - dev_warn(&pdev->dev, "Not supported\n"); - return 0; - } - - if (netif_running(ndev)) { - netif_stop_queue(ndev); - netif_device_detach(ndev); - } - - ret = c_can_power_down(ndev); - if (ret) { - netdev_err(ndev, "failed to enter power down mode\n"); - return ret; - } - - priv->can.state = CAN_STATE_SLEEPING; - - return 0; -} - -static int c_can_resume(struct platform_device *pdev) -{ - int ret; - struct net_device *ndev = platform_get_drvdata(pdev); - struct c_can_priv *priv = netdev_priv(ndev); - - if (priv->type != BOSCH_D_CAN) { - dev_warn(&pdev->dev, "Not supported\n"); - return 0; - } - - ret = c_can_power_up(ndev); - if (ret) { - netdev_err(ndev, "Still in power down mode\n"); - return ret; - } - - priv->can.state = CAN_STATE_ERROR_ACTIVE; - - if (netif_running(ndev)) { - netif_device_attach(ndev); - netif_start_queue(ndev); +static const struct platform_device_id c_can_id_table[] = { + { + .name = KBUILD_MODNAME, + .driver_data = C_CAN_DEVTYPE, + }, { + .name = "c_can", + .driver_data = C_CAN_DEVTYPE, + }, { + .name = "d_can", + .driver_data = D_CAN_DEVTYPE, + }, { } - - return 0; -} -#else -#define c_can_suspend NULL -#define c_can_resume NULL -#endif +}; static struct platform_driver c_can_plat_driver = { .driver = { .name = KBUILD_MODNAME, .owner = THIS_MODULE, - .of_match_table = of_match_ptr(c_can_of_table), }, .probe = c_can_plat_probe, .remove = __devexit_p(c_can_plat_remove), - .suspend = c_can_suspend, - .resume = c_can_resume, .id_table = c_can_id_table, }; diff --git a/trunk/drivers/net/can/flexcan.c b/trunk/drivers/net/can/flexcan.c index c78ecfca1e45..c5f143165f80 100644 --- a/trunk/drivers/net/can/flexcan.c +++ b/trunk/drivers/net/can/flexcan.c @@ -144,10 +144,6 @@ #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) -/* FLEXCAN hardware feature flags */ -#define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ -#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* Broken error state handling */ - /* Structure of the message buffer */ struct flexcan_mb { u32 can_ctrl; @@ -182,7 +178,7 @@ struct flexcan_regs { }; struct flexcan_devtype_data { - u32 features; /* hardware controller features */ + u32 hw_ver; /* hardware controller version */ }; struct flexcan_priv { @@ -201,11 +197,11 @@ struct flexcan_priv { }; static struct flexcan_devtype_data fsl_p1010_devtype_data = { - .features = FLEXCAN_HAS_BROKEN_ERR_STATE, + .hw_ver = 3, }; -static struct flexcan_devtype_data fsl_imx28_devtype_data; + static struct flexcan_devtype_data fsl_imx6q_devtype_data = { - .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE, + .hw_ver = 10, }; static const struct can_bittiming_const flexcan_bittiming_const = { @@ -745,19 +741,15 @@ static int flexcan_chip_start(struct net_device *dev) * enable tx and rx warning interrupt * enable bus off interrupt * (== FLEXCAN_CTRL_ERR_STATE) + * + * _note_: we enable the "error interrupt" + * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any + * warning or bus passive interrupts. */ reg_ctrl = flexcan_read(®s->ctrl); reg_ctrl &= ~FLEXCAN_CTRL_TSYN; reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | - FLEXCAN_CTRL_ERR_STATE; - /* - * enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK), - * on most Flexcan cores, too. Otherwise we don't get - * any error warning or passive interrupts. - */ - if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE || - priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) - reg_ctrl |= FLEXCAN_CTRL_ERR_MSK; + FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK; /* save for later use */ priv->reg_ctrl_default = reg_ctrl; @@ -780,7 +772,7 @@ static int flexcan_chip_start(struct net_device *dev) flexcan_write(0x0, ®s->rx14mask); flexcan_write(0x0, ®s->rx15mask); - if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) + if (priv->devtype_data->hw_ver >= 10) flexcan_write(0x0, ®s->rxfgmask); flexcan_transceiver_switch(priv, 1); @@ -962,7 +954,6 @@ static void __devexit unregister_flexcandev(struct net_device *dev) static const struct of_device_id flexcan_of_match[] = { { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, - { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, { /* sentinel */ }, }; diff --git a/trunk/drivers/net/can/janz-ican3.c b/trunk/drivers/net/can/janz-ican3.c index 7edadee487ba..98ee43819911 100644 --- a/trunk/drivers/net/can/janz-ican3.c +++ b/trunk/drivers/net/can/janz-ican3.c @@ -1391,6 +1391,7 @@ static irqreturn_t ican3_irq(int irq, void *dev_id) */ static int ican3_reset_module(struct ican3_dev *mod) { + u8 val = 1 << mod->num; unsigned long start; u8 runold, runnew; @@ -1404,7 +1405,8 @@ static int ican3_reset_module(struct ican3_dev *mod) runold = ioread8(mod->dpm + TARGET_RUNNING); /* reset the module */ - iowrite8(0x00, &mod->dpmctrl->hwreset); + iowrite8(val, &mod->ctrl->reset_assert); + iowrite8(val, &mod->ctrl->reset_deassert); /* wait until the module has finished resetting and is running */ start = jiffies; diff --git a/trunk/drivers/net/can/mscan/mpc5xxx_can.c b/trunk/drivers/net/can/mscan/mpc5xxx_can.c index 524ef96dc24d..06adf881ea24 100644 --- a/trunk/drivers/net/can/mscan/mpc5xxx_can.c +++ b/trunk/drivers/net/can/mscan/mpc5xxx_can.c @@ -181,7 +181,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (!clock_name || !strcmp(clock_name, "sys")) { sys_clk = clk_get(&ofdev->dev, "sys_clk"); - if (IS_ERR(sys_clk)) { + if (!sys_clk) { dev_err(&ofdev->dev, "couldn't get sys_clk\n"); goto exit_unmap; } @@ -204,7 +204,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (clocksrc < 0) { ref_clk = clk_get(&ofdev->dev, "ref_clk"); - if (IS_ERR(ref_clk)) { + if (!ref_clk) { dev_err(&ofdev->dev, "couldn't get ref_clk\n"); goto exit_unmap; } diff --git a/trunk/drivers/net/can/sja1000/sja1000.c b/trunk/drivers/net/can/sja1000/sja1000.c index 25011dbe1b96..4c4f33d482d2 100644 --- a/trunk/drivers/net/can/sja1000/sja1000.c +++ b/trunk/drivers/net/can/sja1000/sja1000.c @@ -156,13 +156,8 @@ static void set_normal_mode(struct net_device *dev) } /* set chip to normal mode */ - if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) - priv->write_reg(priv, REG_MOD, MOD_LOM); - else - priv->write_reg(priv, REG_MOD, 0x00); - + priv->write_reg(priv, REG_MOD, 0x00); udelay(10); - status = priv->read_reg(priv, REG_MOD); } @@ -315,10 +310,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb, can_put_echo_skb(skb, dev, 0); - if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) - sja1000_write_cmdreg(priv, CMD_TR | CMD_AT); - else - sja1000_write_cmdreg(priv, CMD_TR); + sja1000_write_cmdreg(priv, CMD_TR); return NETDEV_TX_OK; } @@ -513,18 +505,10 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) netdev_warn(dev, "wakeup interrupt\n"); if (isrc & IRQ_TI) { - /* transmission buffer released */ - if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT && - !(status & SR_TCS)) { - stats->tx_errors++; - can_free_echo_skb(dev, 0); - } else { - /* transmission complete */ - stats->tx_bytes += - priv->read_reg(priv, REG_FI) & 0xf; - stats->tx_packets++; - can_get_echo_skb(dev, 0); - } + /* transmission complete interrupt */ + stats->tx_bytes += priv->read_reg(priv, REG_FI) & 0xf; + stats->tx_packets++; + can_get_echo_skb(dev, 0); netif_wake_queue(dev); } if (isrc & IRQ_RI) { @@ -621,8 +605,7 @@ struct net_device *alloc_sja1000dev(int sizeof_priv) priv->can.do_set_mode = sja1000_set_mode; priv->can.do_get_berr_counter = sja1000_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | - CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_LISTENONLY | - CAN_CTRLMODE_ONE_SHOT; + CAN_CTRLMODE_BERR_REPORTING; spin_lock_init(&priv->cmdreg_lock); diff --git a/trunk/drivers/net/can/ti_hecc.c b/trunk/drivers/net/can/ti_hecc.c index 9ded21e79db5..527dbcf95335 100644 --- a/trunk/drivers/net/can/ti_hecc.c +++ b/trunk/drivers/net/can/ti_hecc.c @@ -984,12 +984,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(ndev); - unregister_candev(ndev); clk_disable(priv->clk); clk_put(priv->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(priv->base); release_mem_region(res->start, resource_size(res)); + unregister_candev(ndev); free_candev(ndev); platform_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/trunk/drivers/net/can/usb/peak_usb/pcan_usb_core.c index c4643c400d46..d2f91f737871 100644 --- a/trunk/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/trunk/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -53,7 +53,7 @@ static struct peak_usb_adapter *peak_usb_adapters_list[] = { * dump memory */ #define DUMP_WIDTH 16 -void pcan_dump_mem(char *prompt, void *p, int l) +void dump_mem(char *prompt, void *p, int l) { pr_info("%s dumping %s (%d bytes):\n", PCAN_USB_DRIVER_NAME, prompt ? prompt : "memory", l); @@ -203,9 +203,9 @@ static void peak_usb_read_bulk_callback(struct urb *urb) if (dev->state & PCAN_USB_STATE_STARTED) { err = dev->adapter->dev_decode_buf(dev, urb); if (err) - pcan_dump_mem("received usb message", - urb->transfer_buffer, - urb->transfer_buffer_length); + dump_mem("received usb message", + urb->transfer_buffer, + urb->transfer_buffer_length); } } diff --git a/trunk/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/trunk/drivers/net/can/usb/peak_usb/pcan_usb_core.h index c8e5e91d7cb5..4c775b620be2 100644 --- a/trunk/drivers/net/can/usb/peak_usb/pcan_usb_core.h +++ b/trunk/drivers/net/can/usb/peak_usb/pcan_usb_core.h @@ -131,7 +131,7 @@ struct peak_usb_device { struct peak_usb_device *next_siblings; }; -void pcan_dump_mem(char *prompt, void *p, int l); +void dump_mem(char *prompt, void *p, int l); /* common timestamp management */ void peak_usb_init_time_ref(struct peak_time_ref *time_ref, diff --git a/trunk/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/trunk/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index e1626d92511a..629c4ba5d49d 100644 --- a/trunk/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/trunk/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -292,8 +292,8 @@ static int pcan_usb_pro_wait_rsp(struct peak_usb_device *dev, if (!rec_len) { netdev_err(dev->netdev, "got unprocessed record in msg\n"); - pcan_dump_mem("rcvd rsp msg", pum->u.rec_buffer, - actual_length); + dump_mem("rcvd rsp msg", pum->u.rec_buffer, + actual_length); break; } @@ -756,8 +756,8 @@ static int pcan_usb_pro_decode_buf(struct peak_usb_device *dev, struct urb *urb) fail: if (err) - pcan_dump_mem("received msg", - urb->transfer_buffer, urb->actual_length); + dump_mem("received msg", + urb->transfer_buffer, urb->actual_length); return err; } diff --git a/trunk/drivers/net/ethernet/Kconfig b/trunk/drivers/net/ethernet/Kconfig index e4ff38949112..a11af5cc4844 100644 --- a/trunk/drivers/net/ethernet/Kconfig +++ b/trunk/drivers/net/ethernet/Kconfig @@ -89,6 +89,15 @@ source "drivers/net/ethernet/marvell/Kconfig" source "drivers/net/ethernet/mellanox/Kconfig" source "drivers/net/ethernet/micrel/Kconfig" source "drivers/net/ethernet/microchip/Kconfig" + +config MIPS_SIM_NET + tristate "MIPS simulator Network device" + depends on MIPS_SIM + ---help--- + The MIPSNET device is a simple Ethernet network device which is + emulated by the MIPS Simulator. + If you are not using a MIPSsim or are unsure, say N. + source "drivers/net/ethernet/myricom/Kconfig" config FEALNX diff --git a/trunk/drivers/net/ethernet/Makefile b/trunk/drivers/net/ethernet/Makefile index d4473072654a..878ad32b93f2 100644 --- a/trunk/drivers/net/ethernet/Makefile +++ b/trunk/drivers/net/ethernet/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/ obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/ obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/ obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/ +obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o obj-$(CONFIG_NET_VENDOR_MYRI) += myricom/ obj-$(CONFIG_FEALNX) += fealnx.o obj-$(CONFIG_NET_VENDOR_NATSEMI) += natsemi/ diff --git a/trunk/drivers/net/ethernet/broadcom/Kconfig b/trunk/drivers/net/ethernet/broadcom/Kconfig index 4bd416b72e65..f15e72e81ac4 100644 --- a/trunk/drivers/net/ethernet/broadcom/Kconfig +++ b/trunk/drivers/net/ethernet/broadcom/Kconfig @@ -101,7 +101,6 @@ config TIGON3 tristate "Broadcom Tigon3 support" depends on PCI select PHYLIB - select HWMON ---help--- This driver supports Broadcom Tigon3 based gigabit Ethernet cards. diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2.c b/trunk/drivers/net/ethernet/broadcom/bnx2.c index e48312f2305d..79cebd8525ce 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2.c @@ -8564,7 +8564,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; error: - pci_iounmap(pdev, bp->regview); + iounmap(bp->regview); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 38650843ca21..6d1a24acb77e 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -23,8 +23,8 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.78.00-0" -#define DRV_MODULE_RELDATE "2012/09/27" +#define DRV_MODULE_VERSION "1.72.51-0" +#define DRV_MODULE_RELDATE "2012/06/18" #define BNX2X_BC_VER 0x040200 #if defined(CONFIG_DCB) diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 30f04a389227..ca8048757c84 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -662,16 +662,14 @@ void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, struct bnx2x_fastpath *fp, struct bnx2x_eth_q_stats *qstats) { - /* Do nothing if no L4 csum validation was done. - * We do not check whether IP csum was validated. For IPv4 we assume - * that if the card got as far as validating the L4 csum, it also - * validated the IP csum. IPv6 has no IP csum. - */ + /* Do nothing if no IP/L4 csum validation was done */ + if (cqe->fast_path_cqe.status_flags & - ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) + (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | + ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) return; - /* If L4 validation was done, check if an error was found. */ + /* If both IP/L4 validation were done, check if an error was found. */ if (cqe->fast_path_cqe.type_error_flags & (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | @@ -3026,9 +3024,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) first_bd = tx_start_bd; tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; - SET_FLAG(tx_start_bd->general_data, - ETH_TX_START_BD_PARSE_NBDS, - 0); + SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_ETH_ADDR_TYPE, + mac_type); /* header nbd */ SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_HDR_NBDS, 1); @@ -3078,20 +3075,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) &pbd_e2->dst_mac_addr_lo, eth->h_dest); } - - SET_FLAG(pbd_e2_parsing_data, - ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE, mac_type); } else { - u16 global_data = 0; pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x; memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x)); /* Set PBD in checksum offload case */ if (xmit_type & XMIT_CSUM) hlen = bnx2x_set_pbd_csum(bp, skb, pbd_e1x, xmit_type); - SET_FLAG(global_data, - ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE, mac_type); - pbd_e1x->global_data |= cpu_to_le16(global_data); } /* Setup the data pointer of the first BD of the packet */ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 2245c3895409..8a73374e52a7 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c @@ -91,21 +91,25 @@ static void bnx2x_pfc_set(struct bnx2x *bp) /* * Rx COS configuration * Changing PFC RX configuration . - * In RX COS0 will always be configured to lossless and COS1 to lossy + * In RX COS0 will always be configured to lossy and COS1 to lossless */ for (i = 0 ; i < MAX_PFC_PRIORITIES ; i++) { pri_bit = 1 << i; - if (!(pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp))) + if (pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp)) val |= 1 << (i * 4); } pfc_params.pkt_priority_to_cos = val; /* RX COS0 */ - pfc_params.llfc_low_priority_classes = DCBX_PFC_PRI_PAUSE_MASK(bp); + pfc_params.llfc_low_priority_classes = 0; /* RX COS1 */ - pfc_params.llfc_high_priority_classes = 0; + pfc_params.llfc_high_priority_classes = DCBX_PFC_PRI_PAUSE_MASK(bp); + + /* BRB configuration */ + pfc_params.cos0_pauseable = false; + pfc_params.cos1_pauseable = true; bnx2x_acquire_phy_lock(bp); bp->link_params.feature_config_flags |= FEATURE_CONFIG_PFC_ENABLED; diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c65295dded39..f923125e1c20 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1607,7 +1607,7 @@ static int bnx2x_set_pauseparam(struct net_device *dev, return 0; } -static const char bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF][ETH_GSTRING_LEN] = { +static char *bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF] = { "register_test (offline) ", "memory_test (offline) ", "int_loopback_test (offline)", @@ -2040,6 +2040,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) u16 pkt_prod, bd_prod; struct sw_tx_bd *tx_buf; struct eth_tx_start_bd *tx_start_bd; + struct eth_tx_parse_bd_e1x *pbd_e1x = NULL; + struct eth_tx_parse_bd_e2 *pbd_e2 = NULL; dma_addr_t mapping; union eth_rx_cqe *cqe; u8 cqe_fp_flags, cqe_fp_type; @@ -2130,33 +2132,22 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb)); tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod); tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; + SET_FLAG(tx_start_bd->general_data, + ETH_TX_START_BD_ETH_ADDR_TYPE, + UNICAST_ADDRESS); SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_HDR_NBDS, 1); - SET_FLAG(tx_start_bd->general_data, - ETH_TX_START_BD_PARSE_NBDS, - 0); /* turn on parsing and get a BD */ bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); - if (CHIP_IS_E1x(bp)) { - u16 global_data = 0; - struct eth_tx_parse_bd_e1x *pbd_e1x = - &txdata->tx_desc_ring[bd_prod].parse_bd_e1x; - memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x)); - SET_FLAG(global_data, - ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE, UNICAST_ADDRESS); - pbd_e1x->global_data = cpu_to_le16(global_data); - } else { - u32 parsing_data = 0; - struct eth_tx_parse_bd_e2 *pbd_e2 = - &txdata->tx_desc_ring[bd_prod].parse_bd_e2; - memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2)); - SET_FLAG(parsing_data, - ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE, UNICAST_ADDRESS); - pbd_e2->parsing_data = cpu_to_le32(parsing_data); - } + pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x; + pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2; + + memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2)); + memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x)); + wmb(); txdata->tx_db.data.prod += 2; @@ -2545,7 +2536,7 @@ static int bnx2x_get_sset_count(struct net_device *dev, int stringset) static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { struct bnx2x *bp = netdev_priv(dev); - int i, j, k, start; + int i, j, k, offset, start; char queue_name[MAX_QUEUE_NAME_LEN+1]; switch (stringset) { @@ -2581,8 +2572,13 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) start = 0; else start = 4; - memcpy(buf, bnx2x_tests_str_arr + start, - ETH_GSTRING_LEN * BNX2X_NUM_TESTS(bp)); + for (i = 0, j = start; j < (start + BNX2X_NUM_TESTS(bp)); + i++, j++) { + offset = sprintf(buf+32*i, "%s", + bnx2x_tests_str_arr[j]); + *(buf+offset) = '\0'; + } + break; } } diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h index 620fe939ecfd..bbc66ced9c25 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h @@ -88,6 +88,9 @@ #define TSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[102].base) #define TSTORM_ASSERT_LIST_OFFSET(assertListEntry) \ (IRO[101].base + ((assertListEntry) * IRO[101].m1)) +#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[107].base) +#define TSTORM_COMMON_SAFC_WORKAROUND_TIMEOUT_10USEC_OFFSET \ + (IRO[108].base) #define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(pfId) \ (IRO[201].base + ((pfId) * IRO[201].m1)) #define TSTORM_FUNC_EN_OFFSET(funcId) \ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 18704929e642..c795cfc5a545 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h @@ -2789,8 +2789,8 @@ struct afex_stats { }; #define BCM_5710_FW_MAJOR_VERSION 7 -#define BCM_5710_FW_MINOR_VERSION 8 -#define BCM_5710_FW_REVISION_VERSION 2 +#define BCM_5710_FW_MINOR_VERSION 2 +#define BCM_5710_FW_REVISION_VERSION 51 #define BCM_5710_FW_ENGINEERING_VERSION 0 #define BCM_5710_FW_COMPILE_FLAGS 1 @@ -3912,8 +3912,10 @@ struct eth_rss_update_ramrod_data { #define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY_SHIFT 4 #define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY (0x1<<5) #define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY_SHIFT 5 -#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<7) -#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 7 +#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<6) +#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 6 +#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0 (0x1<<7) +#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0_SHIFT 7 u8 rss_result_mask; u8 rss_mode; __le32 __reserved2; @@ -4129,29 +4131,27 @@ struct eth_tx_start_bd { #define ETH_TX_START_BD_HDR_NBDS_SHIFT 0 #define ETH_TX_START_BD_FORCE_VLAN_MODE (0x1<<4) #define ETH_TX_START_BD_FORCE_VLAN_MODE_SHIFT 4 -#define ETH_TX_START_BD_PARSE_NBDS (0x3<<5) -#define ETH_TX_START_BD_PARSE_NBDS_SHIFT 5 -#define ETH_TX_START_BD_RESREVED (0x1<<7) -#define ETH_TX_START_BD_RESREVED_SHIFT 7 +#define ETH_TX_START_BD_RESREVED (0x1<<5) +#define ETH_TX_START_BD_RESREVED_SHIFT 5 +#define ETH_TX_START_BD_ETH_ADDR_TYPE (0x3<<6) +#define ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT 6 }; /* * Tx parsing BD structure for ETH E1/E1h */ struct eth_tx_parse_bd_e1x { - __le16 global_data; + u8 global_data; #define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W (0xF<<0) #define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT 0 -#define ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE (0x3<<4) -#define ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE_SHIFT 4 -#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<6) -#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 6 -#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<7) -#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 7 -#define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<8) -#define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 8 -#define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x7F<<9) -#define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 9 +#define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x1<<4) +#define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 4 +#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<5) +#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 5 +#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<6) +#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 6 +#define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<7) +#define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 7 u8 tcp_flags; #define ETH_TX_PARSE_BD_E1X_FIN_FLG (0x1<<0) #define ETH_TX_PARSE_BD_E1X_FIN_FLG_SHIFT 0 @@ -4170,6 +4170,7 @@ struct eth_tx_parse_bd_e1x { #define ETH_TX_PARSE_BD_E1X_CWR_FLG (0x1<<7) #define ETH_TX_PARSE_BD_E1X_CWR_FLG_SHIFT 7 u8 ip_hlen_w; + s8 reserved; __le16 total_hlen_w; __le16 tcp_pseudo_csum; __le16 lso_mss; @@ -4188,16 +4189,14 @@ struct eth_tx_parse_bd_e2 { __le16 src_mac_addr_mid; __le16 src_mac_addr_hi; __le32 parsing_data; -#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x7FF<<0) +#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x1FFF<<0) #define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0 -#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<11) -#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 11 -#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<15) -#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 15 -#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<16) -#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 16 -#define ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE (0x3<<30) -#define ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT 30 +#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<13) +#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 13 +#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<17) +#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 17 +#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<31) +#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 31 }; /* @@ -4965,8 +4964,7 @@ struct flow_control_configuration { * */ struct function_start_data { - u8 function_mode; - u8 reserved; + __le16 function_mode; __le16 sd_vlan_tag; __le16 vif_id; u8 path_id; diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h index c8f10f0e8a0d..559c396d45cc 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h @@ -566,7 +566,7 @@ static const struct { u32 e2; /* 57712 */ u32 e3; /* 578xx */ } reg_mask; /* Register mask (all valid bits) */ - char name[8]; /* Block's longest name is 7 characters long + char name[7]; /* Block's longest name is 6 characters long * (name + suffix) */ } bnx2x_blocks_parity_data[] = { diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index e2e45ee5df33..bcc112b82831 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -161,6 +161,120 @@ #define EDC_MODE_LIMITING 0x0044 #define EDC_MODE_PASSIVE_DAC 0x0055 +/* BRB default for class 0 E2 */ +#define DEFAULT0_E2_BRB_MAC_PAUSE_XOFF_THR 170 +#define DEFAULT0_E2_BRB_MAC_PAUSE_XON_THR 250 +#define DEFAULT0_E2_BRB_MAC_FULL_XOFF_THR 10 +#define DEFAULT0_E2_BRB_MAC_FULL_XON_THR 50 + +/* BRB thresholds for E2*/ +#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE 170 +#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0 + +#define PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE 250 +#define PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0 + +#define PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE 10 +#define PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 90 + +#define PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE 50 +#define PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE 250 + +/* BRB default for class 0 E3A0 */ +#define DEFAULT0_E3A0_BRB_MAC_PAUSE_XOFF_THR 290 +#define DEFAULT0_E3A0_BRB_MAC_PAUSE_XON_THR 410 +#define DEFAULT0_E3A0_BRB_MAC_FULL_XOFF_THR 10 +#define DEFAULT0_E3A0_BRB_MAC_FULL_XON_THR 50 + +/* BRB thresholds for E3A0 */ +#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE 290 +#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0 + +#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE 410 +#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0 + +#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE 10 +#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 170 + +#define PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE 50 +#define PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE 410 + +/* BRB default for E3B0 */ +#define DEFAULT0_E3B0_BRB_MAC_PAUSE_XOFF_THR 330 +#define DEFAULT0_E3B0_BRB_MAC_PAUSE_XON_THR 490 +#define DEFAULT0_E3B0_BRB_MAC_FULL_XOFF_THR 15 +#define DEFAULT0_E3B0_BRB_MAC_FULL_XON_THR 55 + +/* BRB thresholds for E3B0 2 port mode*/ +#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE 1025 +#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0 + +#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE 1025 +#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0 + +#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE 10 +#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 1025 + +#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE 50 +#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE 1025 + +/* only for E3B0*/ +#define PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR 1025 +#define PFC_E3B0_2P_BRB_FULL_LB_XON_THR 1025 + +/* Lossy +Lossless GUARANTIED == GUART */ +#define PFC_E3B0_2P_MIX_PAUSE_LB_GUART 284 +/* Lossless +Lossless*/ +#define PFC_E3B0_2P_PAUSE_LB_GUART 236 +/* Lossy +Lossy*/ +#define PFC_E3B0_2P_NON_PAUSE_LB_GUART 342 + +/* Lossy +Lossless*/ +#define PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART 284 +/* Lossless +Lossless*/ +#define PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART 236 +/* Lossy +Lossy*/ +#define PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART 336 +#define PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST 80 + +#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART 0 +#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST 0 + +/* BRB thresholds for E3B0 4 port mode */ +#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE 304 +#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE 0 + +#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE 384 +#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE 0 + +#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE 10 +#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE 304 + +#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE 50 +#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE 384 + +/* only for E3B0*/ +#define PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR 304 +#define PFC_E3B0_4P_BRB_FULL_LB_XON_THR 384 +#define PFC_E3B0_4P_LB_GUART 120 + +#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART 120 +#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST 80 + +#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART 80 +#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST 120 + +/* Pause defines*/ +#define DEFAULT_E3B0_BRB_FULL_LB_XOFF_THR 330 +#define DEFAULT_E3B0_BRB_FULL_LB_XON_THR 490 +#define DEFAULT_E3B0_LB_GUART 40 + +#define DEFAULT_E3B0_BRB_MAC_0_CLASS_T_GUART 40 +#define DEFAULT_E3B0_BRB_MAC_0_CLASS_T_GUART_HYST 0 + +#define DEFAULT_E3B0_BRB_MAC_1_CLASS_T_GUART 40 +#define DEFAULT_E3B0_BRB_MAC_1_CLASS_T_GUART_HYST 0 + /* ETS defines*/ #define DCBX_INVALID_COS (0xFF) @@ -2030,6 +2144,391 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params, REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2); } +/* PFC BRB internal port configuration params */ +struct bnx2x_pfc_brb_threshold_val { + u32 pause_xoff; + u32 pause_xon; + u32 full_xoff; + u32 full_xon; +}; + +struct bnx2x_pfc_brb_e3b0_val { + u32 per_class_guaranty_mode; + u32 lb_guarantied_hyst; + u32 full_lb_xoff_th; + u32 full_lb_xon_threshold; + u32 lb_guarantied; + u32 mac_0_class_t_guarantied; + u32 mac_0_class_t_guarantied_hyst; + u32 mac_1_class_t_guarantied; + u32 mac_1_class_t_guarantied_hyst; +}; + +struct bnx2x_pfc_brb_th_val { + struct bnx2x_pfc_brb_threshold_val pauseable_th; + struct bnx2x_pfc_brb_threshold_val non_pauseable_th; + struct bnx2x_pfc_brb_threshold_val default_class0; + struct bnx2x_pfc_brb_threshold_val default_class1; + +}; +static int bnx2x_pfc_brb_get_config_params( + struct link_params *params, + struct bnx2x_pfc_brb_th_val *config_val) +{ + struct bnx2x *bp = params->bp; + DP(NETIF_MSG_LINK, "Setting PFC BRB configuration\n"); + + config_val->default_class1.pause_xoff = 0; + config_val->default_class1.pause_xon = 0; + config_val->default_class1.full_xoff = 0; + config_val->default_class1.full_xon = 0; + + if (CHIP_IS_E2(bp)) { + /* Class0 defaults */ + config_val->default_class0.pause_xoff = + DEFAULT0_E2_BRB_MAC_PAUSE_XOFF_THR; + config_val->default_class0.pause_xon = + DEFAULT0_E2_BRB_MAC_PAUSE_XON_THR; + config_val->default_class0.full_xoff = + DEFAULT0_E2_BRB_MAC_FULL_XOFF_THR; + config_val->default_class0.full_xon = + DEFAULT0_E2_BRB_MAC_FULL_XON_THR; + /* Pause able*/ + config_val->pauseable_th.pause_xoff = + PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE; + config_val->pauseable_th.pause_xon = + PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE; + config_val->pauseable_th.full_xoff = + PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE; + config_val->pauseable_th.full_xon = + PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE; + /* Non pause able*/ + config_val->non_pauseable_th.pause_xoff = + PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE; + config_val->non_pauseable_th.pause_xon = + PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE; + config_val->non_pauseable_th.full_xoff = + PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE; + config_val->non_pauseable_th.full_xon = + PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE; + } else if (CHIP_IS_E3A0(bp)) { + /* Class0 defaults */ + config_val->default_class0.pause_xoff = + DEFAULT0_E3A0_BRB_MAC_PAUSE_XOFF_THR; + config_val->default_class0.pause_xon = + DEFAULT0_E3A0_BRB_MAC_PAUSE_XON_THR; + config_val->default_class0.full_xoff = + DEFAULT0_E3A0_BRB_MAC_FULL_XOFF_THR; + config_val->default_class0.full_xon = + DEFAULT0_E3A0_BRB_MAC_FULL_XON_THR; + /* Pause able */ + config_val->pauseable_th.pause_xoff = + PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE; + config_val->pauseable_th.pause_xon = + PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE; + config_val->pauseable_th.full_xoff = + PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE; + config_val->pauseable_th.full_xon = + PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE; + /* Non pause able*/ + config_val->non_pauseable_th.pause_xoff = + PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE; + config_val->non_pauseable_th.pause_xon = + PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE; + config_val->non_pauseable_th.full_xoff = + PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE; + config_val->non_pauseable_th.full_xon = + PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE; + } else if (CHIP_IS_E3B0(bp)) { + /* Class0 defaults */ + config_val->default_class0.pause_xoff = + DEFAULT0_E3B0_BRB_MAC_PAUSE_XOFF_THR; + config_val->default_class0.pause_xon = + DEFAULT0_E3B0_BRB_MAC_PAUSE_XON_THR; + config_val->default_class0.full_xoff = + DEFAULT0_E3B0_BRB_MAC_FULL_XOFF_THR; + config_val->default_class0.full_xon = + DEFAULT0_E3B0_BRB_MAC_FULL_XON_THR; + + if (params->phy[INT_PHY].flags & + FLAGS_4_PORT_MODE) { + config_val->pauseable_th.pause_xoff = + PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE; + config_val->pauseable_th.pause_xon = + PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE; + config_val->pauseable_th.full_xoff = + PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE; + config_val->pauseable_th.full_xon = + PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE; + /* Non pause able*/ + config_val->non_pauseable_th.pause_xoff = + PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE; + config_val->non_pauseable_th.pause_xon = + PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE; + config_val->non_pauseable_th.full_xoff = + PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE; + config_val->non_pauseable_th.full_xon = + PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE; + } else { + config_val->pauseable_th.pause_xoff = + PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE; + config_val->pauseable_th.pause_xon = + PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE; + config_val->pauseable_th.full_xoff = + PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE; + config_val->pauseable_th.full_xon = + PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE; + /* Non pause able*/ + config_val->non_pauseable_th.pause_xoff = + PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE; + config_val->non_pauseable_th.pause_xon = + PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE; + config_val->non_pauseable_th.full_xoff = + PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE; + config_val->non_pauseable_th.full_xon = + PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE; + } + } else + return -EINVAL; + + return 0; +} + +static void bnx2x_pfc_brb_get_e3b0_config_params( + struct link_params *params, + struct bnx2x_pfc_brb_e3b0_val + *e3b0_val, + struct bnx2x_nig_brb_pfc_port_params *pfc_params, + const u8 pfc_enabled) +{ + if (pfc_enabled && pfc_params) { + e3b0_val->per_class_guaranty_mode = 1; + e3b0_val->lb_guarantied_hyst = 80; + + if (params->phy[INT_PHY].flags & + FLAGS_4_PORT_MODE) { + e3b0_val->full_lb_xoff_th = + PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR; + e3b0_val->full_lb_xon_threshold = + PFC_E3B0_4P_BRB_FULL_LB_XON_THR; + e3b0_val->lb_guarantied = + PFC_E3B0_4P_LB_GUART; + e3b0_val->mac_0_class_t_guarantied = + PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART; + e3b0_val->mac_0_class_t_guarantied_hyst = + PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST; + e3b0_val->mac_1_class_t_guarantied = + PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART; + e3b0_val->mac_1_class_t_guarantied_hyst = + PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST; + } else { + e3b0_val->full_lb_xoff_th = + PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR; + e3b0_val->full_lb_xon_threshold = + PFC_E3B0_2P_BRB_FULL_LB_XON_THR; + e3b0_val->mac_0_class_t_guarantied_hyst = + PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST; + e3b0_val->mac_1_class_t_guarantied = + PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART; + e3b0_val->mac_1_class_t_guarantied_hyst = + PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST; + + if (pfc_params->cos0_pauseable != + pfc_params->cos1_pauseable) { + /* Nonpauseable= Lossy + pauseable = Lossless*/ + e3b0_val->lb_guarantied = + PFC_E3B0_2P_MIX_PAUSE_LB_GUART; + e3b0_val->mac_0_class_t_guarantied = + PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART; + } else if (pfc_params->cos0_pauseable) { + /* Lossless +Lossless*/ + e3b0_val->lb_guarantied = + PFC_E3B0_2P_PAUSE_LB_GUART; + e3b0_val->mac_0_class_t_guarantied = + PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART; + } else { + /* Lossy +Lossy*/ + e3b0_val->lb_guarantied = + PFC_E3B0_2P_NON_PAUSE_LB_GUART; + e3b0_val->mac_0_class_t_guarantied = + PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART; + } + } + } else { + e3b0_val->per_class_guaranty_mode = 0; + e3b0_val->lb_guarantied_hyst = 0; + e3b0_val->full_lb_xoff_th = + DEFAULT_E3B0_BRB_FULL_LB_XOFF_THR; + e3b0_val->full_lb_xon_threshold = + DEFAULT_E3B0_BRB_FULL_LB_XON_THR; + e3b0_val->lb_guarantied = + DEFAULT_E3B0_LB_GUART; + e3b0_val->mac_0_class_t_guarantied = + DEFAULT_E3B0_BRB_MAC_0_CLASS_T_GUART; + e3b0_val->mac_0_class_t_guarantied_hyst = + DEFAULT_E3B0_BRB_MAC_0_CLASS_T_GUART_HYST; + e3b0_val->mac_1_class_t_guarantied = + DEFAULT_E3B0_BRB_MAC_1_CLASS_T_GUART; + e3b0_val->mac_1_class_t_guarantied_hyst = + DEFAULT_E3B0_BRB_MAC_1_CLASS_T_GUART_HYST; + } +} +static int bnx2x_update_pfc_brb(struct link_params *params, + struct link_vars *vars, + struct bnx2x_nig_brb_pfc_port_params + *pfc_params) +{ + struct bnx2x *bp = params->bp; + struct bnx2x_pfc_brb_th_val config_val = { {0} }; + struct bnx2x_pfc_brb_threshold_val *reg_th_config = + &config_val.pauseable_th; + struct bnx2x_pfc_brb_e3b0_val e3b0_val = {0}; + const int set_pfc = params->feature_config_flags & + FEATURE_CONFIG_PFC_ENABLED; + const u8 pfc_enabled = (set_pfc && pfc_params); + int bnx2x_status = 0; + u8 port = params->port; + + /* default - pause configuration */ + reg_th_config = &config_val.pauseable_th; + bnx2x_status = bnx2x_pfc_brb_get_config_params(params, &config_val); + if (bnx2x_status) + return bnx2x_status; + + if (pfc_enabled) { + /* First COS */ + if (pfc_params->cos0_pauseable) + reg_th_config = &config_val.pauseable_th; + else + reg_th_config = &config_val.non_pauseable_th; + } else + reg_th_config = &config_val.default_class0; + /* The number of free blocks below which the pause signal to class 0 + * of MAC #n is asserted. n=0,1 + */ + REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1 : + BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 , + reg_th_config->pause_xoff); + /* The number of free blocks above which the pause signal to class 0 + * of MAC #n is de-asserted. n=0,1 + */ + REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XON_THRESHOLD_1 : + BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , reg_th_config->pause_xon); + /* The number of free blocks below which the full signal to class 0 + * of MAC #n is asserted. n=0,1 + */ + REG_WR(bp, (port) ? BRB1_REG_FULL_0_XOFF_THRESHOLD_1 : + BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , reg_th_config->full_xoff); + /* The number of free blocks above which the full signal to class 0 + * of MAC #n is de-asserted. n=0,1 + */ + REG_WR(bp, (port) ? BRB1_REG_FULL_0_XON_THRESHOLD_1 : + BRB1_REG_FULL_0_XON_THRESHOLD_0 , reg_th_config->full_xon); + + if (pfc_enabled) { + /* Second COS */ + if (pfc_params->cos1_pauseable) + reg_th_config = &config_val.pauseable_th; + else + reg_th_config = &config_val.non_pauseable_th; + } else + reg_th_config = &config_val.default_class1; + /* The number of free blocks below which the pause signal to + * class 1 of MAC #n is asserted. n=0,1 + */ + REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 : + BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0, + reg_th_config->pause_xoff); + + /* The number of free blocks above which the pause signal to + * class 1 of MAC #n is de-asserted. n=0,1 + */ + REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 : + BRB1_REG_PAUSE_1_XON_THRESHOLD_0, + reg_th_config->pause_xon); + /* The number of free blocks below which the full signal to + * class 1 of MAC #n is asserted. n=0,1 + */ + REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 : + BRB1_REG_FULL_1_XOFF_THRESHOLD_0, + reg_th_config->full_xoff); + /* The number of free blocks above which the full signal to + * class 1 of MAC #n is de-asserted. n=0,1 + */ + REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 : + BRB1_REG_FULL_1_XON_THRESHOLD_0, + reg_th_config->full_xon); + + if (CHIP_IS_E3B0(bp)) { + bnx2x_pfc_brb_get_e3b0_config_params( + params, + &e3b0_val, + pfc_params, + pfc_enabled); + + REG_WR(bp, BRB1_REG_PER_CLASS_GUARANTY_MODE, + e3b0_val.per_class_guaranty_mode); + + /* The hysteresis on the guarantied buffer space for the Lb + * port before signaling XON. + */ + REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST, + e3b0_val.lb_guarantied_hyst); + + /* The number of free blocks below which the full signal to the + * LB port is asserted. + */ + REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD, + e3b0_val.full_lb_xoff_th); + /* The number of free blocks above which the full signal to the + * LB port is de-asserted. + */ + REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD, + e3b0_val.full_lb_xon_threshold); + /* The number of blocks guarantied for the MAC #n port. n=0,1 + */ + + /* The number of blocks guarantied for the LB port. */ + REG_WR(bp, BRB1_REG_LB_GUARANTIED, + e3b0_val.lb_guarantied); + + /* The number of blocks guarantied for the MAC #n port. */ + REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0, + 2 * e3b0_val.mac_0_class_t_guarantied); + REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1, + 2 * e3b0_val.mac_1_class_t_guarantied); + /* The number of blocks guarantied for class #t in MAC0. t=0,1 + */ + REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED, + e3b0_val.mac_0_class_t_guarantied); + REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED, + e3b0_val.mac_0_class_t_guarantied); + /* The hysteresis on the guarantied buffer space for class in + * MAC0. t=0,1 + */ + REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST, + e3b0_val.mac_0_class_t_guarantied_hyst); + REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST, + e3b0_val.mac_0_class_t_guarantied_hyst); + + /* The number of blocks guarantied for class #t in MAC1.t=0,1 + */ + REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED, + e3b0_val.mac_1_class_t_guarantied); + REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED, + e3b0_val.mac_1_class_t_guarantied); + /* The hysteresis on the guarantied buffer space for class #t + * in MAC1. t=0,1 + */ + REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST, + e3b0_val.mac_1_class_t_guarantied_hyst); + REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST, + e3b0_val.mac_1_class_t_guarantied_hyst); + } + + return bnx2x_status; +} + /****************************************************************************** * Description: * This function is needed because NIG ARB_CREDIT_WEIGHT_X are @@ -2206,6 +2705,11 @@ int bnx2x_update_pfc(struct link_params *params, /* Update NIG params */ bnx2x_update_pfc_nig(params, vars, pfc_params); + /* Update BRB params */ + bnx2x_status = bnx2x_update_pfc_brb(params, vars, pfc_params); + if (bnx2x_status) + return bnx2x_status; + if (!vars->link_up) return bnx2x_status; diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index c319e4c431fb..7a9157052c7c 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -9841,13 +9841,12 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp) } #ifdef CONFIG_PCI_MSI - /* Due to new PF resource allocation by MFW T7.4 and above, it's - * optional that number of CAM entries will not be equal to the value - * advertised in PCI. - * Driver should use the minimal value of both as the actual status - * block count + /* + * It's expected that number of CAM entries for this functions is equal + * to the number evaluated based on the MSI-X table size. We want a + * harsh warning if these values are different! */ - bp->igu_sb_cnt = min_t(int, bp->igu_sb_cnt, igu_sb_cnt); + WARN_ON(bp->igu_sb_cnt != igu_sb_cnt); #endif if (igu_sb_cnt == 0) diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 71971a161bd1..5a5fbf57c4b4 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -5619,7 +5619,7 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp, memset(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data with provided parameters */ - rdata->function_mode = (u8)start_params->mf_mode; + rdata->function_mode = cpu_to_le16(start_params->mf_mode); rdata->sd_vlan_tag = cpu_to_le16(start_params->sd_vlan_tag); rdata->path_id = BP_PATH(bp); rdata->network_cos_mode = start_params->network_cos_mode; diff --git a/trunk/drivers/net/ethernet/broadcom/cnic.c b/trunk/drivers/net/ethernet/broadcom/cnic.c index cc8434fd606e..2107d79d69b3 100644 --- a/trunk/drivers/net/ethernet/broadcom/cnic.c +++ b/trunk/drivers/net/ethernet/broadcom/cnic.c @@ -4891,9 +4891,6 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev, buf_map = udev->l2_buf_map; for (i = 0; i < MAX_TX_DESC_CNT; i += 3, txbd += 3) { struct eth_tx_start_bd *start_bd = &txbd->start_bd; - struct eth_tx_parse_bd_e1x *pbd_e1x = - &((txbd + 1)->parse_bd_e1x); - struct eth_tx_parse_bd_e2 *pbd_e2 = &((txbd + 1)->parse_bd_e2); struct eth_tx_bd *reg_bd = &((txbd + 2)->reg_bd); start_bd->addr_hi = cpu_to_le32((u64) buf_map >> 32); @@ -4903,15 +4900,10 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev, start_bd->nbytes = cpu_to_le16(0x10); start_bd->nbd = cpu_to_le16(3); start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; - start_bd->general_data &= ~ETH_TX_START_BD_PARSE_NBDS; + start_bd->general_data = (UNICAST_ADDRESS << + ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT); start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT); - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) - pbd_e2->parsing_data = (UNICAST_ADDRESS << - ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT); - else - pbd_e1x->global_data = (UNICAST_ADDRESS << - ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE_SHIFT); } val = (u64) ring_map >> 32; diff --git a/trunk/drivers/net/ethernet/broadcom/cnic_defs.h b/trunk/drivers/net/ethernet/broadcom/cnic_defs.h index ede3db35d757..382c98b0cc0c 100644 --- a/trunk/drivers/net/ethernet/broadcom/cnic_defs.h +++ b/trunk/drivers/net/ethernet/broadcom/cnic_defs.h @@ -896,7 +896,7 @@ struct tstorm_tcp_tcp_ag_context_section { u32 snd_nxt; u32 rtt_seq; u32 rtt_time; - u32 wnd_right_edge_local; + u32 __reserved66; u32 wnd_right_edge; u32 tcp_agg_vars1; #define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0) diff --git a/trunk/drivers/net/ethernet/broadcom/cnic_if.h b/trunk/drivers/net/ethernet/broadcom/cnic_if.h index 865095aad1f6..2e92c348083e 100644 --- a/trunk/drivers/net/ethernet/broadcom/cnic_if.h +++ b/trunk/drivers/net/ethernet/broadcom/cnic_if.h @@ -14,8 +14,8 @@ #include "bnx2x/bnx2x_mfw_req.h" -#define CNIC_MODULE_VERSION "2.5.14" -#define CNIC_MODULE_RELDATE "Sep 30, 2012" +#define CNIC_MODULE_VERSION "2.5.13" +#define CNIC_MODULE_RELDATE "Sep 07, 2012" #define CNIC_ULP_RDMA 0 #define CNIC_ULP_ISCSI 1 diff --git a/trunk/drivers/net/ethernet/broadcom/tg3.c b/trunk/drivers/net/ethernet/broadcom/tg3.c index 008ea14b638e..bf906c51d82a 100644 --- a/trunk/drivers/net/ethernet/broadcom/tg3.c +++ b/trunk/drivers/net/ethernet/broadcom/tg3.c @@ -44,8 +44,10 @@ #include #include #include +#if IS_ENABLED(CONFIG_HWMON) #include #include +#endif #include #include @@ -90,10 +92,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 125 +#define TG3_MIN_NUM 124 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "September 26, 2012" +#define DRV_MODULE_RELDATE "March 21, 2012" #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 @@ -6276,7 +6278,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) u32 jmb_prod_idx = dpr->rx_jmb_prod_idx; tp->rx_refill = false; - for (i = 1; i <= tp->rxq_cnt; i++) + for (i = 1; i < tp->irq_cnt; i++) err |= tg3_rx_prodring_xfer(tp, dpr, &tp->napi[i].prodring); @@ -7605,11 +7607,15 @@ static int tg3_init_rings(struct tg3 *tp) return 0; } -static void tg3_mem_tx_release(struct tg3 *tp) +/* + * Must not be invoked with interrupt sources disabled and + * the hardware shutdown down. + */ +static void tg3_free_consistent(struct tg3 *tp) { int i; - for (i = 0; i < tp->irq_max; i++) { + for (i = 0; i < tp->irq_cnt; i++) { struct tg3_napi *tnapi = &tp->napi[i]; if (tnapi->tx_ring) { @@ -7620,114 +7626,17 @@ static void tg3_mem_tx_release(struct tg3 *tp) kfree(tnapi->tx_buffers); tnapi->tx_buffers = NULL; - } -} - -static int tg3_mem_tx_acquire(struct tg3 *tp) -{ - int i; - struct tg3_napi *tnapi = &tp->napi[0]; - - /* If multivector TSS is enabled, vector 0 does not handle - * tx interrupts. Don't allocate any resources for it. - */ - if (tg3_flag(tp, ENABLE_TSS)) - tnapi++; - - for (i = 0; i < tp->txq_cnt; i++, tnapi++) { - tnapi->tx_buffers = kzalloc(sizeof(struct tg3_tx_ring_info) * - TG3_TX_RING_SIZE, GFP_KERNEL); - if (!tnapi->tx_buffers) - goto err_out; - tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev, - TG3_TX_RING_BYTES, - &tnapi->tx_desc_mapping, - GFP_KERNEL); - if (!tnapi->tx_ring) - goto err_out; - } - - return 0; - -err_out: - tg3_mem_tx_release(tp); - return -ENOMEM; -} - -static void tg3_mem_rx_release(struct tg3 *tp) -{ - int i; - - for (i = 0; i < tp->irq_max; i++) { - struct tg3_napi *tnapi = &tp->napi[i]; + if (tnapi->rx_rcb) { + dma_free_coherent(&tp->pdev->dev, + TG3_RX_RCB_RING_BYTES(tp), + tnapi->rx_rcb, + tnapi->rx_rcb_mapping); + tnapi->rx_rcb = NULL; + } tg3_rx_prodring_fini(tp, &tnapi->prodring); - if (!tnapi->rx_rcb) - continue; - - dma_free_coherent(&tp->pdev->dev, - TG3_RX_RCB_RING_BYTES(tp), - tnapi->rx_rcb, - tnapi->rx_rcb_mapping); - tnapi->rx_rcb = NULL; - } -} - -static int tg3_mem_rx_acquire(struct tg3 *tp) -{ - unsigned int i, limit; - - limit = tp->rxq_cnt; - - /* If RSS is enabled, we need a (dummy) producer ring - * set on vector zero. This is the true hw prodring. - */ - if (tg3_flag(tp, ENABLE_RSS)) - limit++; - - for (i = 0; i < limit; i++) { - struct tg3_napi *tnapi = &tp->napi[i]; - - if (tg3_rx_prodring_init(tp, &tnapi->prodring)) - goto err_out; - - /* If multivector RSS is enabled, vector 0 - * does not handle rx or tx interrupts. - * Don't allocate any resources for it. - */ - if (!i && tg3_flag(tp, ENABLE_RSS)) - continue; - - tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev, - TG3_RX_RCB_RING_BYTES(tp), - &tnapi->rx_rcb_mapping, - GFP_KERNEL); - if (!tnapi->rx_rcb) - goto err_out; - - memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); - } - - return 0; - -err_out: - tg3_mem_rx_release(tp); - return -ENOMEM; -} - -/* - * Must not be invoked with interrupt sources disabled and - * the hardware shutdown down. - */ -static void tg3_free_consistent(struct tg3 *tp) -{ - int i; - - for (i = 0; i < tp->irq_cnt; i++) { - struct tg3_napi *tnapi = &tp->napi[i]; - if (tnapi->hw_status) { dma_free_coherent(&tp->pdev->dev, TG3_HW_STATUS_SIZE, tnapi->hw_status, @@ -7736,9 +7645,6 @@ static void tg3_free_consistent(struct tg3 *tp) } } - tg3_mem_rx_release(tp); - tg3_mem_tx_release(tp); - if (tp->hw_stats) { dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats), tp->hw_stats, tp->stats_mapping); @@ -7777,37 +7683,71 @@ static int tg3_alloc_consistent(struct tg3 *tp) memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); sblk = tnapi->hw_status; - if (tg3_flag(tp, ENABLE_RSS)) { - u16 *prodptr = 0; + if (tg3_rx_prodring_init(tp, &tnapi->prodring)) + goto err_out; - /* - * When RSS is enabled, the status block format changes - * slightly. The "rx_jumbo_consumer", "reserved", - * and "rx_mini_consumer" members get mapped to the - * other three rx return ring producer indexes. - */ - switch (i) { - case 1: - prodptr = &sblk->idx[0].rx_producer; - break; - case 2: - prodptr = &sblk->rx_jumbo_consumer; - break; - case 3: - prodptr = &sblk->reserved; - break; - case 4: - prodptr = &sblk->rx_mini_consumer; + /* If multivector TSS is enabled, vector 0 does not handle + * tx interrupts. Don't allocate any resources for it. + */ + if ((!i && !tg3_flag(tp, ENABLE_TSS)) || + (i && tg3_flag(tp, ENABLE_TSS))) { + tnapi->tx_buffers = kzalloc( + sizeof(struct tg3_tx_ring_info) * + TG3_TX_RING_SIZE, GFP_KERNEL); + if (!tnapi->tx_buffers) + goto err_out; + + tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev, + TG3_TX_RING_BYTES, + &tnapi->tx_desc_mapping, + GFP_KERNEL); + if (!tnapi->tx_ring) + goto err_out; + } + + /* + * When RSS is enabled, the status block format changes + * slightly. The "rx_jumbo_consumer", "reserved", + * and "rx_mini_consumer" members get mapped to the + * other three rx return ring producer indexes. + */ + switch (i) { + default: + if (tg3_flag(tp, ENABLE_RSS)) { + tnapi->rx_rcb_prod_idx = NULL; break; } - tnapi->rx_rcb_prod_idx = prodptr; - } else { + /* Fall through */ + case 1: tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer; + break; + case 2: + tnapi->rx_rcb_prod_idx = &sblk->rx_jumbo_consumer; + break; + case 3: + tnapi->rx_rcb_prod_idx = &sblk->reserved; + break; + case 4: + tnapi->rx_rcb_prod_idx = &sblk->rx_mini_consumer; + break; } - } - if (tg3_mem_tx_acquire(tp) || tg3_mem_rx_acquire(tp)) - goto err_out; + /* + * If multivector RSS is enabled, vector 0 does not handle + * rx or tx interrupts. Don't allocate any resources for it. + */ + if (!i && tg3_flag(tp, ENABLE_RSS)) + continue; + + tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev, + TG3_RX_RCB_RING_BYTES(tp), + &tnapi->rx_rcb_mapping, + GFP_KERNEL); + if (!tnapi->rx_rcb) + goto err_out; + + memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); + } return 0; @@ -8329,10 +8269,9 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, nic_addr); } - -static void tg3_coal_tx_init(struct tg3 *tp, struct ethtool_coalesce *ec) +static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) { - int i = 0; + int i; if (!tg3_flag(tp, ENABLE_TSS)) { tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs); @@ -8342,43 +8281,31 @@ static void tg3_coal_tx_init(struct tg3 *tp, struct ethtool_coalesce *ec) tw32(HOSTCC_TXCOL_TICKS, 0); tw32(HOSTCC_TXMAX_FRAMES, 0); tw32(HOSTCC_TXCOAL_MAXF_INT, 0); - - for (; i < tp->txq_cnt; i++) { - u32 reg; - - reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18; - tw32(reg, ec->tx_coalesce_usecs); - reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18; - tw32(reg, ec->tx_max_coalesced_frames); - reg = HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18; - tw32(reg, ec->tx_max_coalesced_frames_irq); - } } - for (; i < tp->irq_max - 1; i++) { - tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0); - tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0); - tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); - } -} - -static void tg3_coal_rx_init(struct tg3 *tp, struct ethtool_coalesce *ec) -{ - int i = 0; - u32 limit = tp->rxq_cnt; - if (!tg3_flag(tp, ENABLE_RSS)) { tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs); tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames); tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq); - limit--; } else { tw32(HOSTCC_RXCOL_TICKS, 0); tw32(HOSTCC_RXMAX_FRAMES, 0); tw32(HOSTCC_RXCOAL_MAXF_INT, 0); } - for (; i < limit; i++) { + if (!tg3_flag(tp, 5705_PLUS)) { + u32 val = ec->stats_block_coalesce_usecs; + + tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq); + tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq); + + if (!netif_carrier_ok(tp->dev)) + val = 0; + + tw32(HOSTCC_STAT_COAL_TICKS, val); + } + + for (i = 0; i < tp->irq_cnt - 1; i++) { u32 reg; reg = HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18; @@ -8387,30 +8314,27 @@ static void tg3_coal_rx_init(struct tg3 *tp, struct ethtool_coalesce *ec) tw32(reg, ec->rx_max_coalesced_frames); reg = HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18; tw32(reg, ec->rx_max_coalesced_frames_irq); + + if (tg3_flag(tp, ENABLE_TSS)) { + reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18; + tw32(reg, ec->tx_coalesce_usecs); + reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18; + tw32(reg, ec->tx_max_coalesced_frames); + reg = HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18; + tw32(reg, ec->tx_max_coalesced_frames_irq); + } } for (; i < tp->irq_max - 1; i++) { tw32(HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18, 0); tw32(HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18, 0); tw32(HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); - } -} -static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) -{ - tg3_coal_tx_init(tp, ec); - tg3_coal_rx_init(tp, ec); - - if (!tg3_flag(tp, 5705_PLUS)) { - u32 val = ec->stats_block_coalesce_usecs; - - tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq); - tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq); - - if (!netif_carrier_ok(tp->dev)) - val = 0; - - tw32(HOSTCC_STAT_COAL_TICKS, val); + if (tg3_flag(tp, ENABLE_TSS)) { + tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0); + tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0); + tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); + } } } @@ -8668,12 +8592,13 @@ static void __tg3_set_rx_mode(struct net_device *dev) } } -static void tg3_rss_init_dflt_indir_tbl(struct tg3 *tp, u32 qcnt) +static void tg3_rss_init_dflt_indir_tbl(struct tg3 *tp) { int i; for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) - tp->rss_ind_tbl[i] = ethtool_rxfh_indir_default(i, qcnt); + tp->rss_ind_tbl[i] = + ethtool_rxfh_indir_default(i, tp->irq_cnt - 1); } static void tg3_rss_check_indir_tbl(struct tg3 *tp) @@ -8695,7 +8620,7 @@ static void tg3_rss_check_indir_tbl(struct tg3 *tp) } if (i != TG3_RSS_INDIR_TBL_SIZE) - tg3_rss_init_dflt_indir_tbl(tp, tp->rxq_cnt); + tg3_rss_init_dflt_indir_tbl(tp); } static void tg3_rss_write_indir_tbl(struct tg3 *tp) @@ -9592,6 +9517,7 @@ static int tg3_init_hw(struct tg3 *tp, int reset_phy) return tg3_reset_hw(tp, reset_phy); } +#if IS_ENABLED(CONFIG_HWMON) static void tg3_sd_scan_scratchpad(struct tg3 *tp, struct tg3_ocir *ocir) { int i; @@ -9644,17 +9570,22 @@ static const struct attribute_group tg3_group = { .attrs = tg3_attributes, }; +#endif + static void tg3_hwmon_close(struct tg3 *tp) { +#if IS_ENABLED(CONFIG_HWMON) if (tp->hwmon_dev) { hwmon_device_unregister(tp->hwmon_dev); tp->hwmon_dev = NULL; sysfs_remove_group(&tp->pdev->dev.kobj, &tg3_group); } +#endif } static void tg3_hwmon_open(struct tg3 *tp) { +#if IS_ENABLED(CONFIG_HWMON) int i, err; u32 size = 0; struct pci_dev *pdev = tp->pdev; @@ -9686,6 +9617,7 @@ static void tg3_hwmon_open(struct tg3 *tp) dev_err(&pdev->dev, "Cannot register hwmon device, aborting\n"); sysfs_remove_group(&pdev->dev.kobj, &tg3_group); } +#endif } @@ -10209,43 +10141,21 @@ static int tg3_request_firmware(struct tg3 *tp) return 0; } -static u32 tg3_irq_count(struct tg3 *tp) +static bool tg3_enable_msix(struct tg3 *tp) { - u32 irq_cnt = max(tp->rxq_cnt, tp->txq_cnt); + int i, rc; + struct msix_entry msix_ent[tp->irq_max]; - if (irq_cnt > 1) { + tp->irq_cnt = netif_get_num_default_rss_queues(); + if (tp->irq_cnt > 1) { /* We want as many rx rings enabled as there are cpus. * In multiqueue MSI-X mode, the first MSI-X vector * only deals with link interrupts, etc, so we add * one to the number of vectors we are requesting. */ - irq_cnt = min_t(unsigned, irq_cnt + 1, tp->irq_max); + tp->irq_cnt = min_t(unsigned, tp->irq_cnt + 1, tp->irq_max); } - return irq_cnt; -} - -static bool tg3_enable_msix(struct tg3 *tp) -{ - int i, rc; - struct msix_entry msix_ent[tp->irq_max]; - - tp->txq_cnt = tp->txq_req; - tp->rxq_cnt = tp->rxq_req; - if (!tp->rxq_cnt) - tp->rxq_cnt = netif_get_num_default_rss_queues(); - if (tp->rxq_cnt > tp->rxq_max) - tp->rxq_cnt = tp->rxq_max; - - /* Disable multiple TX rings by default. Simple round-robin hardware - * scheduling of the TX rings can cause starvation of rings with - * small packets when other rings have TSO or jumbo packets. - */ - if (!tp->txq_req) - tp->txq_cnt = 1; - - tp->irq_cnt = tg3_irq_count(tp); - for (i = 0; i < tp->irq_max; i++) { msix_ent[i].entry = i; msix_ent[i].vector = 0; @@ -10260,28 +10170,27 @@ static bool tg3_enable_msix(struct tg3 *tp) netdev_notice(tp->dev, "Requested %d MSI-X vectors, received %d\n", tp->irq_cnt, rc); tp->irq_cnt = rc; - tp->rxq_cnt = max(rc - 1, 1); - if (tp->txq_cnt) - tp->txq_cnt = min(tp->rxq_cnt, tp->txq_max); } for (i = 0; i < tp->irq_max; i++) tp->napi[i].irq_vec = msix_ent[i].vector; - if (netif_set_real_num_rx_queues(tp->dev, tp->rxq_cnt)) { + netif_set_real_num_tx_queues(tp->dev, 1); + rc = tp->irq_cnt > 1 ? tp->irq_cnt - 1 : 1; + if (netif_set_real_num_rx_queues(tp->dev, rc)) { pci_disable_msix(tp->pdev); return false; } - if (tp->irq_cnt == 1) - return true; - - tg3_flag_set(tp, ENABLE_RSS); - - if (tp->txq_cnt > 1) - tg3_flag_set(tp, ENABLE_TSS); + if (tp->irq_cnt > 1) { + tg3_flag_set(tp, ENABLE_RSS); - netif_set_real_num_tx_queues(tp->dev, tp->txq_cnt); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + tg3_flag_set(tp, ENABLE_TSS); + netif_set_real_num_tx_queues(tp->dev, tp->irq_cnt - 1); + } + } return true; } @@ -10315,11 +10224,6 @@ static void tg3_ints_init(struct tg3 *tp) if (!tg3_flag(tp, USING_MSIX)) { tp->irq_cnt = 1; tp->napi[0].irq_vec = tp->pdev->irq; - } - - if (tp->irq_cnt == 1) { - tp->txq_cnt = 1; - tp->rxq_cnt = 1; netif_set_real_num_tx_queues(tp->dev, 1); netif_set_real_num_rx_queues(tp->dev, 1); } @@ -10337,11 +10241,38 @@ static void tg3_ints_fini(struct tg3 *tp) tg3_flag_clear(tp, ENABLE_TSS); } -static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq) +static int tg3_open(struct net_device *dev) { - struct net_device *dev = tp->dev; + struct tg3 *tp = netdev_priv(dev); int i, err; + if (tp->fw_needed) { + err = tg3_request_firmware(tp); + if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { + if (err) + return err; + } else if (err) { + netdev_warn(tp->dev, "TSO capability disabled\n"); + tg3_flag_clear(tp, TSO_CAPABLE); + } else if (!tg3_flag(tp, TSO_CAPABLE)) { + netdev_notice(tp->dev, "TSO capability restored\n"); + tg3_flag_set(tp, TSO_CAPABLE); + } + } + + netif_carrier_off(tp->dev); + + err = tg3_power_up(tp); + if (err) + return err; + + tg3_full_lock(tp, 0); + + tg3_disable_ints(tp); + tg3_flag_clear(tp, INIT_COMPLETE); + + tg3_full_unlock(tp); + /* * Setup interrupts first so we know how * many NAPI resources to allocate @@ -10375,7 +10306,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq) tg3_full_lock(tp, 0); - err = tg3_init_hw(tp, reset_phy); + err = tg3_init_hw(tp, 1); if (err) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); @@ -10386,7 +10317,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq) if (err) goto err_out3; - if (test_irq && tg3_flag(tp, USING_MSI)) { + if (tg3_flag(tp, USING_MSI)) { err = tg3_test_msi(tp); if (err) { @@ -10442,18 +10373,20 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq) err_out1: tg3_ints_fini(tp); - + tg3_frob_aux_power(tp, false); + pci_set_power_state(tp->pdev, PCI_D3hot); return err; } -static void tg3_stop(struct tg3 *tp) +static int tg3_close(struct net_device *dev) { int i; + struct tg3 *tp = netdev_priv(dev); tg3_napi_disable(tp); tg3_reset_task_cancel(tp); - netif_tx_disable(tp->dev); + netif_tx_stop_all_queues(dev); tg3_timer_stop(tp); @@ -10478,61 +10411,14 @@ static void tg3_stop(struct tg3 *tp) tg3_ints_fini(tp); - tg3_napi_fini(tp); - - tg3_free_consistent(tp); -} - -static int tg3_open(struct net_device *dev) -{ - struct tg3 *tp = netdev_priv(dev); - int err; - - if (tp->fw_needed) { - err = tg3_request_firmware(tp); - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { - if (err) - return err; - } else if (err) { - netdev_warn(tp->dev, "TSO capability disabled\n"); - tg3_flag_clear(tp, TSO_CAPABLE); - } else if (!tg3_flag(tp, TSO_CAPABLE)) { - netdev_notice(tp->dev, "TSO capability restored\n"); - tg3_flag_set(tp, TSO_CAPABLE); - } - } - - netif_carrier_off(tp->dev); - - err = tg3_power_up(tp); - if (err) - return err; - - tg3_full_lock(tp, 0); - - tg3_disable_ints(tp); - tg3_flag_clear(tp, INIT_COMPLETE); - - tg3_full_unlock(tp); - - err = tg3_start(tp, true, true); - if (err) { - tg3_frob_aux_power(tp, false); - pci_set_power_state(tp->pdev, PCI_D3hot); - } - return err; -} - -static int tg3_close(struct net_device *dev) -{ - struct tg3 *tp = netdev_priv(dev); - - tg3_stop(tp); - /* Clear stats across close / open calls */ memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev)); memset(&tp->estats_prev, 0, sizeof(tp->estats_prev)); + tg3_napi_fini(tp); + + tg3_free_consistent(tp); + tg3_power_down(tp); netif_carrier_off(tp->dev); @@ -11321,11 +11207,11 @@ static int tg3_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, switch (info->cmd) { case ETHTOOL_GRXRINGS: if (netif_running(tp->dev)) - info->data = tp->rxq_cnt; + info->data = tp->irq_cnt; else { info->data = num_online_cpus(); - if (info->data > TG3_RSS_MAX_NUM_QS) - info->data = TG3_RSS_MAX_NUM_QS; + if (info->data > TG3_IRQ_MAX_VECS_RSS) + info->data = TG3_IRQ_MAX_VECS_RSS; } /* The first interrupt vector only @@ -11382,58 +11268,6 @@ static int tg3_set_rxfh_indir(struct net_device *dev, const u32 *indir) return 0; } -static void tg3_get_channels(struct net_device *dev, - struct ethtool_channels *channel) -{ - struct tg3 *tp = netdev_priv(dev); - u32 deflt_qs = netif_get_num_default_rss_queues(); - - channel->max_rx = tp->rxq_max; - channel->max_tx = tp->txq_max; - - if (netif_running(dev)) { - channel->rx_count = tp->rxq_cnt; - channel->tx_count = tp->txq_cnt; - } else { - if (tp->rxq_req) - channel->rx_count = tp->rxq_req; - else - channel->rx_count = min(deflt_qs, tp->rxq_max); - - if (tp->txq_req) - channel->tx_count = tp->txq_req; - else - channel->tx_count = min(deflt_qs, tp->txq_max); - } -} - -static int tg3_set_channels(struct net_device *dev, - struct ethtool_channels *channel) -{ - struct tg3 *tp = netdev_priv(dev); - - if (!tg3_flag(tp, SUPPORT_MSIX)) - return -EOPNOTSUPP; - - if (channel->rx_count > tp->rxq_max || - channel->tx_count > tp->txq_max) - return -EINVAL; - - tp->rxq_req = channel->rx_count; - tp->txq_req = channel->tx_count; - - if (!netif_running(dev)) - return 0; - - tg3_stop(tp); - - netif_carrier_off(dev); - - tg3_start(tp, true, false); - - return 0; -} - static void tg3_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { switch (stringset) { @@ -12682,8 +12516,6 @@ static const struct ethtool_ops tg3_ethtool_ops = { .get_rxfh_indir_size = tg3_get_rxfh_indir_size, .get_rxfh_indir = tg3_get_rxfh_indir, .set_rxfh_indir = tg3_set_rxfh_indir, - .get_channels = tg3_get_channels, - .set_channels = tg3_set_channels, .get_ts_info = ethtool_op_get_ts_info, }; @@ -14700,20 +14532,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tg3_flag(tp, 57765_PLUS)) { tg3_flag_set(tp, SUPPORT_MSIX); tp->irq_max = TG3_IRQ_MAX_VECS; + tg3_rss_init_dflt_indir_tbl(tp); } } - tp->txq_max = 1; - tp->rxq_max = 1; - if (tp->irq_max > 1) { - tp->rxq_max = TG3_RSS_MAX_NUM_QS; - tg3_rss_init_dflt_indir_tbl(tp, TG3_RSS_MAX_NUM_QS); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) - tp->txq_max = tp->irq_max - 1; - } - if (tg3_flag(tp, 5755_PLUS) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tg3_flag_set(tp, SHORT_DMA_BUG); diff --git a/trunk/drivers/net/ethernet/broadcom/tg3.h b/trunk/drivers/net/ethernet/broadcom/tg3.h index d9308c32102e..6d52cb286826 100644 --- a/trunk/drivers/net/ethernet/broadcom/tg3.h +++ b/trunk/drivers/net/ethernet/broadcom/tg3.h @@ -2860,8 +2860,7 @@ struct tg3_rx_prodring_set { dma_addr_t rx_jmb_mapping; }; -#define TG3_RSS_MAX_NUM_QS 4 -#define TG3_IRQ_MAX_VECS_RSS (TG3_RSS_MAX_NUM_QS + 1) +#define TG3_IRQ_MAX_VECS_RSS 5 #define TG3_IRQ_MAX_VECS TG3_IRQ_MAX_VECS_RSS struct tg3_napi { @@ -3038,9 +3037,6 @@ struct tg3 { void (*write32_tx_mbox) (struct tg3 *, u32, u32); u32 dma_limit; - u32 txq_req; - u32 txq_cnt; - u32 txq_max; /* begin "rx thread" cacheline section */ struct tg3_napi napi[TG3_IRQ_MAX_VECS]; @@ -3055,9 +3051,6 @@ struct tg3 { u32 rx_std_max_post; u32 rx_offset; u32 rx_pkt_map_sz; - u32 rxq_req; - u32 rxq_cnt; - u32 rxq_max; bool rx_refill; diff --git a/trunk/drivers/net/ethernet/brocade/bna/bnad.c b/trunk/drivers/net/ethernet/brocade/bna/bnad.c index ce1eac529470..b441f33258e7 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bnad.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bnad.c @@ -3268,7 +3268,6 @@ bnad_pci_probe(struct pci_dev *pdev, * Output : using_dac = 1 for 64 bit DMA * = 0 for 32 bit DMA */ - using_dac = false; err = bnad_pci_init(bnad, pdev, &using_dac); if (err) goto unlock_mutex; diff --git a/trunk/drivers/net/ethernet/cadence/at91_ether.c b/trunk/drivers/net/ethernet/cadence/at91_ether.c index 4e980a7886fb..77884191a8c6 100644 --- a/trunk/drivers/net/ethernet/cadence/at91_ether.c +++ b/trunk/drivers/net/ethernet/cadence/at91_ether.c @@ -1086,7 +1086,7 @@ static int __init at91ether_probe(struct platform_device *pdev) /* Clock */ lp->ether_clk = clk_get(&pdev->dev, "ether_clk"); if (IS_ERR(lp->ether_clk)) { - res = PTR_ERR(lp->ether_clk); + res = -ENODEV; goto err_ioumap; } clk_enable(lp->ether_clk); diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 745a1f53361f..ec2dafe8ae5b 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -67,12 +67,12 @@ enum { }; enum { - MEMWIN0_APERTURE = 2048, - MEMWIN0_BASE = 0x1b800, + MEMWIN0_APERTURE = 65536, + MEMWIN0_BASE = 0x30000, MEMWIN1_APERTURE = 32768, MEMWIN1_BASE = 0x28000, - MEMWIN2_APERTURE = 65536, - MEMWIN2_BASE = 0x30000, + MEMWIN2_APERTURE = 2048, + MEMWIN2_BASE = 0x1b800, }; enum dev_master { @@ -211,9 +211,6 @@ struct tp_err_stats { struct tp_params { unsigned int ntxchan; /* # of Tx channels */ unsigned int tre; /* log2 of core clocks per TP tick */ - - uint32_t dack_re; /* DACK timer resolution */ - unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */ }; struct vpd_params { @@ -318,10 +315,6 @@ enum { /* adapter flags */ USING_MSI = (1 << 1), USING_MSIX = (1 << 2), FW_OK = (1 << 4), - RSS_TNLALLLOOKUP = (1 << 5), - USING_SOFT_PARAMS = (1 << 6), - MASTER_PF = (1 << 7), - FW_OFLD_CONN = (1 << 9), }; struct rx_sw_desc; @@ -474,11 +467,6 @@ struct sge { u16 rdma_rxq[NCHAN]; u16 timer_val[SGE_NTIMERS]; u8 counter_val[SGE_NCOUNTERS]; - u32 fl_pg_order; /* large page allocation size */ - u32 stat_len; /* length of status page at ring end */ - u32 pktshift; /* padding between CPL & packet data */ - u32 fl_align; /* response queue message alignment */ - u32 fl_starve_thres; /* Free List starvation threshold */ unsigned int starve_thres; u8 idma_state[2]; unsigned int egr_start; @@ -523,8 +511,6 @@ struct adapter { struct net_device *port[MAX_NPORTS]; u8 chan_map[NCHAN]; /* channel -> port map */ - unsigned int l2t_start; - unsigned int l2t_end; struct l2t_data *l2t; void *uld_handle[CXGB4_ULD_MAX]; struct list_head list_node; @@ -633,7 +619,7 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq, int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq, struct net_device *dev, unsigned int iqid); irqreturn_t t4_sge_intr_msix(int irq, void *cookie); -int t4_sge_init(struct adapter *adap); +void t4_sge_init(struct adapter *adap); void t4_sge_start(struct adapter *adap); void t4_sge_stop(struct adapter *adap); extern int dbfifo_int_thresh; @@ -652,14 +638,6 @@ static inline unsigned int us_to_core_ticks(const struct adapter *adap, return (us * adap->params.vpd.cclk) / 1000; } -static inline unsigned int core_ticks_to_us(const struct adapter *adapter, - unsigned int ticks) -{ - /* add Core Clock / 2 to round ticks to nearest uS */ - return ((ticks * 1000 + adapter->params.vpd.cclk/2) / - adapter->params.vpd.cclk); -} - void t4_set_reg_field(struct adapter *adap, unsigned int addr, u32 mask, u32 val); @@ -678,9 +656,6 @@ static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd, return t4_wr_mbox_meat(adap, mbox, cmd, size, rpl, false); } -void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, - unsigned int data_reg, const u32 *vals, - unsigned int nregs, unsigned int start_idx); void t4_intr_enable(struct adapter *adapter); void t4_intr_disable(struct adapter *adapter); int t4_slow_intr_handler(struct adapter *adapter); @@ -689,12 +664,8 @@ int t4_wait_dev_ready(struct adapter *adap); int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port, struct link_config *lc); int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port); -int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len, - __be32 *buf); int t4_seeprom_wp(struct adapter *adapter, bool enable); -int get_vpd_params(struct adapter *adapter, struct vpd_params *p); int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size); -unsigned int t4_flash_cfg_addr(struct adapter *adapter); int t4_check_fw_version(struct adapter *adapter); int t4_prep_adapter(struct adapter *adapter); int t4_port_init(struct adapter *adap, int mbox, int pf, int vf); @@ -709,8 +680,6 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p); void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log); -void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr, - unsigned int mask, unsigned int val); void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4, struct tp_tcp_stats *v6); void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, @@ -726,16 +695,6 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox, int t4_fw_bye(struct adapter *adap, unsigned int mbox); int t4_early_init(struct adapter *adap, unsigned int mbox); int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset); -int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force); -int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset); -int t4_fw_upgrade(struct adapter *adap, unsigned int mbox, - const u8 *fw_data, unsigned int size, int force); -int t4_fw_config_file(struct adapter *adap, unsigned int mbox, - unsigned int mtype, unsigned int maddr, - u32 *finiver, u32 *finicsum, u32 *cfcsum); -int t4_fixup_host_params(struct adapter *adap, unsigned int page_size, - unsigned int cache_line_size); -int t4_fw_initialize(struct adapter *adap, unsigned int mbox); int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, u32 *val); diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 94b784610319..34d510dd56a8 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -78,45 +78,28 @@ */ #define MAX_SGE_TIMERVAL 200U -enum { - /* - * Physical Function provisioning constants. - */ - PFRES_NVI = 4, /* # of Virtual Interfaces */ - PFRES_NETHCTRL = 128, /* # of EQs used for ETH or CTRL Qs */ - PFRES_NIQFLINT = 128, /* # of ingress Qs/w Free List(s)/intr - */ - PFRES_NEQ = 256, /* # of egress queues */ - PFRES_NIQ = 0, /* # of ingress queues */ - PFRES_TC = 0, /* PCI-E traffic class */ - PFRES_NEXACTF = 128, /* # of exact MPS filters */ - - PFRES_R_CAPS = FW_CMD_CAP_PF, - PFRES_WX_CAPS = FW_CMD_CAP_PF, - #ifdef CONFIG_PCI_IOV - /* - * Virtual Function provisioning constants. We need two extra Ingress - * Queues with Interrupt capability to serve as the VF's Firmware - * Event Queue and Forwarded Interrupt Queue (when using MSI mode) -- - * neither will have Free Lists associated with them). For each - * Ethernet/Control Egress Queue and for each Free List, we need an - * Egress Context. - */ +/* + * Virtual Function provisioning constants. We need two extra Ingress Queues + * with Interrupt capability to serve as the VF's Firmware Event Queue and + * Forwarded Interrupt Queue (when using MSI mode) -- neither will have Free + * Lists associated with them). For each Ethernet/Control Egress Queue and + * for each Free List, we need an Egress Context. + */ +enum { VFRES_NPORTS = 1, /* # of "ports" per VF */ VFRES_NQSETS = 2, /* # of "Queue Sets" per VF */ VFRES_NVI = VFRES_NPORTS, /* # of Virtual Interfaces */ VFRES_NETHCTRL = VFRES_NQSETS, /* # of EQs used for ETH or CTRL Qs */ VFRES_NIQFLINT = VFRES_NQSETS+2,/* # of ingress Qs/w Free List(s)/intr */ - VFRES_NEQ = VFRES_NQSETS*2, /* # of egress queues */ VFRES_NIQ = 0, /* # of non-fl/int ingress queues */ + VFRES_NEQ = VFRES_NQSETS*2, /* # of egress queues */ VFRES_TC = 0, /* PCI-E traffic class */ VFRES_NEXACTF = 16, /* # of exact MPS filters */ VFRES_R_CAPS = FW_CMD_CAP_DMAQ|FW_CMD_CAP_VF|FW_CMD_CAP_PORT, VFRES_WX_CAPS = FW_CMD_CAP_DMAQ|FW_CMD_CAP_VF, -#endif }; /* @@ -163,6 +146,7 @@ static unsigned int pfvfres_pmask(struct adapter *adapter, } /*NOTREACHED*/ } +#endif enum { MAX_TXQ_ENTRIES = 16384, @@ -209,7 +193,6 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = { }; #define FW_FNAME "cxgb4/t4fw.bin" -#define FW_CFNAME "cxgb4/t4-config.txt" MODULE_DESCRIPTION(DRV_DESC); MODULE_AUTHOR("Chelsio Communications"); @@ -218,28 +201,6 @@ MODULE_VERSION(DRV_VERSION); MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl); MODULE_FIRMWARE(FW_FNAME); -/* - * Normally we're willing to become the firmware's Master PF but will be happy - * if another PF has already become the Master and initialized the adapter. - * Setting "force_init" will cause this driver to forcibly establish itself as - * the Master PF and initialize the adapter. - */ -static uint force_init; - -module_param(force_init, uint, 0644); -MODULE_PARM_DESC(force_init, "Forcibly become Master PF and initialize adapter"); - -/* - * Normally if the firmware we connect to has Configuration File support, we - * use that and only fall back to the old Driver-based initialization if the - * Configuration File fails for some reason. If force_old_init is set, then - * we'll always use the old Driver-based initialization sequence. - */ -static uint force_old_init; - -module_param(force_old_init, uint, 0644); -MODULE_PARM_DESC(force_old_init, "Force old initialization sequence"); - static int dflt_msg_enable = DFLT_MSG_ENABLE; module_param(dflt_msg_enable, int, 0644); @@ -275,20 +236,6 @@ module_param_array(intr_cnt, uint, NULL, 0644); MODULE_PARM_DESC(intr_cnt, "thresholds 1..3 for queue interrupt packet counters"); -/* - * Normally we tell the chip to deliver Ingress Packets into our DMA buffers - * offset by 2 bytes in order to have the IP headers line up on 4-byte - * boundaries. This is a requirement for many architectures which will throw - * a machine check fault if an attempt is made to access one of the 4-byte IP - * header fields on a non-4-byte boundary. And it's a major performance issue - * even on some architectures which allow it like some implementations of the - * x86 ISA. However, some architectures don't mind this and for some very - * edge-case performance sensitive applications (like forwarding large volumes - * of small packets), setting this DMA offset to 0 will decrease the number of - * PCI-E Bus transfers enough to measurably affect performance. - */ -static int rx_dma_offset = 2; - static bool vf_acls; #ifdef CONFIG_PCI_IOV @@ -301,30 +248,6 @@ module_param_array(num_vf, uint, NULL, 0644); MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3"); #endif -/* - * The filter TCAM has a fixed portion and a variable portion. The fixed - * portion can match on source/destination IP IPv4/IPv6 addresses and TCP/UDP - * ports. The variable portion is 36 bits which can include things like Exact - * Match MAC Index (9 bits), Ether Type (16 bits), IP Protocol (8 bits), - * [Inner] VLAN Tag (17 bits), etc. which, if all were somehow selected, would - * far exceed the 36-bit budget for this "compressed" header portion of the - * filter. Thus, we have a scarce resource which must be carefully managed. - * - * By default we set this up to mostly match the set of filter matching - * capabilities of T3 but with accommodations for some of T4's more - * interesting features: - * - * { IP Fragment (1), MPS Match Type (3), IP Protocol (8), - * [Inner] VLAN (17), Port (3), FCoE (1) } - */ -enum { - TP_VLAN_PRI_MAP_DEFAULT = HW_TPL_FR_MT_PR_IV_P_FC, - TP_VLAN_PRI_MAP_FIRST = FCOE_SHIFT, - TP_VLAN_PRI_MAP_LAST = FRAGMENTATION_SHIFT, -}; - -static unsigned int tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT; - static struct dentry *cxgb4_debugfs_root; static LIST_HEAD(adapter_list); @@ -929,25 +852,11 @@ static int upgrade_fw(struct adapter *adap) */ if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != FW_VERSION_MAJOR || vers > adap->params.fw_vers) { - dev_info(dev, "upgrading firmware ...\n"); - ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size, - /*force=*/false); + ret = -t4_load_fw(adap, fw->data, fw->size); if (!ret) - dev_info(dev, "firmware successfully upgraded to " - FW_FNAME " (%d.%d.%d.%d)\n", - FW_HDR_FW_VER_MAJOR_GET(vers), - FW_HDR_FW_VER_MINOR_GET(vers), - FW_HDR_FW_VER_MICRO_GET(vers), - FW_HDR_FW_VER_BUILD_GET(vers)); - else - dev_err(dev, "firmware upgrade failed! err=%d\n", -ret); - } else { - /* - * Tell our caller that we didn't upgrade the firmware. - */ - ret = -EINVAL; + dev_info(dev, "firmware upgraded to version %pI4 from " + FW_FNAME "\n", &hdr->fw_ver); } - out: release_firmware(fw); return ret; } @@ -3167,10 +3076,6 @@ static void setup_memwin(struct adapter *adap) t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2), (bar0 + MEMWIN2_BASE) | BIR(0) | WINDOW(ilog2(MEMWIN2_APERTURE) - 10)); -} - -static void setup_memwin_rdma(struct adapter *adap) -{ if (adap->vres.ocq.size) { unsigned int start, sz_kb; @@ -3248,488 +3153,6 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c) */ #define MAX_ATIDS 8192U -/* - * Phase 0 of initialization: contact FW, obtain config, perform basic init. - * - * If the firmware we're dealing with has Configuration File support, then - * we use that to perform all configuration - */ - -/* - * Tweak configuration based on module parameters, etc. Most of these have - * defaults assigned to them by Firmware Configuration Files (if we're using - * them) but need to be explicitly set if we're using hard-coded - * initialization. But even in the case of using Firmware Configuration - * Files, we'd like to expose the ability to change these via module - * parameters so these are essentially common tweaks/settings for - * Configuration Files and hard-coded initialization ... - */ -static int adap_init0_tweaks(struct adapter *adapter) -{ - /* - * Fix up various Host-Dependent Parameters like Page Size, Cache - * Line Size, etc. The firmware default is for a 4KB Page Size and - * 64B Cache Line Size ... - */ - t4_fixup_host_params(adapter, PAGE_SIZE, L1_CACHE_BYTES); - - /* - * Process module parameters which affect early initialization. - */ - if (rx_dma_offset != 2 && rx_dma_offset != 0) { - dev_err(&adapter->pdev->dev, - "Ignoring illegal rx_dma_offset=%d, using 2\n", - rx_dma_offset); - rx_dma_offset = 2; - } - t4_set_reg_field(adapter, SGE_CONTROL, - PKTSHIFT_MASK, - PKTSHIFT(rx_dma_offset)); - - /* - * Don't include the "IP Pseudo Header" in CPL_RX_PKT checksums: Linux - * adds the pseudo header itself. - */ - t4_tp_wr_bits_indirect(adapter, TP_INGRESS_CONFIG, - CSUM_HAS_PSEUDO_HDR, 0); - - return 0; -} - -/* - * Attempt to initialize the adapter via a Firmware Configuration File. - */ -static int adap_init0_config(struct adapter *adapter, int reset) -{ - struct fw_caps_config_cmd caps_cmd; - const struct firmware *cf; - unsigned long mtype = 0, maddr = 0; - u32 finiver, finicsum, cfcsum; - int ret, using_flash; - - /* - * Reset device if necessary. - */ - if (reset) { - ret = t4_fw_reset(adapter, adapter->mbox, - PIORSTMODE | PIORST); - if (ret < 0) - goto bye; - } - - /* - * If we have a T4 configuration file under /lib/firmware/cxgb4/, - * then use that. Otherwise, use the configuration file stored - * in the adapter flash ... - */ - ret = request_firmware(&cf, FW_CFNAME, adapter->pdev_dev); - if (ret < 0) { - using_flash = 1; - mtype = FW_MEMTYPE_CF_FLASH; - maddr = t4_flash_cfg_addr(adapter); - } else { - u32 params[7], val[7]; - - using_flash = 0; - if (cf->size >= FLASH_CFG_MAX_SIZE) - ret = -ENOMEM; - else { - params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF)); - ret = t4_query_params(adapter, adapter->mbox, - adapter->fn, 0, 1, params, val); - if (ret == 0) { - /* - * For t4_memory_write() below addresses and - * sizes have to be in terms of multiples of 4 - * bytes. So, if the Configuration File isn't - * a multiple of 4 bytes in length we'll have - * to write that out separately since we can't - * guarantee that the bytes following the - * residual byte in the buffer returned by - * request_firmware() are zeroed out ... - */ - size_t resid = cf->size & 0x3; - size_t size = cf->size & ~0x3; - __be32 *data = (__be32 *)cf->data; - - mtype = FW_PARAMS_PARAM_Y_GET(val[0]); - maddr = FW_PARAMS_PARAM_Z_GET(val[0]) << 16; - - ret = t4_memory_write(adapter, mtype, maddr, - size, data); - if (ret == 0 && resid != 0) { - union { - __be32 word; - char buf[4]; - } last; - int i; - - last.word = data[size >> 2]; - for (i = resid; i < 4; i++) - last.buf[i] = 0; - ret = t4_memory_write(adapter, mtype, - maddr + size, - 4, &last.word); - } - } - } - - release_firmware(cf); - if (ret) - goto bye; - } - - /* - * Issue a Capability Configuration command to the firmware to get it - * to parse the Configuration File. We don't use t4_fw_config_file() - * because we want the ability to modify various features after we've - * processed the configuration file ... - */ - memset(&caps_cmd, 0, sizeof(caps_cmd)); - caps_cmd.op_to_write = - htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ); - caps_cmd.retval_len16 = - htonl(FW_CAPS_CONFIG_CMD_CFVALID | - FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) | - FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) | - FW_LEN16(caps_cmd)); - ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), - &caps_cmd); - if (ret < 0) - goto bye; - - finiver = ntohl(caps_cmd.finiver); - finicsum = ntohl(caps_cmd.finicsum); - cfcsum = ntohl(caps_cmd.cfcsum); - if (finicsum != cfcsum) - dev_warn(adapter->pdev_dev, "Configuration File checksum "\ - "mismatch: [fini] csum=%#x, computed csum=%#x\n", - finicsum, cfcsum); - - /* - * If we're a pure NIC driver then disable all offloading facilities. - * This will allow the firmware to optimize aspects of the hardware - * configuration which will result in improved performance. - */ - caps_cmd.ofldcaps = 0; - caps_cmd.iscsicaps = 0; - caps_cmd.rdmacaps = 0; - caps_cmd.fcoecaps = 0; - - /* - * And now tell the firmware to use the configuration we just loaded. - */ - caps_cmd.op_to_write = - htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE); - caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); - ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), - NULL); - if (ret < 0) - goto bye; - - /* - * Tweak configuration based on system architecture, module - * parameters, etc. - */ - ret = adap_init0_tweaks(adapter); - if (ret < 0) - goto bye; - - /* - * And finally tell the firmware to initialize itself using the - * parameters from the Configuration File. - */ - ret = t4_fw_initialize(adapter, adapter->mbox); - if (ret < 0) - goto bye; - - /* - * Return successfully and note that we're operating with parameters - * not supplied by the driver, rather than from hard-wired - * initialization constants burried in the driver. - */ - adapter->flags |= USING_SOFT_PARAMS; - dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\ - "Configuration File %s, version %#x, computed checksum %#x\n", - (using_flash - ? "in device FLASH" - : "/lib/firmware/" FW_CFNAME), - finiver, cfcsum); - return 0; - - /* - * Something bad happened. Return the error ... (If the "error" - * is that there's no Configuration File on the adapter we don't - * want to issue a warning since this is fairly common.) - */ -bye: - if (ret != -ENOENT) - dev_warn(adapter->pdev_dev, "Configuration file error %d\n", - -ret); - return ret; -} - -/* - * Attempt to initialize the adapter via hard-coded, driver supplied - * parameters ... - */ -static int adap_init0_no_config(struct adapter *adapter, int reset) -{ - struct sge *s = &adapter->sge; - struct fw_caps_config_cmd caps_cmd; - u32 v; - int i, ret; - - /* - * Reset device if necessary - */ - if (reset) { - ret = t4_fw_reset(adapter, adapter->mbox, - PIORSTMODE | PIORST); - if (ret < 0) - goto bye; - } - - /* - * Get device capabilities and select which we'll be using. - */ - memset(&caps_cmd, 0, sizeof(caps_cmd)); - caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_READ); - caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); - ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), - &caps_cmd); - if (ret < 0) - goto bye; - -#ifndef CONFIG_CHELSIO_T4_OFFLOAD - /* - * If we're a pure NIC driver then disable all offloading facilities. - * This will allow the firmware to optimize aspects of the hardware - * configuration which will result in improved performance. - */ - caps_cmd.ofldcaps = 0; - caps_cmd.iscsicaps = 0; - caps_cmd.rdmacaps = 0; - caps_cmd.fcoecaps = 0; -#endif - - if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) { - if (!vf_acls) - caps_cmd.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM); - else - caps_cmd.niccaps = htons(FW_CAPS_CONFIG_NIC_VM); - } else if (vf_acls) { - dev_err(adapter->pdev_dev, "virtualization ACLs not supported"); - goto bye; - } - caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_WRITE); - ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), - NULL); - if (ret < 0) - goto bye; - - /* - * Tweak configuration based on system architecture, module - * parameters, etc. - */ - ret = adap_init0_tweaks(adapter); - if (ret < 0) - goto bye; - - /* - * Select RSS Global Mode we want to use. We use "Basic Virtual" - * mode which maps each Virtual Interface to its own section of - * the RSS Table and we turn on all map and hash enables ... - */ - adapter->flags |= RSS_TNLALLLOOKUP; - ret = t4_config_glbl_rss(adapter, adapter->mbox, - FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL, - FW_RSS_GLB_CONFIG_CMD_TNLMAPEN | - FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ | - ((adapter->flags & RSS_TNLALLLOOKUP) ? - FW_RSS_GLB_CONFIG_CMD_TNLALLLKP : 0)); - if (ret < 0) - goto bye; - - /* - * Set up our own fundamental resource provisioning ... - */ - ret = t4_cfg_pfvf(adapter, adapter->mbox, adapter->fn, 0, - PFRES_NEQ, PFRES_NETHCTRL, - PFRES_NIQFLINT, PFRES_NIQ, - PFRES_TC, PFRES_NVI, - FW_PFVF_CMD_CMASK_MASK, - pfvfres_pmask(adapter, adapter->fn, 0), - PFRES_NEXACTF, - PFRES_R_CAPS, PFRES_WX_CAPS); - if (ret < 0) - goto bye; - - /* - * Perform low level SGE initialization. We need to do this before we - * send the firmware the INITIALIZE command because that will cause - * any other PF Drivers which are waiting for the Master - * Initialization to proceed forward. - */ - for (i = 0; i < SGE_NTIMERS - 1; i++) - s->timer_val[i] = min(intr_holdoff[i], MAX_SGE_TIMERVAL); - s->timer_val[SGE_NTIMERS - 1] = MAX_SGE_TIMERVAL; - s->counter_val[0] = 1; - for (i = 1; i < SGE_NCOUNTERS; i++) - s->counter_val[i] = min(intr_cnt[i - 1], - THRESHOLD_0_GET(THRESHOLD_0_MASK)); - t4_sge_init(adapter); - -#ifdef CONFIG_PCI_IOV - /* - * Provision resource limits for Virtual Functions. We currently - * grant them all the same static resource limits except for the Port - * Access Rights Mask which we're assigning based on the PF. All of - * the static provisioning stuff for both the PF and VF really needs - * to be managed in a persistent manner for each device which the - * firmware controls. - */ - { - int pf, vf; - - for (pf = 0; pf < ARRAY_SIZE(num_vf); pf++) { - if (num_vf[pf] <= 0) - continue; - - /* VF numbering starts at 1! */ - for (vf = 1; vf <= num_vf[pf]; vf++) { - ret = t4_cfg_pfvf(adapter, adapter->mbox, - pf, vf, - VFRES_NEQ, VFRES_NETHCTRL, - VFRES_NIQFLINT, VFRES_NIQ, - VFRES_TC, VFRES_NVI, - FW_PFVF_CMD_CMASK_GET( - FW_PFVF_CMD_CMASK_MASK), - pfvfres_pmask( - adapter, pf, vf), - VFRES_NEXACTF, - VFRES_R_CAPS, VFRES_WX_CAPS); - if (ret < 0) - dev_warn(adapter->pdev_dev, - "failed to "\ - "provision pf/vf=%d/%d; " - "err=%d\n", pf, vf, ret); - } - } - } -#endif - - /* - * Set up the default filter mode. Later we'll want to implement this - * via a firmware command, etc. ... This needs to be done before the - * firmare initialization command ... If the selected set of fields - * isn't equal to the default value, we'll need to make sure that the - * field selections will fit in the 36-bit budget. - */ - if (tp_vlan_pri_map != TP_VLAN_PRI_MAP_DEFAULT) { - int i, bits = 0; - - for (i = TP_VLAN_PRI_MAP_FIRST; i <= TP_VLAN_PRI_MAP_LAST; i++) - switch (tp_vlan_pri_map & (1 << i)) { - case 0: - /* compressed filter field not enabled */ - break; - case FCOE_MASK: - bits += 1; - break; - case PORT_MASK: - bits += 3; - break; - case VNIC_ID_MASK: - bits += 17; - break; - case VLAN_MASK: - bits += 17; - break; - case TOS_MASK: - bits += 8; - break; - case PROTOCOL_MASK: - bits += 8; - break; - case ETHERTYPE_MASK: - bits += 16; - break; - case MACMATCH_MASK: - bits += 9; - break; - case MPSHITTYPE_MASK: - bits += 3; - break; - case FRAGMENTATION_MASK: - bits += 1; - break; - } - - if (bits > 36) { - dev_err(adapter->pdev_dev, - "tp_vlan_pri_map=%#x needs %d bits > 36;"\ - " using %#x\n", tp_vlan_pri_map, bits, - TP_VLAN_PRI_MAP_DEFAULT); - tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT; - } - } - v = tp_vlan_pri_map; - t4_write_indirect(adapter, TP_PIO_ADDR, TP_PIO_DATA, - &v, 1, TP_VLAN_PRI_MAP); - - /* - * We need Five Tuple Lookup mode to be set in TP_GLOBAL_CONFIG order - * to support any of the compressed filter fields above. Newer - * versions of the firmware do this automatically but it doesn't hurt - * to set it here. Meanwhile, we do _not_ need to set Lookup Every - * Packet in TP_INGRESS_CONFIG to support matching non-TCP packets - * since the firmware automatically turns this on and off when we have - * a non-zero number of filters active (since it does have a - * performance impact). - */ - if (tp_vlan_pri_map) - t4_set_reg_field(adapter, TP_GLOBAL_CONFIG, - FIVETUPLELOOKUP_MASK, - FIVETUPLELOOKUP_MASK); - - /* - * Tweak some settings. - */ - t4_write_reg(adapter, TP_SHIFT_CNT, SYNSHIFTMAX(6) | - RXTSHIFTMAXR1(4) | RXTSHIFTMAXR2(15) | - PERSHIFTBACKOFFMAX(8) | PERSHIFTMAX(8) | - KEEPALIVEMAXR1(4) | KEEPALIVEMAXR2(9)); - - /* - * Get basic stuff going by issuing the Firmware Initialize command. - * Note that this _must_ be after all PFVF commands ... - */ - ret = t4_fw_initialize(adapter, adapter->mbox); - if (ret < 0) - goto bye; - - /* - * Return successfully! - */ - dev_info(adapter->pdev_dev, "Successfully configured using built-in "\ - "driver parameters\n"); - return 0; - - /* - * Something bad happened. Return the error ... - */ -bye: - return ret; -} - /* * Phase 0 of initialization: contact FW, obtain config, perform basic init. */ @@ -3739,216 +3162,72 @@ static int adap_init0(struct adapter *adap) u32 v, port_vec; enum dev_state state; u32 params[7], val[7]; - int reset = 1, j; + struct fw_caps_config_cmd c; - /* - * Contact FW, advertising Master capability (and potentially forcing - * ourselves as the Master PF if our module parameter force_init is - * set). - */ - ret = t4_fw_hello(adap, adap->mbox, adap->fn, - force_init ? MASTER_MUST : MASTER_MAY, - &state); + ret = t4_check_fw_version(adap); + if (ret == -EINVAL || ret > 0) { + if (upgrade_fw(adap) >= 0) /* recache FW version */ + ret = t4_check_fw_version(adap); + } + if (ret < 0) + return ret; + + /* contact FW, request master */ + ret = t4_fw_hello(adap, adap->fn, adap->fn, MASTER_MUST, &state); if (ret < 0) { dev_err(adap->pdev_dev, "could not connect to FW, error %d\n", ret); return ret; } - if (ret == adap->mbox) - adap->flags |= MASTER_PF; - if (force_init && state == DEV_STATE_INIT) - state = DEV_STATE_UNINIT; - - /* - * If we're the Master PF Driver and the device is uninitialized, - * then let's consider upgrading the firmware ... (We always want - * to check the firmware version number in order to A. get it for - * later reporting and B. to warn if the currently loaded firmware - * is excessively mismatched relative to the driver.) - */ - ret = t4_check_fw_version(adap); - if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) { - if (ret == -EINVAL || ret > 0) { - if (upgrade_fw(adap) >= 0) { - /* - * Note that the chip was reset as part of the - * firmware upgrade so we don't reset it again - * below and grab the new firmware version. - */ - reset = 0; - ret = t4_check_fw_version(adap); - } - } - if (ret < 0) - return ret; - } - /* - * Grab VPD parameters. This should be done after we establish a - * connection to the firmware since some of the VPD parameters - * (notably the Core Clock frequency) are retrieved via requests to - * the firmware. On the other hand, we need these fairly early on - * so we do this right after getting ahold of the firmware. - */ - ret = get_vpd_params(adap, &adap->params.vpd); + /* reset device */ + ret = t4_fw_reset(adap, adap->fn, PIORSTMODE | PIORST); if (ret < 0) goto bye; - /* - * Find out what ports are available to us. Note that we need to do - * this before calling adap_init0_no_config() since it needs nports - * and portvec ... - */ - v = - FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PORTVEC); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 1, &v, &port_vec); + for (v = 0; v < SGE_NTIMERS - 1; v++) + adap->sge.timer_val[v] = min(intr_holdoff[v], MAX_SGE_TIMERVAL); + adap->sge.timer_val[SGE_NTIMERS - 1] = MAX_SGE_TIMERVAL; + adap->sge.counter_val[0] = 1; + for (v = 1; v < SGE_NCOUNTERS; v++) + adap->sge.counter_val[v] = min(intr_cnt[v - 1], + THRESHOLD_3_MASK); +#define FW_PARAM_DEV(param) \ + (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ + FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) + + params[0] = FW_PARAM_DEV(CCLK); + ret = t4_query_params(adap, adap->fn, adap->fn, 0, 1, params, val); if (ret < 0) goto bye; + adap->params.vpd.cclk = val[0]; - adap->params.nports = hweight32(port_vec); - adap->params.portvec = port_vec; - - /* - * If the firmware is initialized already (and we're not forcing a - * master initialization), note that we're living with existing - * adapter parameters. Otherwise, it's time to try initializing the - * adapter ... - */ - if (state == DEV_STATE_INIT) { - dev_info(adap->pdev_dev, "Coming up as %s: "\ - "Adapter already initialized\n", - adap->flags & MASTER_PF ? "MASTER" : "SLAVE"); - adap->flags |= USING_SOFT_PARAMS; - } else { - dev_info(adap->pdev_dev, "Coming up as MASTER: "\ - "Initializing adapter\n"); - - /* - * If the firmware doesn't support Configuration - * Files warn user and exit, - */ - if (ret < 0) - dev_warn(adap->pdev_dev, "Firmware doesn't support " - "configuration file.\n"); - if (force_old_init) - ret = adap_init0_no_config(adap, reset); - else { - /* - * Find out whether we're dealing with a version of - * the firmware which has configuration file support. - */ - params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF)); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 1, - params, val); - - /* - * If the firmware doesn't support Configuration - * Files, use the old Driver-based, hard-wired - * initialization. Otherwise, try using the - * Configuration File support and fall back to the - * Driver-based initialization if there's no - * Configuration File found. - */ - if (ret < 0) - ret = adap_init0_no_config(adap, reset); - else { - /* - * The firmware provides us with a memory - * buffer where we can load a Configuration - * File from the host if we want to override - * the Configuration File in flash. - */ - - ret = adap_init0_config(adap, reset); - if (ret == -ENOENT) { - dev_info(adap->pdev_dev, - "No Configuration File present " - "on adapter. Using hard-wired " - "configuration parameters.\n"); - ret = adap_init0_no_config(adap, reset); - } - } - } - if (ret < 0) { - dev_err(adap->pdev_dev, - "could not initialize adapter, error %d\n", - -ret); - goto bye; - } - } - - /* - * If we're living with non-hard-coded parameters (either from a - * Firmware Configuration File or values programmed by a different PF - * Driver), give the SGE code a chance to pull in anything that it - * needs ... Note that this must be called after we retrieve our VPD - * parameters in order to know how to convert core ticks to seconds. - */ - if (adap->flags & USING_SOFT_PARAMS) { - ret = t4_sge_init(adap); - if (ret < 0) - goto bye; - } - - /* - * Grab some of our basic fundamental operating parameters. - */ -#define FW_PARAM_DEV(param) \ - (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) + ret = adap_init1(adap, &c); + if (ret < 0) + goto bye; #define FW_PARAM_PFVF(param) \ - FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)| \ - FW_PARAMS_PARAM_Y(0) | \ - FW_PARAMS_PARAM_Z(0) + (FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ + FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param) | \ + FW_PARAMS_PARAM_Y(adap->fn)) - params[0] = FW_PARAM_PFVF(EQ_START); + params[0] = FW_PARAM_DEV(PORTVEC); params[1] = FW_PARAM_PFVF(L2T_START); params[2] = FW_PARAM_PFVF(L2T_END); params[3] = FW_PARAM_PFVF(FILTER_START); params[4] = FW_PARAM_PFVF(FILTER_END); params[5] = FW_PARAM_PFVF(IQFLINT_START); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 6, params, val); + params[6] = FW_PARAM_PFVF(EQ_START); + ret = t4_query_params(adap, adap->fn, adap->fn, 0, 7, params, val); if (ret < 0) goto bye; - adap->sge.egr_start = val[0]; - adap->l2t_start = val[1]; - adap->l2t_end = val[2]; + port_vec = val[0]; adap->tids.ftid_base = val[3]; adap->tids.nftids = val[4] - val[3] + 1; adap->sge.ingr_start = val[5]; + adap->sge.egr_start = val[6]; - /* query params related to active filter region */ - params[0] = FW_PARAM_PFVF(ACTIVE_FILTER_START); - params[1] = FW_PARAM_PFVF(ACTIVE_FILTER_END); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, params, val); - /* If Active filter size is set we enable establishing - * offload connection through firmware work request - */ - if ((val[0] != val[1]) && (ret >= 0)) { - adap->flags |= FW_OFLD_CONN; - adap->tids.aftid_base = val[0]; - adap->tids.aftid_end = val[1]; - } - -#ifdef CONFIG_CHELSIO_T4_OFFLOAD - /* - * Get device capabilities so we can determine what resources we need - * to manage. - */ - memset(&caps_cmd, 0, sizeof(caps_cmd)); - caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_READ); - caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); - ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd), - &caps_cmd); - if (ret < 0) - goto bye; - - if (caps_cmd.ofldcaps) { + if (c.ofldcaps) { /* query offload-related parameters */ params[0] = FW_PARAM_DEV(NTID); params[1] = FW_PARAM_PFVF(SERVER_START); @@ -3956,55 +3235,28 @@ static int adap_init0(struct adapter *adap) params[3] = FW_PARAM_PFVF(TDDP_START); params[4] = FW_PARAM_PFVF(TDDP_END); params[5] = FW_PARAM_DEV(FLOWC_BUFFIFO_SZ); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 6, - params, val); + ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params, + val); if (ret < 0) goto bye; adap->tids.ntids = val[0]; adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS); adap->tids.stid_base = val[1]; adap->tids.nstids = val[2] - val[1] + 1; - /* - * Setup server filter region. Divide the availble filter - * region into two parts. Regular filters get 1/3rd and server - * filters get 2/3rd part. This is only enabled if workarond - * path is enabled. - * 1. For regular filters. - * 2. Server filter: This are special filters which are used - * to redirect SYN packets to offload queue. - */ - if (adap->flags & FW_OFLD_CONN && !is_bypass(adap)) { - adap->tids.sftid_base = adap->tids.ftid_base + - DIV_ROUND_UP(adap->tids.nftids, 3); - adap->tids.nsftids = adap->tids.nftids - - DIV_ROUND_UP(adap->tids.nftids, 3); - adap->tids.nftids = adap->tids.sftid_base - - adap->tids.ftid_base; - } adap->vres.ddp.start = val[3]; adap->vres.ddp.size = val[4] - val[3] + 1; adap->params.ofldq_wr_cred = val[5]; - - params[0] = FW_PARAM_PFVF(ETHOFLD_START); - params[1] = FW_PARAM_PFVF(ETHOFLD_END); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, - params, val); - if ((val[0] != val[1]) && (ret >= 0)) { - adap->tids.uotid_base = val[0]; - adap->tids.nuotids = val[1] - val[0] + 1; - } - adap->params.offload = 1; } - if (caps_cmd.rdmacaps) { + if (c.rdmacaps) { params[0] = FW_PARAM_PFVF(STAG_START); params[1] = FW_PARAM_PFVF(STAG_END); params[2] = FW_PARAM_PFVF(RQ_START); params[3] = FW_PARAM_PFVF(RQ_END); params[4] = FW_PARAM_PFVF(PBL_START); params[5] = FW_PARAM_PFVF(PBL_END); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 6, - params, val); + ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params, + val); if (ret < 0) goto bye; adap->vres.stag.start = val[0]; @@ -4020,7 +3272,8 @@ static int adap_init0(struct adapter *adap) params[3] = FW_PARAM_PFVF(CQ_END); params[4] = FW_PARAM_PFVF(OCQ_START); params[5] = FW_PARAM_PFVF(OCQ_END); - ret = t4_query_params(adap, 0, 0, 0, 6, params, val); + ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params, + val); if (ret < 0) goto bye; adap->vres.qp.start = val[0]; @@ -4030,11 +3283,11 @@ static int adap_init0(struct adapter *adap) adap->vres.ocq.start = val[4]; adap->vres.ocq.size = val[5] - val[4] + 1; } - if (caps_cmd.iscsicaps) { + if (c.iscsicaps) { params[0] = FW_PARAM_PFVF(ISCSI_START); params[1] = FW_PARAM_PFVF(ISCSI_END); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, - params, val); + ret = t4_query_params(adap, adap->fn, adap->fn, 0, 2, params, + val); if (ret < 0) goto bye; adap->vres.iscsi.start = val[0]; @@ -4042,33 +3295,63 @@ static int adap_init0(struct adapter *adap) } #undef FW_PARAM_PFVF #undef FW_PARAM_DEV -#endif /* CONFIG_CHELSIO_T4_OFFLOAD */ - /* - * These are finalized by FW initialization, load their values now. - */ + adap->params.nports = hweight32(port_vec); + adap->params.portvec = port_vec; + adap->flags |= FW_OK; + + /* These are finalized by FW initialization, load their values now */ v = t4_read_reg(adap, TP_TIMER_RESOLUTION); adap->params.tp.tre = TIMERRESOLUTION_GET(v); - adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v); t4_read_mtu_tbl(adap, adap->params.mtus, NULL); t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd, adap->params.b_wnd); - /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */ - for (j = 0; j < NCHAN; j++) - adap->params.tp.tx_modq[j] = j; +#ifdef CONFIG_PCI_IOV + /* + * Provision resource limits for Virtual Functions. We currently + * grant them all the same static resource limits except for the Port + * Access Rights Mask which we're assigning based on the PF. All of + * the static provisioning stuff for both the PF and VF really needs + * to be managed in a persistent manner for each device which the + * firmware controls. + */ + { + int pf, vf; - adap->flags |= FW_OK; + for (pf = 0; pf < ARRAY_SIZE(num_vf); pf++) { + if (num_vf[pf] <= 0) + continue; + + /* VF numbering starts at 1! */ + for (vf = 1; vf <= num_vf[pf]; vf++) { + ret = t4_cfg_pfvf(adap, adap->fn, pf, vf, + VFRES_NEQ, VFRES_NETHCTRL, + VFRES_NIQFLINT, VFRES_NIQ, + VFRES_TC, VFRES_NVI, + FW_PFVF_CMD_CMASK_MASK, + pfvfres_pmask(adap, pf, vf), + VFRES_NEXACTF, + VFRES_R_CAPS, VFRES_WX_CAPS); + if (ret < 0) + dev_warn(adap->pdev_dev, "failed to " + "provision pf/vf=%d/%d; " + "err=%d\n", pf, vf, ret); + } + } + } +#endif + + setup_memwin(adap); return 0; /* - * Something bad happened. If a command timed out or failed with EIO - * FW does not operate within its spec or something catastrophic - * happened to HW/FW, stop issuing commands. + * If a command timed out or failed with EIO FW does not operate within + * its spec or something catastrophic happened to HW/FW, stop issuing + * commands. */ -bye: - if (ret != -ETIMEDOUT && ret != -EIO) - t4_fw_bye(adap, adap->mbox); +bye: if (ret != -ETIMEDOUT && ret != -EIO) + t4_fw_bye(adap, adap->fn); return ret; } @@ -4531,9 +3814,7 @@ static int __devinit init_one(struct pci_dev *pdev, err = t4_prep_adapter(adapter); if (err) goto out_unmap_bar; - setup_memwin(adapter); err = adap_init0(adapter); - setup_memwin_rdma(adapter); if (err) goto out_unmap_bar; @@ -4675,11 +3956,8 @@ static void __devexit remove_one(struct pci_dev *pdev) { struct adapter *adapter = pci_get_drvdata(pdev); -#ifdef CONFIG_PCI_IOV pci_disable_sriov(pdev); -#endif - if (adapter) { int i; diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 1b899fea1a91..d79980c5fc63 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -100,8 +100,6 @@ struct tid_info { unsigned int nftids; unsigned int ftid_base; - unsigned int aftid_base; - unsigned int aftid_end; spinlock_t atid_lock ____cacheline_aligned_in_smp; union aopen_entry *afree; diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/sge.c b/trunk/drivers/net/ethernet/chelsio/cxgb4/sge.c index 3ecc087d732d..1fde57d45318 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -68,6 +68,9 @@ */ #define RX_PKT_SKB_LEN 512 +/* Ethernet header padding prepended to RX_PKTs */ +#define RX_PKT_PAD 2 + /* * Max number of Tx descriptors we clean up at a time. Should be modest as * freeing skbs isn't cheap and it happens while holding locks. We just need @@ -134,6 +137,13 @@ */ #define MAX_CTRL_WR_LEN SGE_MAX_WR_LEN +enum { + /* packet alignment in FL buffers */ + FL_ALIGN = L1_CACHE_BYTES < 32 ? 32 : L1_CACHE_BYTES, + /* egress status entry size */ + STAT_LEN = L1_CACHE_BYTES > 64 ? 128 : 64 +}; + struct tx_sw_desc { /* SW state per Tx descriptor */ struct sk_buff *skb; struct ulptx_sgl *sgl; @@ -145,57 +155,16 @@ struct rx_sw_desc { /* SW state per Rx descriptor */ }; /* - * Rx buffer sizes for "useskbs" Free List buffers (one ingress packet pe skb - * buffer). We currently only support two sizes for 1500- and 9000-byte MTUs. - * We could easily support more but there doesn't seem to be much need for - * that ... - */ -#define FL_MTU_SMALL 1500 -#define FL_MTU_LARGE 9000 - -static inline unsigned int fl_mtu_bufsize(struct adapter *adapter, - unsigned int mtu) -{ - struct sge *s = &adapter->sge; - - return ALIGN(s->pktshift + ETH_HLEN + VLAN_HLEN + mtu, s->fl_align); -} - -#define FL_MTU_SMALL_BUFSIZE(adapter) fl_mtu_bufsize(adapter, FL_MTU_SMALL) -#define FL_MTU_LARGE_BUFSIZE(adapter) fl_mtu_bufsize(adapter, FL_MTU_LARGE) - -/* - * Bits 0..3 of rx_sw_desc.dma_addr have special meaning. The hardware uses - * these to specify the buffer size as an index into the SGE Free List Buffer - * Size register array. We also use bit 4, when the buffer has been unmapped - * for DMA, but this is of course never sent to the hardware and is only used - * to prevent double unmappings. All of the above requires that the Free List - * Buffers which we allocate have the bottom 5 bits free (0) -- i.e. are - * 32-byte or or a power of 2 greater in alignment. Since the SGE's minimal - * Free List Buffer alignment is 32 bytes, this works out for us ... + * The low bits of rx_sw_desc.dma_addr have special meaning. */ enum { - RX_BUF_FLAGS = 0x1f, /* bottom five bits are special */ - RX_BUF_SIZE = 0x0f, /* bottom three bits are for buf sizes */ - RX_UNMAPPED_BUF = 0x10, /* buffer is not mapped */ - - /* - * XXX We shouldn't depend on being able to use these indices. - * XXX Especially when some other Master PF has initialized the - * XXX adapter or we use the Firmware Configuration File. We - * XXX should really search through the Host Buffer Size register - * XXX array for the appropriately sized buffer indices. - */ - RX_SMALL_PG_BUF = 0x0, /* small (PAGE_SIZE) page buffer */ - RX_LARGE_PG_BUF = 0x1, /* buffer large (FL_PG_ORDER) page buffer */ - - RX_SMALL_MTU_BUF = 0x2, /* small MTU buffer */ - RX_LARGE_MTU_BUF = 0x3, /* large MTU buffer */ + RX_LARGE_BUF = 1 << 0, /* buffer is larger than PAGE_SIZE */ + RX_UNMAPPED_BUF = 1 << 1, /* buffer is not mapped */ }; static inline dma_addr_t get_buf_addr(const struct rx_sw_desc *d) { - return d->dma_addr & ~(dma_addr_t)RX_BUF_FLAGS; + return d->dma_addr & ~(dma_addr_t)(RX_LARGE_BUF | RX_UNMAPPED_BUF); } static inline bool is_buf_mapped(const struct rx_sw_desc *d) @@ -423,35 +392,14 @@ static inline void reclaim_completed_tx(struct adapter *adap, struct sge_txq *q, } } -static inline int get_buf_size(struct adapter *adapter, - const struct rx_sw_desc *d) +static inline int get_buf_size(const struct rx_sw_desc *d) { - struct sge *s = &adapter->sge; - unsigned int rx_buf_size_idx = d->dma_addr & RX_BUF_SIZE; - int buf_size; - - switch (rx_buf_size_idx) { - case RX_SMALL_PG_BUF: - buf_size = PAGE_SIZE; - break; - - case RX_LARGE_PG_BUF: - buf_size = PAGE_SIZE << s->fl_pg_order; - break; - - case RX_SMALL_MTU_BUF: - buf_size = FL_MTU_SMALL_BUFSIZE(adapter); - break; - - case RX_LARGE_MTU_BUF: - buf_size = FL_MTU_LARGE_BUFSIZE(adapter); - break; - - default: - BUG_ON(1); - } - - return buf_size; +#if FL_PG_ORDER > 0 + return (d->dma_addr & RX_LARGE_BUF) ? (PAGE_SIZE << FL_PG_ORDER) : + PAGE_SIZE; +#else + return PAGE_SIZE; +#endif } /** @@ -470,8 +418,7 @@ static void free_rx_bufs(struct adapter *adap, struct sge_fl *q, int n) if (is_buf_mapped(d)) dma_unmap_page(adap->pdev_dev, get_buf_addr(d), - get_buf_size(adap, d), - PCI_DMA_FROMDEVICE); + get_buf_size(d), PCI_DMA_FROMDEVICE); put_page(d->page); d->page = NULL; if (++q->cidx == q->size) @@ -497,7 +444,7 @@ static void unmap_rx_buf(struct adapter *adap, struct sge_fl *q) if (is_buf_mapped(d)) dma_unmap_page(adap->pdev_dev, get_buf_addr(d), - get_buf_size(adap, d), PCI_DMA_FROMDEVICE); + get_buf_size(d), PCI_DMA_FROMDEVICE); d->page = NULL; if (++q->cidx == q->size) q->cidx = 0; @@ -538,7 +485,6 @@ static inline void set_rx_sw_desc(struct rx_sw_desc *sd, struct page *pg, static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) { - struct sge *s = &adap->sge; struct page *pg; dma_addr_t mapping; unsigned int cred = q->avail; @@ -547,27 +493,25 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp |= __GFP_NOWARN | __GFP_COLD; - if (s->fl_pg_order == 0) - goto alloc_small_pages; - +#if FL_PG_ORDER > 0 /* * Prefer large buffers */ while (n) { - pg = alloc_pages(gfp | __GFP_COMP, s->fl_pg_order); + pg = alloc_pages(gfp | __GFP_COMP, FL_PG_ORDER); if (unlikely(!pg)) { q->large_alloc_failed++; break; /* fall back to single pages */ } mapping = dma_map_page(adap->pdev_dev, pg, 0, - PAGE_SIZE << s->fl_pg_order, + PAGE_SIZE << FL_PG_ORDER, PCI_DMA_FROMDEVICE); if (unlikely(dma_mapping_error(adap->pdev_dev, mapping))) { - __free_pages(pg, s->fl_pg_order); + __free_pages(pg, FL_PG_ORDER); goto out; /* do not try small pages for this error */ } - mapping |= RX_LARGE_PG_BUF; + mapping |= RX_LARGE_BUF; *d++ = cpu_to_be64(mapping); set_rx_sw_desc(sd, pg, mapping); @@ -581,8 +525,8 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n, } n--; } +#endif -alloc_small_pages: while (n--) { pg = __skb_alloc_page(gfp, NULL); if (unlikely(!pg)) { @@ -1575,8 +1519,6 @@ static noinline int handle_trace_pkt(struct adapter *adap, static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl, const struct cpl_rx_pkt *pkt) { - struct adapter *adapter = rxq->rspq.adap; - struct sge *s = &adapter->sge; int ret; struct sk_buff *skb; @@ -1587,8 +1529,8 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl, return; } - copy_frags(skb, gl, s->pktshift); - skb->len = gl->tot_len - s->pktshift; + copy_frags(skb, gl, RX_PKT_PAD); + skb->len = gl->tot_len - RX_PKT_PAD; skb->data_len = skb->len; skb->truesize += skb->data_len; skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -1624,7 +1566,6 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, struct sk_buff *skb; const struct cpl_rx_pkt *pkt; struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq); - struct sge *s = &q->adap->sge; if (unlikely(*(u8 *)rsp == CPL_TRACE_PKT)) return handle_trace_pkt(q->adap, si); @@ -1644,7 +1585,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, return 0; } - __skb_pull(skb, s->pktshift); /* remove ethernet header padding */ + __skb_pull(skb, RX_PKT_PAD); /* remove ethernet header padding */ skb->protocol = eth_type_trans(skb, q->netdev); skb_record_rx_queue(skb, q->idx); if (skb->dev->features & NETIF_F_RXHASH) @@ -1755,8 +1696,6 @@ static int process_responses(struct sge_rspq *q, int budget) int budget_left = budget; const struct rsp_ctrl *rc; struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq); - struct adapter *adapter = q->adap; - struct sge *s = &adapter->sge; while (likely(budget_left)) { rc = (void *)q->cur_desc + (q->iqe_len - sizeof(*rc)); @@ -1783,7 +1722,7 @@ static int process_responses(struct sge_rspq *q, int budget) /* gather packet fragments */ for (frags = 0, fp = si.frags; ; frags++, fp++) { rsd = &rxq->fl.sdesc[rxq->fl.cidx]; - bufsz = get_buf_size(adapter, rsd); + bufsz = get_buf_size(rsd); fp->page = rsd->page; fp->offset = q->offset; fp->size = min(bufsz, len); @@ -1808,7 +1747,7 @@ static int process_responses(struct sge_rspq *q, int budget) si.nfrags = frags + 1; ret = q->handler(q, q->cur_desc, &si); if (likely(ret == 0)) - q->offset += ALIGN(fp->size, s->fl_align); + q->offset += ALIGN(fp->size, FL_ALIGN); else restore_rx_bufs(&si, &rxq->fl, frags); } else if (likely(rsp_type == RSP_TYPE_CPL)) { @@ -2044,7 +1983,6 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, { int ret, flsz = 0; struct fw_iq_cmd c; - struct sge *s = &adap->sge; struct port_info *pi = netdev_priv(dev); /* Size needs to be multiple of 16, including status entry. */ @@ -2077,11 +2015,11 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, fl->size = roundup(fl->size, 8); fl->desc = alloc_ring(adap->pdev_dev, fl->size, sizeof(__be64), sizeof(struct rx_sw_desc), &fl->addr, - &fl->sdesc, s->stat_len, NUMA_NO_NODE); + &fl->sdesc, STAT_LEN, NUMA_NO_NODE); if (!fl->desc) goto fl_nomem; - flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc); + flsz = fl->size / 8 + STAT_LEN / sizeof(struct tx_desc); c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN | FW_IQ_CMD_FL0FETCHRO(1) | FW_IQ_CMD_FL0DATARO(1) | @@ -2158,15 +2096,14 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, { int ret, nentries; struct fw_eq_eth_cmd c; - struct sge *s = &adap->sge; struct port_info *pi = netdev_priv(dev); /* Add status entries */ - nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc); + nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc); txq->q.desc = alloc_ring(adap->pdev_dev, txq->q.size, sizeof(struct tx_desc), sizeof(struct tx_sw_desc), - &txq->q.phys_addr, &txq->q.sdesc, s->stat_len, + &txq->q.phys_addr, &txq->q.sdesc, STAT_LEN, netdev_queue_numa_node_read(netdevq)); if (!txq->q.desc) return -ENOMEM; @@ -2212,11 +2149,10 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq, { int ret, nentries; struct fw_eq_ctrl_cmd c; - struct sge *s = &adap->sge; struct port_info *pi = netdev_priv(dev); /* Add status entries */ - nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc); + nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc); txq->q.desc = alloc_ring(adap->pdev_dev, nentries, sizeof(struct tx_desc), 0, &txq->q.phys_addr, @@ -2264,15 +2200,14 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq, { int ret, nentries; struct fw_eq_ofld_cmd c; - struct sge *s = &adap->sge; struct port_info *pi = netdev_priv(dev); /* Add status entries */ - nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc); + nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc); txq->q.desc = alloc_ring(adap->pdev_dev, txq->q.size, sizeof(struct tx_desc), sizeof(struct tx_sw_desc), - &txq->q.phys_addr, &txq->q.sdesc, s->stat_len, + &txq->q.phys_addr, &txq->q.sdesc, STAT_LEN, NUMA_NO_NODE); if (!txq->q.desc) return -ENOMEM; @@ -2316,10 +2251,8 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq, static void free_txq(struct adapter *adap, struct sge_txq *q) { - struct sge *s = &adap->sge; - dma_free_coherent(adap->pdev_dev, - q->size * sizeof(struct tx_desc) + s->stat_len, + q->size * sizeof(struct tx_desc) + STAT_LEN, q->desc, q->phys_addr); q->cntxt_id = 0; q->sdesc = NULL; @@ -2329,7 +2262,6 @@ static void free_txq(struct adapter *adap, struct sge_txq *q) static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, struct sge_fl *fl) { - struct sge *s = &adap->sge; unsigned int fl_id = fl ? fl->cntxt_id : 0xffff; adap->sge.ingr_map[rq->cntxt_id - adap->sge.ingr_start] = NULL; @@ -2344,7 +2276,7 @@ static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, if (fl) { free_rx_bufs(adap, fl, fl->avail); - dma_free_coherent(adap->pdev_dev, fl->size * 8 + s->stat_len, + dma_free_coherent(adap->pdev_dev, fl->size * 8 + STAT_LEN, fl->desc, fl->addr); kfree(fl->sdesc); fl->sdesc = NULL; @@ -2476,112 +2408,18 @@ void t4_sge_stop(struct adapter *adap) * Performs SGE initialization needed every time after a chip reset. * We do not initialize any of the queues here, instead the driver * top-level must request them individually. - * - * Called in two different modes: - * - * 1. Perform actual hardware initialization and record hard-coded - * parameters which were used. This gets used when we're the - * Master PF and the Firmware Configuration File support didn't - * work for some reason. - * - * 2. We're not the Master PF or initialization was performed with - * a Firmware Configuration File. In this case we need to grab - * any of the SGE operating parameters that we need to have in - * order to do our job and make sure we can live with them ... */ - -static int t4_sge_init_soft(struct adapter *adap) +void t4_sge_init(struct adapter *adap) { + unsigned int i, v; struct sge *s = &adap->sge; - u32 fl_small_pg, fl_large_pg, fl_small_mtu, fl_large_mtu; - u32 timer_value_0_and_1, timer_value_2_and_3, timer_value_4_and_5; - u32 ingress_rx_threshold; + unsigned int fl_align_log = ilog2(FL_ALIGN); - /* - * Verify that CPL messages are going to the Ingress Queue for - * process_responses() and that only packet data is going to the - * Free Lists. - */ - if ((t4_read_reg(adap, SGE_CONTROL) & RXPKTCPLMODE_MASK) != - RXPKTCPLMODE(X_RXPKTCPLMODE_SPLIT)) { - dev_err(adap->pdev_dev, "bad SGE CPL MODE\n"); - return -EINVAL; - } - - /* - * Validate the Host Buffer Register Array indices that we want to - * use ... - * - * XXX Note that we should really read through the Host Buffer Size - * XXX register array and find the indices of the Buffer Sizes which - * XXX meet our needs! - */ - #define READ_FL_BUF(x) \ - t4_read_reg(adap, SGE_FL_BUFFER_SIZE0+(x)*sizeof(u32)) - - fl_small_pg = READ_FL_BUF(RX_SMALL_PG_BUF); - fl_large_pg = READ_FL_BUF(RX_LARGE_PG_BUF); - fl_small_mtu = READ_FL_BUF(RX_SMALL_MTU_BUF); - fl_large_mtu = READ_FL_BUF(RX_LARGE_MTU_BUF); - - #undef READ_FL_BUF - - if (fl_small_pg != PAGE_SIZE || - (fl_large_pg != 0 && (fl_large_pg <= fl_small_pg || - (fl_large_pg & (fl_large_pg-1)) != 0))) { - dev_err(adap->pdev_dev, "bad SGE FL page buffer sizes [%d, %d]\n", - fl_small_pg, fl_large_pg); - return -EINVAL; - } - if (fl_large_pg) - s->fl_pg_order = ilog2(fl_large_pg) - PAGE_SHIFT; - - if (fl_small_mtu < FL_MTU_SMALL_BUFSIZE(adap) || - fl_large_mtu < FL_MTU_LARGE_BUFSIZE(adap)) { - dev_err(adap->pdev_dev, "bad SGE FL MTU sizes [%d, %d]\n", - fl_small_mtu, fl_large_mtu); - return -EINVAL; - } - - /* - * Retrieve our RX interrupt holdoff timer values and counter - * threshold values from the SGE parameters. - */ - timer_value_0_and_1 = t4_read_reg(adap, SGE_TIMER_VALUE_0_AND_1); - timer_value_2_and_3 = t4_read_reg(adap, SGE_TIMER_VALUE_2_AND_3); - timer_value_4_and_5 = t4_read_reg(adap, SGE_TIMER_VALUE_4_AND_5); - s->timer_val[0] = core_ticks_to_us(adap, - TIMERVALUE0_GET(timer_value_0_and_1)); - s->timer_val[1] = core_ticks_to_us(adap, - TIMERVALUE1_GET(timer_value_0_and_1)); - s->timer_val[2] = core_ticks_to_us(adap, - TIMERVALUE2_GET(timer_value_2_and_3)); - s->timer_val[3] = core_ticks_to_us(adap, - TIMERVALUE3_GET(timer_value_2_and_3)); - s->timer_val[4] = core_ticks_to_us(adap, - TIMERVALUE4_GET(timer_value_4_and_5)); - s->timer_val[5] = core_ticks_to_us(adap, - TIMERVALUE5_GET(timer_value_4_and_5)); - - ingress_rx_threshold = t4_read_reg(adap, SGE_INGRESS_RX_THRESHOLD); - s->counter_val[0] = THRESHOLD_0_GET(ingress_rx_threshold); - s->counter_val[1] = THRESHOLD_1_GET(ingress_rx_threshold); - s->counter_val[2] = THRESHOLD_2_GET(ingress_rx_threshold); - s->counter_val[3] = THRESHOLD_3_GET(ingress_rx_threshold); - - return 0; -} - -static int t4_sge_init_hard(struct adapter *adap) -{ - struct sge *s = &adap->sge; - - /* - * Set up our basic SGE mode to deliver CPL messages to our Ingress - * Queue and Packet Date to the Free List. - */ - t4_set_reg_field(adap, SGE_CONTROL, RXPKTCPLMODE_MASK, - RXPKTCPLMODE_MASK); + t4_set_reg_field(adap, SGE_CONTROL, PKTSHIFT_MASK | + INGPADBOUNDARY_MASK | EGRSTATUSPAGESIZE, + INGPADBOUNDARY(fl_align_log - 5) | PKTSHIFT(2) | + RXPKTCPLMODE | + (STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0)); /* * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows @@ -2595,24 +2433,13 @@ static int t4_sge_init_hard(struct adapter *adap) t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_ENABLE_DROP, F_ENABLE_DROP); - /* - * SGE_FL_BUFFER_SIZE0 (RX_SMALL_PG_BUF) is set up by - * t4_fixup_host_params(). - */ - s->fl_pg_order = FL_PG_ORDER; - if (s->fl_pg_order) - t4_write_reg(adap, - SGE_FL_BUFFER_SIZE0+RX_LARGE_PG_BUF*sizeof(u32), - PAGE_SIZE << FL_PG_ORDER); - t4_write_reg(adap, SGE_FL_BUFFER_SIZE0+RX_SMALL_MTU_BUF*sizeof(u32), - FL_MTU_SMALL_BUFSIZE(adap)); - t4_write_reg(adap, SGE_FL_BUFFER_SIZE0+RX_LARGE_MTU_BUF*sizeof(u32), - FL_MTU_LARGE_BUFSIZE(adap)); - - /* - * Note that the SGE Ingress Packet Count Interrupt Threshold and - * Timer Holdoff values must be supplied by our caller. - */ + for (i = v = 0; i < 32; i += 4) + v |= (PAGE_SHIFT - 10) << i; + t4_write_reg(adap, SGE_HOST_PAGE_SIZE, v); + t4_write_reg(adap, SGE_FL_BUFFER_SIZE0, PAGE_SIZE); +#if FL_PG_ORDER > 0 + t4_write_reg(adap, SGE_FL_BUFFER_SIZE1, PAGE_SIZE << FL_PG_ORDER); +#endif t4_write_reg(adap, SGE_INGRESS_RX_THRESHOLD, THRESHOLD_0(s->counter_val[0]) | THRESHOLD_1(s->counter_val[1]) | @@ -2622,54 +2449,14 @@ static int t4_sge_init_hard(struct adapter *adap) TIMERVALUE0(us_to_core_ticks(adap, s->timer_val[0])) | TIMERVALUE1(us_to_core_ticks(adap, s->timer_val[1]))); t4_write_reg(adap, SGE_TIMER_VALUE_2_AND_3, - TIMERVALUE2(us_to_core_ticks(adap, s->timer_val[2])) | - TIMERVALUE3(us_to_core_ticks(adap, s->timer_val[3]))); + TIMERVALUE0(us_to_core_ticks(adap, s->timer_val[2])) | + TIMERVALUE1(us_to_core_ticks(adap, s->timer_val[3]))); t4_write_reg(adap, SGE_TIMER_VALUE_4_AND_5, - TIMERVALUE4(us_to_core_ticks(adap, s->timer_val[4])) | - TIMERVALUE5(us_to_core_ticks(adap, s->timer_val[5]))); - - return 0; -} - -int t4_sge_init(struct adapter *adap) -{ - struct sge *s = &adap->sge; - u32 sge_control; - int ret; - - /* - * Ingress Padding Boundary and Egress Status Page Size are set up by - * t4_fixup_host_params(). - */ - sge_control = t4_read_reg(adap, SGE_CONTROL); - s->pktshift = PKTSHIFT_GET(sge_control); - s->stat_len = (sge_control & EGRSTATUSPAGESIZE_MASK) ? 128 : 64; - s->fl_align = 1 << (INGPADBOUNDARY_GET(sge_control) + - X_INGPADBOUNDARY_SHIFT); - - if (adap->flags & USING_SOFT_PARAMS) - ret = t4_sge_init_soft(adap); - else - ret = t4_sge_init_hard(adap); - if (ret < 0) - return ret; - - /* - * A FL with <= fl_starve_thres buffers is starving and a periodic - * timer will attempt to refill it. This needs to be larger than the - * SGE's Egress Congestion Threshold. If it isn't, then we can get - * stuck waiting for new packets while the SGE is waiting for us to - * give it more Free List entries. (Note that the SGE's Egress - * Congestion Threshold is in units of 2 Free List pointers.) - */ - s->fl_starve_thres - = EGRTHRESHOLD_GET(t4_read_reg(adap, SGE_CONM_CTRL))*2 + 1; - + TIMERVALUE0(us_to_core_ticks(adap, s->timer_val[4])) | + TIMERVALUE1(us_to_core_ticks(adap, s->timer_val[5]))); setup_timer(&s->rx_timer, sge_rx_timer_cb, (unsigned long)adap); setup_timer(&s->tx_timer, sge_tx_timer_cb, (unsigned long)adap); s->starve_thres = core_ticks_per_usec(adap) * 1000000; /* 1 s */ s->idma_state[0] = s->idma_state[1] = 0; spin_lock_init(&s->intrq_lock); - - return 0; } diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index ab732b378c4f..8e988d699d05 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -120,28 +120,6 @@ static void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, } } -/** - * t4_write_indirect - write indirectly addressed registers - * @adap: the adapter - * @addr_reg: register holding the indirect addresses - * @data_reg: register holding the value for the indirect registers - * @vals: values to write - * @nregs: how many indirect registers to write - * @start_idx: address of first indirect register to write - * - * Writes a sequential block of registers that are accessed indirectly - * through an address/data register pair. - */ -void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, - unsigned int data_reg, const u32 *vals, - unsigned int nregs, unsigned int start_idx) -{ - while (nregs--) { - t4_write_reg(adap, addr_reg, start_idx++); - t4_write_reg(adap, data_reg, *vals++); - } -} - /* * Get the reply to a mailbox command and store it in @rpl in big-endian order. */ @@ -352,143 +330,6 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc) return 0; } -/* - * t4_mem_win_rw - read/write memory through PCIE memory window - * @adap: the adapter - * @addr: address of first byte requested - * @data: MEMWIN0_APERTURE bytes of data containing the requested address - * @dir: direction of transfer 1 => read, 0 => write - * - * Read/write MEMWIN0_APERTURE bytes of data from MC starting at a - * MEMWIN0_APERTURE-byte-aligned address that covers the requested - * address @addr. - */ -static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir) -{ - int i; - - /* - * Setup offset into PCIE memory window. Address must be a - * MEMWIN0_APERTURE-byte-aligned address. (Read back MA register to - * ensure that changes propagate before we attempt to use the new - * values.) - */ - t4_write_reg(adap, PCIE_MEM_ACCESS_OFFSET, - addr & ~(MEMWIN0_APERTURE - 1)); - t4_read_reg(adap, PCIE_MEM_ACCESS_OFFSET); - - /* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */ - for (i = 0; i < MEMWIN0_APERTURE; i = i+0x4) { - if (dir) - *data++ = t4_read_reg(adap, (MEMWIN0_BASE + i)); - else - t4_write_reg(adap, (MEMWIN0_BASE + i), *data++); - } - - return 0; -} - -/** - * t4_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window - * @adap: the adapter - * @mtype: memory type: MEM_EDC0, MEM_EDC1 or MEM_MC - * @addr: address within indicated memory type - * @len: amount of memory to transfer - * @buf: host memory buffer - * @dir: direction of transfer 1 => read, 0 => write - * - * Reads/writes an [almost] arbitrary memory region in the firmware: the - * firmware memory address, length and host buffer must be aligned on - * 32-bit boudaries. The memory is transferred as a raw byte sequence - * from/to the firmware's memory. If this memory contains data - * structures which contain multi-byte integers, it's the callers - * responsibility to perform appropriate byte order conversions. - */ -static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len, - __be32 *buf, int dir) -{ - u32 pos, start, end, offset, memoffset; - int ret; - - /* - * Argument sanity checks ... - */ - if ((addr & 0x3) || (len & 0x3)) - return -EINVAL; - - /* - * Offset into the region of memory which is being accessed - * MEM_EDC0 = 0 - * MEM_EDC1 = 1 - * MEM_MC = 2 - */ - memoffset = (mtype * (5 * 1024 * 1024)); - - /* Determine the PCIE_MEM_ACCESS_OFFSET */ - addr = addr + memoffset; - - /* - * The underlaying EDC/MC read routines read MEMWIN0_APERTURE bytes - * at a time so we need to round down the start and round up the end. - * We'll start copying out of the first line at (addr - start) a word - * at a time. - */ - start = addr & ~(MEMWIN0_APERTURE-1); - end = (addr + len + MEMWIN0_APERTURE-1) & ~(MEMWIN0_APERTURE-1); - offset = (addr - start)/sizeof(__be32); - - for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) { - __be32 data[MEMWIN0_APERTURE/sizeof(__be32)]; - - /* - * If we're writing, copy the data from the caller's memory - * buffer - */ - if (!dir) { - /* - * If we're doing a partial write, then we need to do - * a read-modify-write ... - */ - if (offset || len < MEMWIN0_APERTURE) { - ret = t4_mem_win_rw(adap, pos, data, 1); - if (ret) - return ret; - } - while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) && - len > 0) { - data[offset++] = *buf++; - len -= sizeof(__be32); - } - } - - /* - * Transfer a block of memory and bail if there's an error. - */ - ret = t4_mem_win_rw(adap, pos, data, dir); - if (ret) - return ret; - - /* - * If we're reading, copy the data into the caller's memory - * buffer. - */ - if (dir) - while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) && - len > 0) { - *buf++ = data[offset++]; - len -= sizeof(__be32); - } - } - - return 0; -} - -int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len, - __be32 *buf) -{ - return t4_memory_rw(adap, mtype, addr, len, buf, 0); -} - #define EEPROM_STAT_ADDR 0x7bfc #define VPD_BASE 0 #define VPD_LEN 512 @@ -514,9 +355,8 @@ int t4_seeprom_wp(struct adapter *adapter, bool enable) * * Reads card parameters stored in VPD EEPROM. */ -int get_vpd_params(struct adapter *adapter, struct vpd_params *p) +static int get_vpd_params(struct adapter *adapter, struct vpd_params *p) { - u32 cclk_param, cclk_val; int i, ret; int ec, sn; u8 vpd[VPD_LEN], csum; @@ -578,19 +418,6 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE); memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN)); strim(p->sn); - - /* - * Ask firmware for the Core Clock since it knows how to translate the - * Reference Clock ('V2') VPD field into a Core Clock value ... - */ - cclk_param = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CCLK)); - ret = t4_query_params(adapter, adapter->mbox, 0, 0, - 1, &cclk_param, &cclk_val); - if (ret) - return ret; - p->cclk = cclk_val; - return 0; } @@ -890,77 +717,6 @@ static int t4_flash_erase_sectors(struct adapter *adapter, int start, int end) return ret; } -/** - * t4_flash_cfg_addr - return the address of the flash configuration file - * @adapter: the adapter - * - * Return the address within the flash where the Firmware Configuration - * File is stored. - */ -unsigned int t4_flash_cfg_addr(struct adapter *adapter) -{ - if (adapter->params.sf_size == 0x100000) - return FLASH_FPGA_CFG_START; - else - return FLASH_CFG_START; -} - -/** - * t4_load_cfg - download config file - * @adap: the adapter - * @cfg_data: the cfg text file to write - * @size: text file size - * - * Write the supplied config text file to the card's serial flash. - */ -int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size) -{ - int ret, i, n; - unsigned int addr; - unsigned int flash_cfg_start_sec; - unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec; - - addr = t4_flash_cfg_addr(adap); - flash_cfg_start_sec = addr / SF_SEC_SIZE; - - if (size > FLASH_CFG_MAX_SIZE) { - dev_err(adap->pdev_dev, "cfg file too large, max is %u bytes\n", - FLASH_CFG_MAX_SIZE); - return -EFBIG; - } - - i = DIV_ROUND_UP(FLASH_CFG_MAX_SIZE, /* # of sectors spanned */ - sf_sec_size); - ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec, - flash_cfg_start_sec + i - 1); - /* - * If size == 0 then we're simply erasing the FLASH sectors associated - * with the on-adapter Firmware Configuration File. - */ - if (ret || size == 0) - goto out; - - /* this will write to the flash up to SF_PAGE_SIZE at a time */ - for (i = 0; i < size; i += SF_PAGE_SIZE) { - if ((size - i) < SF_PAGE_SIZE) - n = size - i; - else - n = SF_PAGE_SIZE; - ret = t4_write_flash(adap, addr, n, cfg_data); - if (ret) - goto out; - - addr += SF_PAGE_SIZE; - cfg_data += SF_PAGE_SIZE; - } - -out: - if (ret) - dev_err(adap->pdev_dev, "config file %s failed %d\n", - (size == 0 ? "clear" : "download"), ret); - return ret; -} - /** * t4_load_fw - download firmware * @adap: the adapter @@ -1960,23 +1716,6 @@ void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log) } } -/** - * t4_tp_wr_bits_indirect - set/clear bits in an indirect TP register - * @adap: the adapter - * @addr: the indirect TP register address - * @mask: specifies the field within the register to modify - * @val: new value for the field - * - * Sets a field of an indirect TP register to the given value. - */ -void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr, - unsigned int mask, unsigned int val) -{ - t4_write_reg(adap, TP_PIO_ADDR, addr); - val |= t4_read_reg(adap, TP_PIO_DATA) & ~mask; - t4_write_reg(adap, TP_PIO_DATA, val); -} - /** * init_cong_ctrl - initialize congestion control parameters * @a: the alpha values for congestion control @@ -2261,9 +2000,9 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, struct fw_ldst_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_addrspace = htonl(FW_CMD_OP(FW_LDST_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | - FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE)); + c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST | + F_FW_CMD_WRITE | + V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE)); c.cycles_to_len16 = htonl(FW_LEN16(c)); c.u.addrval.addr = htonl(addr); c.u.addrval.val = htonl(val); @@ -2363,129 +2102,39 @@ int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr, } /** - * t4_fw_hello - establish communication with FW - * @adap: the adapter - * @mbox: mailbox to use for the FW command - * @evt_mbox: mailbox to receive async FW events - * @master: specifies the caller's willingness to be the device master - * @state: returns the current device state (if non-NULL) + * t4_fw_hello - establish communication with FW + * @adap: the adapter + * @mbox: mailbox to use for the FW command + * @evt_mbox: mailbox to receive async FW events + * @master: specifies the caller's willingness to be the device master + * @state: returns the current device state * - * Issues a command to establish communication with FW. Returns either - * an error (negative integer) or the mailbox of the Master PF. + * Issues a command to establish communication with FW. */ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox, enum dev_master master, enum dev_state *state) { int ret; struct fw_hello_cmd c; - u32 v; - unsigned int master_mbox; - int retries = FW_CMD_HELLO_RETRIES; -retry: - memset(&c, 0, sizeof(c)); INIT_CMD(c, HELLO, WRITE); c.err_to_mbasyncnot = htonl( FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) | FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) | - FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox : - FW_HELLO_CMD_MBMASTER_MASK) | - FW_HELLO_CMD_MBASYNCNOT(evt_mbox) | - FW_HELLO_CMD_STAGE(fw_hello_cmd_stage_os) | - FW_HELLO_CMD_CLEARINIT); + FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox : 0xff) | + FW_HELLO_CMD_MBASYNCNOT(evt_mbox)); - /* - * Issue the HELLO command to the firmware. If it's not successful - * but indicates that we got a "busy" or "timeout" condition, retry - * the HELLO until we exhaust our retry limit. - */ ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); - if (ret < 0) { - if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0) - goto retry; - return ret; - } - - v = ntohl(c.err_to_mbasyncnot); - master_mbox = FW_HELLO_CMD_MBMASTER_GET(v); - if (state) { - if (v & FW_HELLO_CMD_ERR) - *state = DEV_STATE_ERR; - else if (v & FW_HELLO_CMD_INIT) + if (ret == 0 && state) { + u32 v = ntohl(c.err_to_mbasyncnot); + if (v & FW_HELLO_CMD_INIT) *state = DEV_STATE_INIT; + else if (v & FW_HELLO_CMD_ERR) + *state = DEV_STATE_ERR; else *state = DEV_STATE_UNINIT; } - - /* - * If we're not the Master PF then we need to wait around for the - * Master PF Driver to finish setting up the adapter. - * - * Note that we also do this wait if we're a non-Master-capable PF and - * there is no current Master PF; a Master PF may show up momentarily - * and we wouldn't want to fail pointlessly. (This can happen when an - * OS loads lots of different drivers rapidly at the same time). In - * this case, the Master PF returned by the firmware will be - * FW_PCIE_FW_MASTER_MASK so the test below will work ... - */ - if ((v & (FW_HELLO_CMD_ERR|FW_HELLO_CMD_INIT)) == 0 && - master_mbox != mbox) { - int waiting = FW_CMD_HELLO_TIMEOUT; - - /* - * Wait for the firmware to either indicate an error or - * initialized state. If we see either of these we bail out - * and report the issue to the caller. If we exhaust the - * "hello timeout" and we haven't exhausted our retries, try - * again. Otherwise bail with a timeout error. - */ - for (;;) { - u32 pcie_fw; - - msleep(50); - waiting -= 50; - - /* - * If neither Error nor Initialialized are indicated - * by the firmware keep waiting till we exaust our - * timeout ... and then retry if we haven't exhausted - * our retries ... - */ - pcie_fw = t4_read_reg(adap, MA_PCIE_FW); - if (!(pcie_fw & (FW_PCIE_FW_ERR|FW_PCIE_FW_INIT))) { - if (waiting <= 0) { - if (retries-- > 0) - goto retry; - - return -ETIMEDOUT; - } - continue; - } - - /* - * We either have an Error or Initialized condition - * report errors preferentially. - */ - if (state) { - if (pcie_fw & FW_PCIE_FW_ERR) - *state = DEV_STATE_ERR; - else if (pcie_fw & FW_PCIE_FW_INIT) - *state = DEV_STATE_INIT; - } - - /* - * If we arrived before a Master PF was selected and - * there's not a valid Master PF, grab its identity - * for our caller. - */ - if (master_mbox == FW_PCIE_FW_MASTER_MASK && - (pcie_fw & FW_PCIE_FW_MASTER_VLD)) - master_mbox = FW_PCIE_FW_MASTER_GET(pcie_fw); - break; - } - } - - return master_mbox; + return ret; } /** @@ -2536,334 +2185,6 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset) return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } -/** - * t4_fw_halt - issue a reset/halt to FW and put uP into RESET - * @adap: the adapter - * @mbox: mailbox to use for the FW RESET command (if desired) - * @force: force uP into RESET even if FW RESET command fails - * - * Issues a RESET command to firmware (if desired) with a HALT indication - * and then puts the microprocessor into RESET state. The RESET command - * will only be issued if a legitimate mailbox is provided (mbox <= - * FW_PCIE_FW_MASTER_MASK). - * - * This is generally used in order for the host to safely manipulate the - * adapter without fear of conflicting with whatever the firmware might - * be doing. The only way out of this state is to RESTART the firmware - * ... - */ -int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force) -{ - int ret = 0; - - /* - * If a legitimate mailbox is provided, issue a RESET command - * with a HALT indication. - */ - if (mbox <= FW_PCIE_FW_MASTER_MASK) { - struct fw_reset_cmd c; - - memset(&c, 0, sizeof(c)); - INIT_CMD(c, RESET, WRITE); - c.val = htonl(PIORST | PIORSTMODE); - c.halt_pkd = htonl(FW_RESET_CMD_HALT(1U)); - ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); - } - - /* - * Normally we won't complete the operation if the firmware RESET - * command fails but if our caller insists we'll go ahead and put the - * uP into RESET. This can be useful if the firmware is hung or even - * missing ... We'll have to take the risk of putting the uP into - * RESET without the cooperation of firmware in that case. - * - * We also force the firmware's HALT flag to be on in case we bypassed - * the firmware RESET command above or we're dealing with old firmware - * which doesn't have the HALT capability. This will serve as a flag - * for the incoming firmware to know that it's coming out of a HALT - * rather than a RESET ... if it's new enough to understand that ... - */ - if (ret == 0 || force) { - t4_set_reg_field(adap, CIM_BOOT_CFG, UPCRST, UPCRST); - t4_set_reg_field(adap, PCIE_FW, FW_PCIE_FW_HALT, - FW_PCIE_FW_HALT); - } - - /* - * And we always return the result of the firmware RESET command - * even when we force the uP into RESET ... - */ - return ret; -} - -/** - * t4_fw_restart - restart the firmware by taking the uP out of RESET - * @adap: the adapter - * @reset: if we want to do a RESET to restart things - * - * Restart firmware previously halted by t4_fw_halt(). On successful - * return the previous PF Master remains as the new PF Master and there - * is no need to issue a new HELLO command, etc. - * - * We do this in two ways: - * - * 1. If we're dealing with newer firmware we'll simply want to take - * the chip's microprocessor out of RESET. This will cause the - * firmware to start up from its start vector. And then we'll loop - * until the firmware indicates it's started again (PCIE_FW.HALT - * reset to 0) or we timeout. - * - * 2. If we're dealing with older firmware then we'll need to RESET - * the chip since older firmware won't recognize the PCIE_FW.HALT - * flag and automatically RESET itself on startup. - */ -int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset) -{ - if (reset) { - /* - * Since we're directing the RESET instead of the firmware - * doing it automatically, we need to clear the PCIE_FW.HALT - * bit. - */ - t4_set_reg_field(adap, PCIE_FW, FW_PCIE_FW_HALT, 0); - - /* - * If we've been given a valid mailbox, first try to get the - * firmware to do the RESET. If that works, great and we can - * return success. Otherwise, if we haven't been given a - * valid mailbox or the RESET command failed, fall back to - * hitting the chip with a hammer. - */ - if (mbox <= FW_PCIE_FW_MASTER_MASK) { - t4_set_reg_field(adap, CIM_BOOT_CFG, UPCRST, 0); - msleep(100); - if (t4_fw_reset(adap, mbox, - PIORST | PIORSTMODE) == 0) - return 0; - } - - t4_write_reg(adap, PL_RST, PIORST | PIORSTMODE); - msleep(2000); - } else { - int ms; - - t4_set_reg_field(adap, CIM_BOOT_CFG, UPCRST, 0); - for (ms = 0; ms < FW_CMD_MAX_TIMEOUT; ) { - if (!(t4_read_reg(adap, PCIE_FW) & FW_PCIE_FW_HALT)) - return 0; - msleep(100); - ms += 100; - } - return -ETIMEDOUT; - } - return 0; -} - -/** - * t4_fw_upgrade - perform all of the steps necessary to upgrade FW - * @adap: the adapter - * @mbox: mailbox to use for the FW RESET command (if desired) - * @fw_data: the firmware image to write - * @size: image size - * @force: force upgrade even if firmware doesn't cooperate - * - * Perform all of the steps necessary for upgrading an adapter's - * firmware image. Normally this requires the cooperation of the - * existing firmware in order to halt all existing activities - * but if an invalid mailbox token is passed in we skip that step - * (though we'll still put the adapter microprocessor into RESET in - * that case). - * - * On successful return the new firmware will have been loaded and - * the adapter will have been fully RESET losing all previous setup - * state. On unsuccessful return the adapter may be completely hosed ... - * positive errno indicates that the adapter is ~probably~ intact, a - * negative errno indicates that things are looking bad ... - */ -int t4_fw_upgrade(struct adapter *adap, unsigned int mbox, - const u8 *fw_data, unsigned int size, int force) -{ - const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data; - int reset, ret; - - ret = t4_fw_halt(adap, mbox, force); - if (ret < 0 && !force) - return ret; - - ret = t4_load_fw(adap, fw_data, size); - if (ret < 0) - return ret; - - /* - * Older versions of the firmware don't understand the new - * PCIE_FW.HALT flag and so won't know to perform a RESET when they - * restart. So for newly loaded older firmware we'll have to do the - * RESET for it so it starts up on a clean slate. We can tell if - * the newly loaded firmware will handle this right by checking - * its header flags to see if it advertises the capability. - */ - reset = ((ntohl(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0); - return t4_fw_restart(adap, mbox, reset); -} - - -/** - * t4_fw_config_file - setup an adapter via a Configuration File - * @adap: the adapter - * @mbox: mailbox to use for the FW command - * @mtype: the memory type where the Configuration File is located - * @maddr: the memory address where the Configuration File is located - * @finiver: return value for CF [fini] version - * @finicsum: return value for CF [fini] checksum - * @cfcsum: return value for CF computed checksum - * - * Issue a command to get the firmware to process the Configuration - * File located at the specified mtype/maddress. If the Configuration - * File is processed successfully and return value pointers are - * provided, the Configuration File "[fini] section version and - * checksum values will be returned along with the computed checksum. - * It's up to the caller to decide how it wants to respond to the - * checksums not matching but it recommended that a prominant warning - * be emitted in order to help people rapidly identify changed or - * corrupted Configuration Files. - * - * Also note that it's possible to modify things like "niccaps", - * "toecaps",etc. between processing the Configuration File and telling - * the firmware to use the new configuration. Callers which want to - * do this will need to "hand-roll" their own CAPS_CONFIGS commands for - * Configuration Files if they want to do this. - */ -int t4_fw_config_file(struct adapter *adap, unsigned int mbox, - unsigned int mtype, unsigned int maddr, - u32 *finiver, u32 *finicsum, u32 *cfcsum) -{ - struct fw_caps_config_cmd caps_cmd; - int ret; - - /* - * Tell the firmware to process the indicated Configuration File. - * If there are no errors and the caller has provided return value - * pointers for the [fini] section version, checksum and computed - * checksum, pass those back to the caller. - */ - memset(&caps_cmd, 0, sizeof(caps_cmd)); - caps_cmd.op_to_write = - htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ); - caps_cmd.retval_len16 = - htonl(FW_CAPS_CONFIG_CMD_CFVALID | - FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) | - FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) | - FW_LEN16(caps_cmd)); - ret = t4_wr_mbox(adap, mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); - if (ret < 0) - return ret; - - if (finiver) - *finiver = ntohl(caps_cmd.finiver); - if (finicsum) - *finicsum = ntohl(caps_cmd.finicsum); - if (cfcsum) - *cfcsum = ntohl(caps_cmd.cfcsum); - - /* - * And now tell the firmware to use the configuration we just loaded. - */ - caps_cmd.op_to_write = - htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE); - caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); - return t4_wr_mbox(adap, mbox, &caps_cmd, sizeof(caps_cmd), NULL); -} - -/** - * t4_fixup_host_params - fix up host-dependent parameters - * @adap: the adapter - * @page_size: the host's Base Page Size - * @cache_line_size: the host's Cache Line Size - * - * Various registers in T4 contain values which are dependent on the - * host's Base Page and Cache Line Sizes. This function will fix all of - * those registers with the appropriate values as passed in ... - */ -int t4_fixup_host_params(struct adapter *adap, unsigned int page_size, - unsigned int cache_line_size) -{ - unsigned int page_shift = fls(page_size) - 1; - unsigned int sge_hps = page_shift - 10; - unsigned int stat_len = cache_line_size > 64 ? 128 : 64; - unsigned int fl_align = cache_line_size < 32 ? 32 : cache_line_size; - unsigned int fl_align_log = fls(fl_align) - 1; - - t4_write_reg(adap, SGE_HOST_PAGE_SIZE, - HOSTPAGESIZEPF0(sge_hps) | - HOSTPAGESIZEPF1(sge_hps) | - HOSTPAGESIZEPF2(sge_hps) | - HOSTPAGESIZEPF3(sge_hps) | - HOSTPAGESIZEPF4(sge_hps) | - HOSTPAGESIZEPF5(sge_hps) | - HOSTPAGESIZEPF6(sge_hps) | - HOSTPAGESIZEPF7(sge_hps)); - - t4_set_reg_field(adap, SGE_CONTROL, - INGPADBOUNDARY(INGPADBOUNDARY_MASK) | - EGRSTATUSPAGESIZE_MASK, - INGPADBOUNDARY(fl_align_log - 5) | - EGRSTATUSPAGESIZE(stat_len != 64)); - - /* - * Adjust various SGE Free List Host Buffer Sizes. - * - * This is something of a crock since we're using fixed indices into - * the array which are also known by the sge.c code and the T4 - * Firmware Configuration File. We need to come up with a much better - * approach to managing this array. For now, the first four entries - * are: - * - * 0: Host Page Size - * 1: 64KB - * 2: Buffer size corresponding to 1500 byte MTU (unpacked mode) - * 3: Buffer size corresponding to 9000 byte MTU (unpacked mode) - * - * For the single-MTU buffers in unpacked mode we need to include - * space for the SGE Control Packet Shift, 14 byte Ethernet header, - * possible 4 byte VLAN tag, all rounded up to the next Ingress Packet - * Padding boundry. All of these are accommodated in the Factory - * Default Firmware Configuration File but we need to adjust it for - * this host's cache line size. - */ - t4_write_reg(adap, SGE_FL_BUFFER_SIZE0, page_size); - t4_write_reg(adap, SGE_FL_BUFFER_SIZE2, - (t4_read_reg(adap, SGE_FL_BUFFER_SIZE2) + fl_align-1) - & ~(fl_align-1)); - t4_write_reg(adap, SGE_FL_BUFFER_SIZE3, - (t4_read_reg(adap, SGE_FL_BUFFER_SIZE3) + fl_align-1) - & ~(fl_align-1)); - - t4_write_reg(adap, ULP_RX_TDDP_PSZ, HPZ0(page_shift - 12)); - - return 0; -} - -/** - * t4_fw_initialize - ask FW to initialize the device - * @adap: the adapter - * @mbox: mailbox to use for the FW command - * - * Issues a command to FW to partially initialize the device. This - * performs initialization that generally doesn't depend on user input. - */ -int t4_fw_initialize(struct adapter *adap, unsigned int mbox) -{ - struct fw_initialize_cmd c; - - memset(&c, 0, sizeof(c)); - INIT_CMD(c, INITIALIZE, WRITE); - return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); -} - /** * t4_query_params - query FW or device parameters * @adap: the adapter @@ -3516,6 +2837,10 @@ int __devinit t4_prep_adapter(struct adapter *adapter) return ret; } + ret = get_vpd_params(adapter, &adapter->params.vpd); + if (ret < 0) + return ret; + init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd); /* @@ -3523,7 +2848,6 @@ int __devinit t4_prep_adapter(struct adapter *adapter) */ adapter->params.nports = 1; adapter->params.portvec = 1; - adapter->params.vpd.cclk = 50000; return 0; } diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h index f534ed7e10e9..c26b455f37de 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h @@ -58,7 +58,6 @@ enum { enum { SF_PAGE_SIZE = 256, /* serial flash page size */ - SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */ }; enum { RSP_TYPE_FLBUF, RSP_TYPE_CPL, RSP_TYPE_INTR }; /* response entry types */ @@ -138,83 +137,4 @@ struct rsp_ctrl { #define QINTR_CNT_EN 0x1 #define QINTR_TIMER_IDX(x) ((x) << 1) #define QINTR_TIMER_IDX_GET(x) (((x) >> 1) & 0x7) - -/* - * Flash layout. - */ -#define FLASH_START(start) ((start) * SF_SEC_SIZE) -#define FLASH_MAX_SIZE(nsecs) ((nsecs) * SF_SEC_SIZE) - -enum { - /* - * Various Expansion-ROM boot images, etc. - */ - FLASH_EXP_ROM_START_SEC = 0, - FLASH_EXP_ROM_NSECS = 6, - FLASH_EXP_ROM_START = FLASH_START(FLASH_EXP_ROM_START_SEC), - FLASH_EXP_ROM_MAX_SIZE = FLASH_MAX_SIZE(FLASH_EXP_ROM_NSECS), - - /* - * iSCSI Boot Firmware Table (iBFT) and other driver-related - * parameters ... - */ - FLASH_IBFT_START_SEC = 6, - FLASH_IBFT_NSECS = 1, - FLASH_IBFT_START = FLASH_START(FLASH_IBFT_START_SEC), - FLASH_IBFT_MAX_SIZE = FLASH_MAX_SIZE(FLASH_IBFT_NSECS), - - /* - * Boot configuration data. - */ - FLASH_BOOTCFG_START_SEC = 7, - FLASH_BOOTCFG_NSECS = 1, - FLASH_BOOTCFG_START = FLASH_START(FLASH_BOOTCFG_START_SEC), - FLASH_BOOTCFG_MAX_SIZE = FLASH_MAX_SIZE(FLASH_BOOTCFG_NSECS), - - /* - * Location of firmware image in FLASH. - */ - FLASH_FW_START_SEC = 8, - FLASH_FW_NSECS = 8, - FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC), - FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS), - - /* - * iSCSI persistent/crash information. - */ - FLASH_ISCSI_CRASH_START_SEC = 29, - FLASH_ISCSI_CRASH_NSECS = 1, - FLASH_ISCSI_CRASH_START = FLASH_START(FLASH_ISCSI_CRASH_START_SEC), - FLASH_ISCSI_CRASH_MAX_SIZE = FLASH_MAX_SIZE(FLASH_ISCSI_CRASH_NSECS), - - /* - * FCoE persistent/crash information. - */ - FLASH_FCOE_CRASH_START_SEC = 30, - FLASH_FCOE_CRASH_NSECS = 1, - FLASH_FCOE_CRASH_START = FLASH_START(FLASH_FCOE_CRASH_START_SEC), - FLASH_FCOE_CRASH_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FCOE_CRASH_NSECS), - - /* - * Location of Firmware Configuration File in FLASH. Since the FPGA - * "FLASH" is smaller we need to store the Configuration File in a - * different location -- which will overlap the end of the firmware - * image if firmware ever gets that large ... - */ - FLASH_CFG_START_SEC = 31, - FLASH_CFG_NSECS = 1, - FLASH_CFG_START = FLASH_START(FLASH_CFG_START_SEC), - FLASH_CFG_MAX_SIZE = FLASH_MAX_SIZE(FLASH_CFG_NSECS), - - FLASH_FPGA_CFG_START_SEC = 15, - FLASH_FPGA_CFG_START = FLASH_START(FLASH_FPGA_CFG_START_SEC), - - /* - * Sectors 32-63 are reserved for FLASH failover. - */ -}; - -#undef FLASH_START -#undef FLASH_MAX_SIZE - #endif /* __T4_HW_H */ diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index a1a8b57200f6..8e814bc46822 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h @@ -86,17 +86,10 @@ #define CIDXINC_SHIFT 0 #define CIDXINC(x) ((x) << CIDXINC_SHIFT) -#define X_RXPKTCPLMODE_SPLIT 1 -#define X_INGPADBOUNDARY_SHIFT 5 - #define SGE_CONTROL 0x1008 #define DCASYSTYPE 0x00080000U -#define RXPKTCPLMODE_MASK 0x00040000U -#define RXPKTCPLMODE_SHIFT 18 -#define RXPKTCPLMODE(x) ((x) << RXPKTCPLMODE_SHIFT) -#define EGRSTATUSPAGESIZE_MASK 0x00020000U -#define EGRSTATUSPAGESIZE_SHIFT 17 -#define EGRSTATUSPAGESIZE(x) ((x) << EGRSTATUSPAGESIZE_SHIFT) +#define RXPKTCPLMODE 0x00040000U +#define EGRSTATUSPAGESIZE 0x00020000U #define PKTSHIFT_MASK 0x00001c00U #define PKTSHIFT_SHIFT 10 #define PKTSHIFT(x) ((x) << PKTSHIFT_SHIFT) @@ -115,35 +108,6 @@ #define GLOBALENABLE 0x00000001U #define SGE_HOST_PAGE_SIZE 0x100c - -#define HOSTPAGESIZEPF7_MASK 0x0000000fU -#define HOSTPAGESIZEPF7_SHIFT 28 -#define HOSTPAGESIZEPF7(x) ((x) << HOSTPAGESIZEPF7_SHIFT) - -#define HOSTPAGESIZEPF6_MASK 0x0000000fU -#define HOSTPAGESIZEPF6_SHIFT 24 -#define HOSTPAGESIZEPF6(x) ((x) << HOSTPAGESIZEPF6_SHIFT) - -#define HOSTPAGESIZEPF5_MASK 0x0000000fU -#define HOSTPAGESIZEPF5_SHIFT 20 -#define HOSTPAGESIZEPF5(x) ((x) << HOSTPAGESIZEPF5_SHIFT) - -#define HOSTPAGESIZEPF4_MASK 0x0000000fU -#define HOSTPAGESIZEPF4_SHIFT 16 -#define HOSTPAGESIZEPF4(x) ((x) << HOSTPAGESIZEPF4_SHIFT) - -#define HOSTPAGESIZEPF3_MASK 0x0000000fU -#define HOSTPAGESIZEPF3_SHIFT 12 -#define HOSTPAGESIZEPF3(x) ((x) << HOSTPAGESIZEPF3_SHIFT) - -#define HOSTPAGESIZEPF2_MASK 0x0000000fU -#define HOSTPAGESIZEPF2_SHIFT 8 -#define HOSTPAGESIZEPF2(x) ((x) << HOSTPAGESIZEPF2_SHIFT) - -#define HOSTPAGESIZEPF1_MASK 0x0000000fU -#define HOSTPAGESIZEPF1_SHIFT 4 -#define HOSTPAGESIZEPF1(x) ((x) << HOSTPAGESIZEPF1_SHIFT) - #define HOSTPAGESIZEPF0_MASK 0x0000000fU #define HOSTPAGESIZEPF0_SHIFT 0 #define HOSTPAGESIZEPF0(x) ((x) << HOSTPAGESIZEPF0_SHIFT) @@ -191,8 +155,6 @@ #define SGE_INT_ENABLE3 0x1040 #define SGE_FL_BUFFER_SIZE0 0x1044 #define SGE_FL_BUFFER_SIZE1 0x1048 -#define SGE_FL_BUFFER_SIZE2 0x104c -#define SGE_FL_BUFFER_SIZE3 0x1050 #define SGE_INGRESS_RX_THRESHOLD 0x10a0 #define THRESHOLD_0_MASK 0x3f000000U #define THRESHOLD_0_SHIFT 24 @@ -211,12 +173,6 @@ #define THRESHOLD_3(x) ((x) << THRESHOLD_3_SHIFT) #define THRESHOLD_3_GET(x) (((x) & THRESHOLD_3_MASK) >> THRESHOLD_3_SHIFT) -#define SGE_CONM_CTRL 0x1094 -#define EGRTHRESHOLD_MASK 0x00003f00U -#define EGRTHRESHOLDshift 8 -#define EGRTHRESHOLD(x) ((x) << EGRTHRESHOLDshift) -#define EGRTHRESHOLD_GET(x) (((x) & EGRTHRESHOLD_MASK) >> EGRTHRESHOLDshift) - #define SGE_TIMER_VALUE_0_AND_1 0x10b8 #define TIMERVALUE0_MASK 0xffff0000U #define TIMERVALUE0_SHIFT 16 @@ -228,25 +184,7 @@ #define TIMERVALUE1_GET(x) (((x) & TIMERVALUE1_MASK) >> TIMERVALUE1_SHIFT) #define SGE_TIMER_VALUE_2_AND_3 0x10bc -#define TIMERVALUE2_MASK 0xffff0000U -#define TIMERVALUE2_SHIFT 16 -#define TIMERVALUE2(x) ((x) << TIMERVALUE2_SHIFT) -#define TIMERVALUE2_GET(x) (((x) & TIMERVALUE2_MASK) >> TIMERVALUE2_SHIFT) -#define TIMERVALUE3_MASK 0x0000ffffU -#define TIMERVALUE3_SHIFT 0 -#define TIMERVALUE3(x) ((x) << TIMERVALUE3_SHIFT) -#define TIMERVALUE3_GET(x) (((x) & TIMERVALUE3_MASK) >> TIMERVALUE3_SHIFT) - #define SGE_TIMER_VALUE_4_AND_5 0x10c0 -#define TIMERVALUE4_MASK 0xffff0000U -#define TIMERVALUE4_SHIFT 16 -#define TIMERVALUE4(x) ((x) << TIMERVALUE4_SHIFT) -#define TIMERVALUE4_GET(x) (((x) & TIMERVALUE4_MASK) >> TIMERVALUE4_SHIFT) -#define TIMERVALUE5_MASK 0x0000ffffU -#define TIMERVALUE5_SHIFT 0 -#define TIMERVALUE5(x) ((x) << TIMERVALUE5_SHIFT) -#define TIMERVALUE5_GET(x) (((x) & TIMERVALUE5_MASK) >> TIMERVALUE5_SHIFT) - #define SGE_DEBUG_INDEX 0x10cc #define SGE_DEBUG_DATA_HIGH 0x10d0 #define SGE_DEBUG_DATA_LOW 0x10d4 @@ -321,8 +259,6 @@ #define WINDOW(x) ((x) << WINDOW_SHIFT) #define PCIE_MEM_ACCESS_OFFSET 0x306c -#define PCIE_FW 0x30b8 - #define PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS 0x5908 #define RNPP 0x80000000U #define RPCP 0x20000000U @@ -400,7 +336,7 @@ #define MEM_WRAP_CLIENT_NUM_MASK 0x0000000fU #define MEM_WRAP_CLIENT_NUM_SHIFT 0 #define MEM_WRAP_CLIENT_NUM_GET(x) (((x) & MEM_WRAP_CLIENT_NUM_MASK) >> MEM_WRAP_CLIENT_NUM_SHIFT) -#define MA_PCIE_FW 0x30b8 + #define MA_PARITY_ERROR_STATUS 0x77f4 #define EDC_0_BASE_ADDR 0x7900 @@ -421,7 +357,6 @@ #define CIM_BOOT_CFG 0x7b00 #define BOOTADDR_MASK 0xffffff00U -#define UPCRST 0x1U #define CIM_PF_MAILBOX_DATA 0x240 #define CIM_PF_MAILBOX_CTRL 0x280 @@ -494,13 +429,6 @@ #define VLANEXTENABLE_MASK 0x0000f000U #define VLANEXTENABLE_SHIFT 12 -#define TP_GLOBAL_CONFIG 0x7d08 -#define FIVETUPLELOOKUP_SHIFT 17 -#define FIVETUPLELOOKUP_MASK 0x00060000U -#define FIVETUPLELOOKUP(x) ((x) << FIVETUPLELOOKUP_SHIFT) -#define FIVETUPLELOOKUP_GET(x) (((x) & FIVETUPLELOOKUP_MASK) >> \ - FIVETUPLELOOKUP_SHIFT) - #define TP_PARA_REG2 0x7d68 #define MAXRXDATA_MASK 0xffff0000U #define MAXRXDATA_SHIFT 16 @@ -510,47 +438,8 @@ #define TIMERRESOLUTION_MASK 0x00ff0000U #define TIMERRESOLUTION_SHIFT 16 #define TIMERRESOLUTION_GET(x) (((x) & TIMERRESOLUTION_MASK) >> TIMERRESOLUTION_SHIFT) -#define DELAYEDACKRESOLUTION_MASK 0x000000ffU -#define DELAYEDACKRESOLUTION_SHIFT 0 -#define DELAYEDACKRESOLUTION_GET(x) \ - (((x) & DELAYEDACKRESOLUTION_MASK) >> DELAYEDACKRESOLUTION_SHIFT) #define TP_SHIFT_CNT 0x7dc0 -#define SYNSHIFTMAX_SHIFT 24 -#define SYNSHIFTMAX_MASK 0xff000000U -#define SYNSHIFTMAX(x) ((x) << SYNSHIFTMAX_SHIFT) -#define SYNSHIFTMAX_GET(x) (((x) & SYNSHIFTMAX_MASK) >> \ - SYNSHIFTMAX_SHIFT) -#define RXTSHIFTMAXR1_SHIFT 20 -#define RXTSHIFTMAXR1_MASK 0x00f00000U -#define RXTSHIFTMAXR1(x) ((x) << RXTSHIFTMAXR1_SHIFT) -#define RXTSHIFTMAXR1_GET(x) (((x) & RXTSHIFTMAXR1_MASK) >> \ - RXTSHIFTMAXR1_SHIFT) -#define RXTSHIFTMAXR2_SHIFT 16 -#define RXTSHIFTMAXR2_MASK 0x000f0000U -#define RXTSHIFTMAXR2(x) ((x) << RXTSHIFTMAXR2_SHIFT) -#define RXTSHIFTMAXR2_GET(x) (((x) & RXTSHIFTMAXR2_MASK) >> \ - RXTSHIFTMAXR2_SHIFT) -#define PERSHIFTBACKOFFMAX_SHIFT 12 -#define PERSHIFTBACKOFFMAX_MASK 0x0000f000U -#define PERSHIFTBACKOFFMAX(x) ((x) << PERSHIFTBACKOFFMAX_SHIFT) -#define PERSHIFTBACKOFFMAX_GET(x) (((x) & PERSHIFTBACKOFFMAX_MASK) >> \ - PERSHIFTBACKOFFMAX_SHIFT) -#define PERSHIFTMAX_SHIFT 8 -#define PERSHIFTMAX_MASK 0x00000f00U -#define PERSHIFTMAX(x) ((x) << PERSHIFTMAX_SHIFT) -#define PERSHIFTMAX_GET(x) (((x) & PERSHIFTMAX_MASK) >> \ - PERSHIFTMAX_SHIFT) -#define KEEPALIVEMAXR1_SHIFT 4 -#define KEEPALIVEMAXR1_MASK 0x000000f0U -#define KEEPALIVEMAXR1(x) ((x) << KEEPALIVEMAXR1_SHIFT) -#define KEEPALIVEMAXR1_GET(x) (((x) & KEEPALIVEMAXR1_MASK) >> \ - KEEPALIVEMAXR1_SHIFT) -#define KEEPALIVEMAXR2_SHIFT 0 -#define KEEPALIVEMAXR2_MASK 0x0000000fU -#define KEEPALIVEMAXR2(x) ((x) << KEEPALIVEMAXR2_SHIFT) -#define KEEPALIVEMAXR2_GET(x) (((x) & KEEPALIVEMAXR2_MASK) >> \ - KEEPALIVEMAXR2_SHIFT) #define TP_CCTRL_TABLE 0x7ddc #define TP_MTU_TABLE 0x7de4 @@ -584,20 +473,6 @@ #define TP_INT_CAUSE 0x7e74 #define FLMTXFLSTEMPTY 0x40000000U -#define TP_VLAN_PRI_MAP 0x140 -#define FRAGMENTATION_SHIFT 9 -#define FRAGMENTATION_MASK 0x00000200U -#define MPSHITTYPE_MASK 0x00000100U -#define MACMATCH_MASK 0x00000080U -#define ETHERTYPE_MASK 0x00000040U -#define PROTOCOL_MASK 0x00000020U -#define TOS_MASK 0x00000010U -#define VLAN_MASK 0x00000008U -#define VNIC_ID_MASK 0x00000004U -#define PORT_MASK 0x00000002U -#define FCOE_SHIFT 0 -#define FCOE_MASK 0x00000001U - #define TP_INGRESS_CONFIG 0x141 #define VNIC 0x00000800U #define CSUM_HAS_PSEUDO_HDR 0x00000400U diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index a6364632b490..ad53f796b574 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -79,8 +79,6 @@ struct fw_wr_hdr { #define FW_WR_FLOWID(x) ((x) << 8) #define FW_WR_LEN16(x) ((x) << 0) -#define HW_TPL_FR_MT_PR_IV_P_FC 0X32B - struct fw_ulptx_wr { __be32 op_to_compl; __be32 flowid_len16; @@ -157,17 +155,6 @@ struct fw_eth_tx_pkt_vm_wr { #define FW_CMD_MAX_TIMEOUT 3000 -/* - * If a host driver does a HELLO and discovers that there's already a MASTER - * selected, we may have to wait for that MASTER to finish issuing RESET, - * configuration and INITIALIZE commands. Also, there's a possibility that - * our own HELLO may get lost if it happens right as the MASTER is issuign a - * RESET command, so we need to be willing to make a few retries of our HELLO. - */ -#define FW_CMD_HELLO_TIMEOUT (3 * FW_CMD_MAX_TIMEOUT) -#define FW_CMD_HELLO_RETRIES 3 - - enum fw_cmd_opcodes { FW_LDST_CMD = 0x01, FW_RESET_CMD = 0x03, @@ -317,17 +304,7 @@ struct fw_reset_cmd { __be32 op_to_write; __be32 retval_len16; __be32 val; - __be32 halt_pkd; -}; - -#define FW_RESET_CMD_HALT_SHIFT 31 -#define FW_RESET_CMD_HALT_MASK 0x1 -#define FW_RESET_CMD_HALT(x) ((x) << FW_RESET_CMD_HALT_SHIFT) -#define FW_RESET_CMD_HALT_GET(x) \ - (((x) >> FW_RESET_CMD_HALT_SHIFT) & FW_RESET_CMD_HALT_MASK) - -enum fw_hellow_cmd { - fw_hello_cmd_stage_os = 0x0 + __be32 r3; }; struct fw_hello_cmd { @@ -338,14 +315,8 @@ struct fw_hello_cmd { #define FW_HELLO_CMD_INIT (1U << 30) #define FW_HELLO_CMD_MASTERDIS(x) ((x) << 29) #define FW_HELLO_CMD_MASTERFORCE(x) ((x) << 28) -#define FW_HELLO_CMD_MBMASTER_MASK 0xfU -#define FW_HELLO_CMD_MBMASTER_SHIFT 24 -#define FW_HELLO_CMD_MBMASTER(x) ((x) << FW_HELLO_CMD_MBMASTER_SHIFT) -#define FW_HELLO_CMD_MBMASTER_GET(x) \ - (((x) >> FW_HELLO_CMD_MBMASTER_SHIFT) & FW_HELLO_CMD_MBMASTER_MASK) +#define FW_HELLO_CMD_MBMASTER(x) ((x) << 24) #define FW_HELLO_CMD_MBASYNCNOT(x) ((x) << 20) -#define FW_HELLO_CMD_STAGE(x) ((x) << 17) -#define FW_HELLO_CMD_CLEARINIT (1U << 16) __be32 fwrev; }; @@ -430,14 +401,6 @@ enum fw_caps_config_fcoe { FW_CAPS_CONFIG_FCOE_TARGET = 0x00000002, }; -enum fw_memtype_cf { - FW_MEMTYPE_CF_EDC0 = 0x0, - FW_MEMTYPE_CF_EDC1 = 0x1, - FW_MEMTYPE_CF_EXTMEM = 0x2, - FW_MEMTYPE_CF_FLASH = 0x4, - FW_MEMTYPE_CF_INTERNAL = 0x5, -}; - struct fw_caps_config_cmd { __be32 op_to_write; __be32 retval_len16; @@ -453,15 +416,10 @@ struct fw_caps_config_cmd { __be16 r4; __be16 iscsicaps; __be16 fcoecaps; - __be32 cfcsum; - __be32 finiver; - __be32 finicsum; + __be32 r5; + __be64 r6; }; -#define FW_CAPS_CONFIG_CMD_CFVALID (1U << 27) -#define FW_CAPS_CONFIG_CMD_MEMTYPE_CF(x) ((x) << 24) -#define FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(x) ((x) << 16) - /* * params command mnemonics */ @@ -493,7 +451,6 @@ enum fw_params_param_dev { FW_PARAMS_PARAM_DEV_INTVER_FCOE = 0x0A, FW_PARAMS_PARAM_DEV_FWREV = 0x0B, FW_PARAMS_PARAM_DEV_TPREV = 0x0C, - FW_PARAMS_PARAM_DEV_CF = 0x0D, }; /* @@ -535,8 +492,6 @@ enum fw_params_param_pfvf { FW_PARAMS_PARAM_PFVF_IQFLINT_END = 0x2A, FW_PARAMS_PARAM_PFVF_EQ_START = 0x2B, FW_PARAMS_PARAM_PFVF_EQ_END = 0x2C, - FW_PARAMS_PARAM_PFVF_ACTIVE_FILTER_START = 0x2D, - FW_PARAMS_PARAM_PFVF_ACTIVE_FILTER_END = 0x2E }; /* @@ -552,16 +507,8 @@ enum fw_params_param_dmaq { #define FW_PARAMS_MNEM(x) ((x) << 24) #define FW_PARAMS_PARAM_X(x) ((x) << 16) -#define FW_PARAMS_PARAM_Y_SHIFT 8 -#define FW_PARAMS_PARAM_Y_MASK 0xffU -#define FW_PARAMS_PARAM_Y(x) ((x) << FW_PARAMS_PARAM_Y_SHIFT) -#define FW_PARAMS_PARAM_Y_GET(x) (((x) >> FW_PARAMS_PARAM_Y_SHIFT) &\ - FW_PARAMS_PARAM_Y_MASK) -#define FW_PARAMS_PARAM_Z_SHIFT 0 -#define FW_PARAMS_PARAM_Z_MASK 0xffu -#define FW_PARAMS_PARAM_Z(x) ((x) << FW_PARAMS_PARAM_Z_SHIFT) -#define FW_PARAMS_PARAM_Z_GET(x) (((x) >> FW_PARAMS_PARAM_Z_SHIFT) &\ - FW_PARAMS_PARAM_Z_MASK) +#define FW_PARAMS_PARAM_Y(x) ((x) << 8) +#define FW_PARAMS_PARAM_Z(x) ((x) << 0) #define FW_PARAMS_PARAM_XYZ(x) ((x) << 0) #define FW_PARAMS_PARAM_YZ(x) ((x) << 0) @@ -1652,16 +1599,6 @@ struct fw_debug_cmd { } u; }; -#define FW_PCIE_FW_ERR (1U << 31) -#define FW_PCIE_FW_INIT (1U << 30) -#define FW_PCIE_FW_HALT (1U << 29) -#define FW_PCIE_FW_MASTER_VLD (1U << 15) -#define FW_PCIE_FW_MASTER_MASK 0x7 -#define FW_PCIE_FW_MASTER_SHIFT 12 -#define FW_PCIE_FW_MASTER(x) ((x) << FW_PCIE_FW_MASTER_SHIFT) -#define FW_PCIE_FW_MASTER_GET(x) (((x) >> FW_PCIE_FW_MASTER_SHIFT) & \ - FW_PCIE_FW_MASTER_MASK) - struct fw_hdr { u8 ver; u8 reserved1; @@ -1676,11 +1613,7 @@ struct fw_hdr { u8 intfver_iscsi; u8 intfver_fcoe; u8 reserved2; - __u32 reserved3; - __u32 reserved4; - __u32 reserved5; - __be32 flags; - __be32 reserved6[23]; + __be32 reserved3[27]; }; #define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff) @@ -1688,8 +1621,18 @@ struct fw_hdr { #define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff) #define FW_HDR_FW_VER_BUILD_GET(x) (((x) >> 0) & 0xff) -enum fw_hdr_flags { - FW_HDR_FLAGS_RESET_HALT = 0x00000001, -}; +#define S_FW_CMD_OP 24 +#define V_FW_CMD_OP(x) ((x) << S_FW_CMD_OP) + +#define S_FW_CMD_REQUEST 23 +#define V_FW_CMD_REQUEST(x) ((x) << S_FW_CMD_REQUEST) +#define F_FW_CMD_REQUEST V_FW_CMD_REQUEST(1U) + +#define S_FW_CMD_WRITE 21 +#define V_FW_CMD_WRITE(x) ((x) << S_FW_CMD_WRITE) +#define F_FW_CMD_WRITE V_FW_CMD_WRITE(1U) + +#define S_FW_LDST_CMD_ADDRSPACE 0 +#define V_FW_LDST_CMD_ADDRSPACE(x) ((x) << S_FW_LDST_CMD_ADDRSPACE) #endif /* _T4FW_INTERFACE_H_ */ diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/trunk/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index f16745f4b36b..8877fbfefb63 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -2421,7 +2421,7 @@ int t4vf_sge_init(struct adapter *adapter) fl0, fl1); return -EINVAL; } - if ((sge_params->sge_control & RXPKTCPLMODE_MASK) == 0) { + if ((sge_params->sge_control & RXPKTCPLMODE) == 0) { dev_err(adapter->pdev_dev, "bad SGE CPL MODE\n"); return -EINVAL; } @@ -2431,8 +2431,7 @@ int t4vf_sge_init(struct adapter *adapter) */ if (fl1) FL_PG_ORDER = ilog2(fl1) - PAGE_SHIFT; - STAT_LEN = ((sge_params->sge_control & EGRSTATUSPAGESIZE_MASK) - ? 128 : 64); + STAT_LEN = ((sge_params->sge_control & EGRSTATUSPAGESIZE) ? 128 : 64); PKTSHIFT = PKTSHIFT_GET(sge_params->sge_control); FL_ALIGN = 1 << (INGPADBOUNDARY_GET(sge_params->sge_control) + SGE_INGPADBOUNDARY_SHIFT); diff --git a/trunk/drivers/net/ethernet/emulex/benet/be.h b/trunk/drivers/net/ethernet/emulex/benet/be.h index cf4c05bdf5fe..5b622993ff17 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be.h +++ b/trunk/drivers/net/ethernet/emulex/benet/be.h @@ -337,6 +337,7 @@ struct phy_info { u16 auto_speeds_supported; u16 fixed_speeds_supported; int link_speed; + int forced_port_speed; u32 dac_cable_len; u32 advertising; u32 supported; diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c index af60bb26e330..701b3e9a715b 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -165,13 +165,14 @@ static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, } } -/* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */ +/* Grp5 QOS Speed evt */ static void be_async_grp5_qos_speed_process(struct be_adapter *adapter, struct be_async_event_grp5_qos_link_speed *evt) { - if (adapter->phy.link_speed >= 0 && - evt->physical_port == adapter->port_num) - adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10; + if (evt->physical_port == adapter->port_num) { + /* qos_link_speed is in units of 10 Mbps */ + adapter->phy.link_speed = evt->qos_link_speed * 10; + } } /*Grp5 PVID evt*/ @@ -716,7 +717,7 @@ int be_cmd_eq_create(struct be_adapter *adapter, /* Use MCC */ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, - bool permanent, u32 if_handle, u32 pmac_id) + u8 type, bool permanent, u32 if_handle, u32 pmac_id) { struct be_mcc_wrb *wrb; struct be_cmd_req_mac_query *req; @@ -733,7 +734,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb, NULL); - req->type = MAC_ADDRESS_TYPE_NETWORK; + req->type = type; if (permanent) { req->permanent = 1; } else { @@ -1325,28 +1326,9 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, return status; } -static int be_mac_to_link_speed(int mac_speed) -{ - switch (mac_speed) { - case PHY_LINK_SPEED_ZERO: - return 0; - case PHY_LINK_SPEED_10MBPS: - return 10; - case PHY_LINK_SPEED_100MBPS: - return 100; - case PHY_LINK_SPEED_1GBPS: - return 1000; - case PHY_LINK_SPEED_10GBPS: - return 10000; - } - return 0; -} - -/* Uses synchronous mcc - * Returns link_speed in Mbps - */ -int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, - u8 *link_status, u32 dom) +/* Uses synchronous mcc */ +int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, + u16 *link_speed, u8 *link_status, u32 dom) { struct be_mcc_wrb *wrb; struct be_cmd_req_link_status *req; @@ -1375,13 +1357,11 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_link_status *resp = embedded_payload(wrb); - if (link_speed) { - *link_speed = resp->link_speed ? - le16_to_cpu(resp->link_speed) * 10 : - be_mac_to_link_speed(resp->mac_speed); - - if (!resp->logical_link_status) - *link_speed = 0; + if (resp->mac_speed != PHY_LINK_SPEED_ZERO) { + if (link_speed) + *link_speed = le16_to_cpu(resp->link_speed); + if (mac_speed) + *mac_speed = resp->mac_speed; } if (link_status) *link_status = resp->logical_link_status; @@ -2425,9 +2405,6 @@ int be_cmd_req_native_mode(struct be_adapter *adapter) struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb); adapter->be3_native = le32_to_cpu(resp->cap_flags) & CAPABILITY_BE3_NATIVE_ERX_API; - if (!adapter->be3_native) - dev_warn(&adapter->pdev->dev, - "adapter not in advanced mode\n"); } err: mutex_unlock(&adapter->mbox_lock); diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.h b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.h index 0936e21e3cff..250f19b5f7b6 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/trunk/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -1687,7 +1687,7 @@ struct be_cmd_req_set_ext_fat_caps { extern int be_pci_fnum_get(struct be_adapter *adapter); extern int be_fw_wait_ready(struct be_adapter *adapter); extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, - bool permanent, u32 if_handle, u32 pmac_id); + u8 type, bool permanent, u32 if_handle, u32 pmac_id); extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, u32 if_id, u32 *pmac_id, u32 domain); extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, @@ -1714,8 +1714,8 @@ extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, int type); extern int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q); -extern int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, - u8 *link_status, u32 dom); +extern int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, + u16 *link_speed, u8 *link_status, u32 dom); extern int be_cmd_reset(struct be_adapter *adapter); extern int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd); diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c b/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c index 8e6fb0ba6aa9..c0e700653f96 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -512,6 +512,28 @@ static u32 convert_to_et_setting(u32 if_type, u32 if_speeds) return val; } +static int convert_to_et_speed(u32 be_speed) +{ + int et_speed = SPEED_10000; + + switch (be_speed) { + case PHY_LINK_SPEED_10MBPS: + et_speed = SPEED_10; + break; + case PHY_LINK_SPEED_100MBPS: + et_speed = SPEED_100; + break; + case PHY_LINK_SPEED_1GBPS: + et_speed = SPEED_1000; + break; + case PHY_LINK_SPEED_10GBPS: + et_speed = SPEED_10000; + break; + } + + return et_speed; +} + bool be_pause_supported(struct be_adapter *adapter) { return (adapter->phy.interface_type == PHY_TYPE_SFP_PLUS_10GB || @@ -522,16 +544,27 @@ bool be_pause_supported(struct be_adapter *adapter) static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct be_adapter *adapter = netdev_priv(netdev); - u8 link_status; + u8 port_speed = 0; u16 link_speed = 0; + u8 link_status; + u32 et_speed = 0; int status; - if (adapter->phy.link_speed < 0) { - status = be_cmd_link_status_query(adapter, &link_speed, - &link_status, 0); - if (!status) - be_link_status_update(adapter, link_status); - ethtool_cmd_speed_set(ecmd, link_speed); + if (adapter->phy.link_speed < 0 || !(netdev->flags & IFF_UP)) { + if (adapter->phy.forced_port_speed < 0) { + status = be_cmd_link_status_query(adapter, &port_speed, + &link_speed, &link_status, 0); + if (!status) + be_link_status_update(adapter, link_status); + if (link_speed) + et_speed = link_speed * 10; + else if (link_status) + et_speed = convert_to_et_speed(port_speed); + } else { + et_speed = adapter->phy.forced_port_speed; + } + + ethtool_cmd_speed_set(ecmd, et_speed); status = be_cmd_get_phy_info(adapter); if (status) @@ -740,8 +773,8 @@ static void be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) { struct be_adapter *adapter = netdev_priv(netdev); - int status; - u8 link_status = 0; + u8 mac_speed = 0; + u16 qos_link_speed = 0; memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM); @@ -765,11 +798,11 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) test->flags |= ETH_TEST_FL_FAILED; } - status = be_cmd_link_status_query(adapter, NULL, &link_status, 0); - if (status) { + if (be_cmd_link_status_query(adapter, &mac_speed, + &qos_link_speed, NULL, 0) != 0) { test->flags |= ETH_TEST_FL_FAILED; data[4] = -1; - } else if (!link_status) { + } else if (!mac_speed) { test->flags |= ETH_TEST_FL_FAILED; data[4] = 1; } diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_main.c b/trunk/drivers/net/ethernet/emulex/benet/be_main.c index 8dd42b309f38..84379f4fe837 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_main.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_main.c @@ -241,8 +241,9 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - status = be_cmd_mac_addr_query(adapter, current_mac, false, - adapter->if_handle, 0); + status = be_cmd_mac_addr_query(adapter, current_mac, + MAC_ADDRESS_TYPE_NETWORK, false, + adapter->if_handle, 0); if (status) goto err; @@ -1075,7 +1076,7 @@ static int be_set_vf_tx_rate(struct net_device *netdev, static int be_find_vfs(struct be_adapter *adapter, int vf_state) { struct pci_dev *dev, *pdev = adapter->pdev; - int vfs = 0, assigned_vfs = 0, pos; + int vfs = 0, assigned_vfs = 0, pos, vf_fn; u16 offset, stride; pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); @@ -1086,7 +1087,9 @@ static int be_find_vfs(struct be_adapter *adapter, int vf_state) dev = pci_get_device(pdev->vendor, PCI_ANY_ID, NULL); while (dev) { - if (dev->is_virtfn && pci_physfn(dev) == pdev) { + vf_fn = (pdev->devfn + offset + stride * vfs) & 0xFFFF; + if (dev->is_virtfn && dev->devfn == vf_fn && + dev->bus->number == pdev->bus->number) { vfs++; if (dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) assigned_vfs++; @@ -1894,8 +1897,6 @@ static int be_tx_qs_create(struct be_adapter *adapter) return status; } - dev_info(&adapter->pdev->dev, "created %d TX queue(s)\n", - adapter->num_tx_qs); return 0; } @@ -1946,9 +1947,10 @@ static int be_rx_cqs_create(struct be_adapter *adapter) return rc; } - dev_info(&adapter->pdev->dev, - "created %d RSS queue(s) and 1 default RX queue\n", - adapter->num_rx_qs - 1); + if (adapter->num_rx_qs != MAX_RX_QS) + dev_info(&adapter->pdev->dev, + "Created only %d receive queues\n", adapter->num_rx_qs); + return 0; } @@ -2186,7 +2188,6 @@ static void be_msix_enable(struct be_adapter *adapter) { #define BE_MIN_MSIX_VECTORS 1 int i, status, num_vec, num_roce_vec = 0; - struct device *dev = &adapter->pdev->dev; /* If RSS queues are not used, need a vec for default RX Q */ num_vec = min(be_num_rss_want(adapter), num_online_cpus()); @@ -2211,8 +2212,6 @@ static void be_msix_enable(struct be_adapter *adapter) num_vec) == 0) goto done; } - - dev_warn(dev, "MSIx enable failed\n"); return; done: if (be_roce_supported(adapter)) { @@ -2226,7 +2225,6 @@ static void be_msix_enable(struct be_adapter *adapter) } } else adapter->num_msix_vec = num_vec; - dev_info(dev, "enabled %d MSI-x vector(s)\n", adapter->num_msix_vec); return; } @@ -2443,7 +2441,8 @@ static int be_open(struct net_device *netdev) be_eq_notify(adapter, eqo->q.id, true, false, 0); } - status = be_cmd_link_status_query(adapter, NULL, &link_status, 0); + status = be_cmd_link_status_query(adapter, NULL, NULL, + &link_status, 0); if (!status) be_link_status_update(adapter, link_status); @@ -2672,6 +2671,7 @@ static void be_setup_init(struct be_adapter *adapter) adapter->be3_native = false; adapter->promiscuous = false; adapter->eq_next_idx = 0; + adapter->phy.forced_port_speed = -1; } static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle, @@ -2693,16 +2693,21 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle, status = be_cmd_get_mac_from_list(adapter, mac, active_mac, pmac_id, 0); if (*active_mac) { - status = be_cmd_mac_addr_query(adapter, mac, false, - if_handle, *pmac_id); + status = be_cmd_mac_addr_query(adapter, mac, + MAC_ADDRESS_TYPE_NETWORK, + false, if_handle, + *pmac_id); } } else if (be_physfn(adapter)) { /* For BE3, for PF get permanent MAC */ - status = be_cmd_mac_addr_query(adapter, mac, true, 0, 0); + status = be_cmd_mac_addr_query(adapter, mac, + MAC_ADDRESS_TYPE_NETWORK, true, + 0, 0); *active_mac = false; } else { /* For BE3, for VF get soft MAC assigned by PF*/ - status = be_cmd_mac_addr_query(adapter, mac, false, + status = be_cmd_mac_addr_query(adapter, mac, + MAC_ADDRESS_TYPE_NETWORK, false, if_handle, 0); *active_mac = true; } @@ -3800,23 +3805,6 @@ static bool be_reset_required(struct be_adapter *adapter) return be_find_vfs(adapter, ENABLED) > 0 ? false : true; } -static char *mc_name(struct be_adapter *adapter) -{ - if (adapter->function_mode & FLEX10_MODE) - return "FLEX10"; - else if (adapter->function_mode & VNIC_MODE) - return "vNIC"; - else if (adapter->function_mode & UMC_ENABLED) - return "UMC"; - else - return ""; -} - -static inline char *func_name(struct be_adapter *adapter) -{ - return be_physfn(adapter) ? "PF" : "VF"; -} - static int __devinit be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) { @@ -3907,7 +3895,7 @@ static int __devinit be_probe(struct pci_dev *pdev, status = be_setup(adapter); if (status) - goto stats_clean; + goto msix_disable; be_netdev_init(netdev); status = register_netdev(netdev); @@ -3921,13 +3909,15 @@ static int __devinit be_probe(struct pci_dev *pdev, be_cmd_query_port_name(adapter, &port_name); - dev_info(&pdev->dev, "%s: %s %s port %c\n", nic_name(pdev), - func_name(adapter), mc_name(adapter), port_name); + dev_info(&pdev->dev, "%s: %s port %c\n", netdev->name, nic_name(pdev), + port_name); return 0; unsetup: be_clear(adapter); +msix_disable: + be_msix_disable(adapter); stats_clean: be_stats_cleanup(adapter); ctrl_clean: diff --git a/trunk/drivers/net/ethernet/freescale/gianfar.c b/trunk/drivers/net/ethernet/freescale/gianfar.c index a1b52ec3b930..4d5b58ce1298 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar.c +++ b/trunk/drivers/net/ethernet/freescale/gianfar.c @@ -394,13 +394,7 @@ static void gfar_init_mac(struct net_device *ndev) if (ndev->features & NETIF_F_IP_CSUM) tctrl |= TCTRL_INIT_CSUM; - if (priv->prio_sched_en) - tctrl |= TCTRL_TXSCHED_PRIO; - else { - tctrl |= TCTRL_TXSCHED_WRRS; - gfar_write(®s->tr03wt, DEFAULT_WRRS_WEIGHT); - gfar_write(®s->tr47wt, DEFAULT_WRRS_WEIGHT); - } + tctrl |= TCTRL_TXSCHED_PRIO; gfar_write(®s->tctrl, tctrl); @@ -1166,9 +1160,6 @@ static int gfar_probe(struct platform_device *ofdev) priv->rx_filer_enable = 1; /* Enable most messages by default */ priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; - /* use pritority h/w tx queue scheduling for single queue devices */ - if (priv->num_tx_queues == 1) - priv->prio_sched_en = 1; /* Carrier starts down, phylib will bring it up */ netif_carrier_off(dev); diff --git a/trunk/drivers/net/ethernet/freescale/gianfar.h b/trunk/drivers/net/ethernet/freescale/gianfar.h index 4141ef2ddafc..2136c7ff5e6d 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar.h +++ b/trunk/drivers/net/ethernet/freescale/gianfar.h @@ -301,16 +301,8 @@ extern const char gfar_driver_version[]; #define TCTRL_TFCPAUSE 0x00000008 #define TCTRL_TXSCHED_MASK 0x00000006 #define TCTRL_TXSCHED_INIT 0x00000000 -/* priority scheduling */ #define TCTRL_TXSCHED_PRIO 0x00000002 -/* weighted round-robin scheduling (WRRS) */ #define TCTRL_TXSCHED_WRRS 0x00000004 -/* default WRRS weight and policy setting, - * tailored to the tr03wt and tr47wt registers: - * equal weight for all Tx Qs, measured in 64byte units - */ -#define DEFAULT_WRRS_WEIGHT 0x18181818 - #define TCTRL_INIT_CSUM (TCTRL_TUCSEN | TCTRL_IPCSEN) #define IEVENT_INIT_CLEAR 0xffffffff @@ -1106,8 +1098,7 @@ struct gfar_private { extended_hash:1, bd_stash_en:1, rx_filer_enable:1, - wol_en:1, /* Wake-on-LAN enabled */ - prio_sched_en:1; /* Enable priorty based Tx scheduling in Hw */ + wol_en:1; /* Wake-on-LAN enabled */ unsigned short padding; /* PHY stuff */ diff --git a/trunk/drivers/net/ethernet/freescale/gianfar_ethtool.c b/trunk/drivers/net/ethernet/freescale/gianfar_ethtool.c index ab6762caa957..8971921cc1c8 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/trunk/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -1773,7 +1773,6 @@ static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd, } int gfar_phc_index = -1; -EXPORT_SYMBOL(gfar_phc_index); static int gfar_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) diff --git a/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c b/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c index b9db0e040563..c08e5d40fecb 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/trunk/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -510,12 +510,12 @@ static int gianfar_ptp_probe(struct platform_device *dev) spin_unlock_irqrestore(&etsects->lock, flags); - etsects->clock = ptp_clock_register(&etsects->caps, &dev->dev); + etsects->clock = ptp_clock_register(&etsects->caps); if (IS_ERR(etsects->clock)) { err = PTR_ERR(etsects->clock); goto no_clock; } - gfar_phc_index = ptp_clock_index(etsects->clock); + gfar_phc_clock = ptp_clock_index(etsects->clock); dev_set_drvdata(&dev->dev, etsects); @@ -539,7 +539,7 @@ static int gianfar_ptp_remove(struct platform_device *dev) gfar_write(&etsects->regs->tmr_temask, 0); gfar_write(&etsects->regs->tmr_ctrl, 0); - gfar_phc_index = -1; + gfar_phc_clock = -1; ptp_clock_unregister(etsects->clock); iounmap(etsects->regs); release_resource(etsects->rsrc); diff --git a/trunk/drivers/net/ethernet/i825xx/Kconfig b/trunk/drivers/net/ethernet/i825xx/Kconfig index 959faf7388e2..fed5080a6b62 100644 --- a/trunk/drivers/net/ethernet/i825xx/Kconfig +++ b/trunk/drivers/net/ethernet/i825xx/Kconfig @@ -150,7 +150,7 @@ config SUN3_82586 config ZNET tristate "Zenith Z-Note support (EXPERIMENTAL)" - depends on EXPERIMENTAL && ISA_DMA_API && X86 + depends on EXPERIMENTAL && ISA_DMA_API ---help--- The Zenith Z-Note notebook computer has a built-in network (Ethernet) card, and this is the Linux driver for it. Note that the diff --git a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c index f9ac229ce222..3a8368e42ede 100644 --- a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -3150,17 +3150,6 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } - /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN, - * packets may get corrupted during padding by HW. - * To WA this issue, pad all small packets manually. - */ - if (skb->len < ETH_ZLEN) { - if (skb_pad(skb, ETH_ZLEN - skb->len)) - return NETDEV_TX_OK; - skb->len = ETH_ZLEN; - skb_set_tail_pointer(skb, ETH_ZLEN); - } - mss = skb_shinfo(skb)->gso_size; /* The controller does a simple calculation to * make sure there is enough room in the FIFO before diff --git a/trunk/drivers/net/ethernet/intel/igb/igb.h b/trunk/drivers/net/ethernet/intel/igb/igb.h index 8aad230c0592..43c8e2914263 100644 --- a/trunk/drivers/net/ethernet/intel/igb/igb.h +++ b/trunk/drivers/net/ethernet/intel/igb/igb.h @@ -101,6 +101,7 @@ struct vf_data_storage { u16 pf_vlan; /* When set, guest VLAN config not allowed. */ u16 pf_qos; u16 tx_rate; + struct pci_dev *vfdev; }; #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ @@ -168,8 +169,8 @@ struct igb_tx_buffer { unsigned int bytecount; u16 gso_segs; __be16 protocol; - DEFINE_DMA_UNMAP_ADDR(dma); - DEFINE_DMA_UNMAP_LEN(len); + dma_addr_t dma; + u32 length; u32 tx_flags; }; @@ -213,6 +214,7 @@ struct igb_q_vector { struct igb_ring_container rx, tx; struct napi_struct napi; + int numa_node; u16 itr_val; u8 set_itr; @@ -257,6 +259,7 @@ struct igb_ring { }; /* Items past this point are only used during ring alloc / free */ dma_addr_t dma; /* phys address of the ring */ + int numa_node; /* node to alloc ring memory on */ }; enum e1000_ring_flags_t { @@ -371,6 +374,7 @@ struct igb_adapter { int vf_rate_link_speed; u32 rss_queues; u32 wvbr; + int node; u32 *shadow_vfta; #ifdef CONFIG_IGB_PTP diff --git a/trunk/drivers/net/ethernet/intel/igb/igb_main.c b/trunk/drivers/net/ethernet/intel/igb/igb_main.c index 60bf46534835..246646b61a1a 100644 --- a/trunk/drivers/net/ethernet/intel/igb/igb_main.c +++ b/trunk/drivers/net/ethernet/intel/igb/igb_main.c @@ -172,7 +172,8 @@ static void igb_check_vf_rate_limit(struct igb_adapter *); #ifdef CONFIG_PCI_IOV static int igb_vf_configure(struct igb_adapter *adapter, int vf); -static bool igb_vfs_are_assigned(struct igb_adapter *adapter); +static int igb_find_enabled_vfs(struct igb_adapter *adapter); +static int igb_check_vf_assignment(struct igb_adapter *adapter); #endif #ifdef CONFIG_PM @@ -403,8 +404,8 @@ static void igb_dump(struct igb_adapter *adapter) buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n", n, tx_ring->next_to_use, tx_ring->next_to_clean, - (u64)dma_unmap_addr(buffer_info, dma), - dma_unmap_len(buffer_info, len), + (u64)buffer_info->dma, + buffer_info->length, buffer_info->next_to_watch, (u64)buffer_info->time_stamp); } @@ -455,8 +456,8 @@ static void igb_dump(struct igb_adapter *adapter) " %04X %p %016llX %p%s\n", i, le64_to_cpu(u0->a), le64_to_cpu(u0->b), - (u64)dma_unmap_addr(buffer_info, dma), - dma_unmap_len(buffer_info, len), + (u64)buffer_info->dma, + buffer_info->length, buffer_info->next_to_watch, (u64)buffer_info->time_stamp, buffer_info->skb, next_desc); @@ -465,8 +466,7 @@ static void igb_dump(struct igb_adapter *adapter) print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, buffer_info->skb->data, - dma_unmap_len(buffer_info, len), - true); + buffer_info->length, true); } } @@ -683,29 +683,52 @@ static int igb_alloc_queues(struct igb_adapter *adapter) { struct igb_ring *ring; int i; + int orig_node = adapter->node; for (i = 0; i < adapter->num_tx_queues; i++) { - ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); + if (orig_node == -1) { + int cur_node = next_online_node(adapter->node); + if (cur_node == MAX_NUMNODES) + cur_node = first_online_node; + adapter->node = cur_node; + } + ring = kzalloc_node(sizeof(struct igb_ring), GFP_KERNEL, + adapter->node); + if (!ring) + ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); if (!ring) goto err; ring->count = adapter->tx_ring_count; ring->queue_index = i; ring->dev = &adapter->pdev->dev; ring->netdev = adapter->netdev; + ring->numa_node = adapter->node; /* For 82575, context index must be unique per ring. */ if (adapter->hw.mac.type == e1000_82575) set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags); adapter->tx_ring[i] = ring; } + /* Restore the adapter's original node */ + adapter->node = orig_node; for (i = 0; i < adapter->num_rx_queues; i++) { - ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); + if (orig_node == -1) { + int cur_node = next_online_node(adapter->node); + if (cur_node == MAX_NUMNODES) + cur_node = first_online_node; + adapter->node = cur_node; + } + ring = kzalloc_node(sizeof(struct igb_ring), GFP_KERNEL, + adapter->node); + if (!ring) + ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); if (!ring) goto err; ring->count = adapter->rx_ring_count; ring->queue_index = i; ring->dev = &adapter->pdev->dev; ring->netdev = adapter->netdev; + ring->numa_node = adapter->node; /* set flag indicating ring supports SCTP checksum offload */ if (adapter->hw.mac.type >= e1000_82576) set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); @@ -719,12 +742,16 @@ static int igb_alloc_queues(struct igb_adapter *adapter) adapter->rx_ring[i] = ring; } + /* Restore the adapter's original node */ + adapter->node = orig_node; igb_cache_ring_register(adapter); return 0; err: + /* Restore the adapter's original node */ + adapter->node = orig_node; igb_free_queues(adapter); return -ENOMEM; @@ -1090,10 +1117,24 @@ static int igb_alloc_q_vectors(struct igb_adapter *adapter) struct igb_q_vector *q_vector; struct e1000_hw *hw = &adapter->hw; int v_idx; + int orig_node = adapter->node; for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { - q_vector = kzalloc(sizeof(struct igb_q_vector), - GFP_KERNEL); + if ((adapter->num_q_vectors == (adapter->num_rx_queues + + adapter->num_tx_queues)) && + (adapter->num_rx_queues == v_idx)) + adapter->node = orig_node; + if (orig_node == -1) { + int cur_node = next_online_node(adapter->node); + if (cur_node == MAX_NUMNODES) + cur_node = first_online_node; + adapter->node = cur_node; + } + q_vector = kzalloc_node(sizeof(struct igb_q_vector), GFP_KERNEL, + adapter->node); + if (!q_vector) + q_vector = kzalloc(sizeof(struct igb_q_vector), + GFP_KERNEL); if (!q_vector) goto err_out; q_vector->adapter = adapter; @@ -1102,10 +1143,14 @@ static int igb_alloc_q_vectors(struct igb_adapter *adapter) netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64); adapter->q_vector[v_idx] = q_vector; } + /* Restore the adapter's original node */ + adapter->node = orig_node; return 0; err_out: + /* Restore the adapter's original node */ + adapter->node = orig_node; igb_free_q_vectors(adapter); return -ENOMEM; } @@ -2255,11 +2300,11 @@ static void __devexit igb_remove(struct pci_dev *pdev) /* reclaim resources allocated to VFs */ if (adapter->vf_data) { /* disable iov and allow time for transactions to clear */ - if (igb_vfs_are_assigned(adapter)) { - dev_info(&pdev->dev, "Unloading driver while VFs are assigned - VFs will not be deallocated\n"); - } else { + if (!igb_check_vf_assignment(adapter)) { pci_disable_sriov(pdev); msleep(500); + } else { + dev_info(&pdev->dev, "VF(s) assigned to guests!\n"); } kfree(adapter->vf_data); @@ -2299,7 +2344,7 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter) #ifdef CONFIG_PCI_IOV struct pci_dev *pdev = adapter->pdev; struct e1000_hw *hw = &adapter->hw; - int old_vfs = pci_num_vf(adapter->pdev); + int old_vfs = igb_find_enabled_vfs(adapter); int i; /* Virtualization features not supported on i210 family. */ @@ -2379,6 +2424,8 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) VLAN_HLEN; adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; + adapter->node = -1; + spin_lock_init(&adapter->stats64_lock); #ifdef CONFIG_PCI_IOV switch (hw->mac.type) { @@ -2625,11 +2672,13 @@ static int igb_close(struct net_device *netdev) int igb_setup_tx_resources(struct igb_ring *tx_ring) { struct device *dev = tx_ring->dev; + int orig_node = dev_to_node(dev); int size; size = sizeof(struct igb_tx_buffer) * tx_ring->count; - - tx_ring->tx_buffer_info = vzalloc(size); + tx_ring->tx_buffer_info = vzalloc_node(size, tx_ring->numa_node); + if (!tx_ring->tx_buffer_info) + tx_ring->tx_buffer_info = vzalloc(size); if (!tx_ring->tx_buffer_info) goto err; @@ -2637,10 +2686,18 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring) tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); + set_dev_node(dev, tx_ring->numa_node); tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, &tx_ring->dma, GFP_KERNEL); + set_dev_node(dev, orig_node); + if (!tx_ring->desc) + tx_ring->desc = dma_alloc_coherent(dev, + tx_ring->size, + &tx_ring->dma, + GFP_KERNEL); + if (!tx_ring->desc) goto err; @@ -2651,8 +2708,8 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring) err: vfree(tx_ring->tx_buffer_info); - tx_ring->tx_buffer_info = NULL; - dev_err(dev, "Unable to allocate memory for the Tx descriptor ring\n"); + dev_err(dev, + "Unable to allocate memory for the transmit descriptor ring\n"); return -ENOMEM; } @@ -2769,23 +2826,34 @@ static void igb_configure_tx(struct igb_adapter *adapter) int igb_setup_rx_resources(struct igb_ring *rx_ring) { struct device *dev = rx_ring->dev; - int size; + int orig_node = dev_to_node(dev); + int size, desc_len; size = sizeof(struct igb_rx_buffer) * rx_ring->count; - - rx_ring->rx_buffer_info = vzalloc(size); + rx_ring->rx_buffer_info = vzalloc_node(size, rx_ring->numa_node); + if (!rx_ring->rx_buffer_info) + rx_ring->rx_buffer_info = vzalloc(size); if (!rx_ring->rx_buffer_info) goto err; + desc_len = sizeof(union e1000_adv_rx_desc); /* Round up to nearest 4K */ - rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc); + rx_ring->size = rx_ring->count * desc_len; rx_ring->size = ALIGN(rx_ring->size, 4096); + set_dev_node(dev, rx_ring->numa_node); rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, &rx_ring->dma, GFP_KERNEL); + set_dev_node(dev, orig_node); + if (!rx_ring->desc) + rx_ring->desc = dma_alloc_coherent(dev, + rx_ring->size, + &rx_ring->dma, + GFP_KERNEL); + if (!rx_ring->desc) goto err; @@ -2797,7 +2865,8 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring) err: vfree(rx_ring->rx_buffer_info); rx_ring->rx_buffer_info = NULL; - dev_err(dev, "Unable to allocate memory for the Rx descriptor ring\n"); + dev_err(dev, "Unable to allocate memory for the receive descriptor" + " ring\n"); return -ENOMEM; } @@ -2835,48 +2904,57 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 mrqc, rxcsum; - u32 j, num_rx_queues, shift = 0; - static const u32 rsskey[10] = { 0xDA565A6D, 0xC20E5B25, 0x3D256741, - 0xB08FA343, 0xCB2BCAD0, 0xB4307BAE, - 0xA32DCB77, 0x0CF23080, 0x3BB7426A, - 0xFA01ACBE }; + u32 j, num_rx_queues, shift = 0, shift2 = 0; + union e1000_reta { + u32 dword; + u8 bytes[4]; + } reta; + static const u8 rsshash[40] = { + 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, 0x41, 0x67, + 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, 0xd0, 0xca, 0x2b, 0xcb, + 0xae, 0x7b, 0x30, 0xb4, 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, + 0xf2, 0x0c, 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa }; /* Fill out hash function seeds */ - for (j = 0; j < 10; j++) - wr32(E1000_RSSRK(j), rsskey[j]); + for (j = 0; j < 10; j++) { + u32 rsskey = rsshash[(j * 4)]; + rsskey |= rsshash[(j * 4) + 1] << 8; + rsskey |= rsshash[(j * 4) + 2] << 16; + rsskey |= rsshash[(j * 4) + 3] << 24; + array_wr32(E1000_RSSRK(0), j, rsskey); + } num_rx_queues = adapter->rss_queues; - switch (hw->mac.type) { - case e1000_82575: - shift = 6; - break; - case e1000_82576: - /* 82576 supports 2 RSS queues for SR-IOV */ - if (adapter->vfs_allocated_count) { + if (adapter->vfs_allocated_count) { + /* 82575 and 82576 supports 2 RSS queues for VMDq */ + switch (hw->mac.type) { + case e1000_i350: + case e1000_82580: + num_rx_queues = 1; + shift = 0; + break; + case e1000_82576: shift = 3; num_rx_queues = 2; + break; + case e1000_82575: + shift = 2; + shift2 = 6; + default: + break; } - break; - default: - break; + } else { + if (hw->mac.type == e1000_82575) + shift = 6; } - /* - * Populate the indirection table 4 entries at a time. To do this - * we are generating the results for n and n+2 and then interleaving - * those with the results with n+1 and n+3. - */ - for (j = 0; j < 32; j++) { - /* first pass generates n and n+2 */ - u32 base = ((j * 0x00040004) + 0x00020000) * num_rx_queues; - u32 reta = (base & 0x07800780) >> (7 - shift); - - /* second pass generates n+1 and n+3 */ - base += 0x00010001 * num_rx_queues; - reta |= (base & 0x07800780) << (1 + shift); - - wr32(E1000_RETA(j), reta); + for (j = 0; j < (32 * 4); j++) { + reta.bytes[j & 3] = (j % num_rx_queues) << shift; + if (shift2) + reta.bytes[j & 3] |= num_rx_queues << shift2; + if ((j & 3) == 3) + wr32(E1000_RETA(j >> 2), reta.dword); } /* @@ -3199,20 +3277,20 @@ void igb_unmap_and_free_tx_resource(struct igb_ring *ring, { if (tx_buffer->skb) { dev_kfree_skb_any(tx_buffer->skb); - if (dma_unmap_len(tx_buffer, len)) + if (tx_buffer->dma) dma_unmap_single(ring->dev, - dma_unmap_addr(tx_buffer, dma), - dma_unmap_len(tx_buffer, len), + tx_buffer->dma, + tx_buffer->length, DMA_TO_DEVICE); - } else if (dma_unmap_len(tx_buffer, len)) { + } else if (tx_buffer->dma) { dma_unmap_page(ring->dev, - dma_unmap_addr(tx_buffer, dma), - dma_unmap_len(tx_buffer, len), + tx_buffer->dma, + tx_buffer->length, DMA_TO_DEVICE); } tx_buffer->next_to_watch = NULL; tx_buffer->skb = NULL; - dma_unmap_len_set(tx_buffer, len, 0); + tx_buffer->dma = 0; /* buffer_info must be completely set up in the transmit path */ } @@ -4207,7 +4285,7 @@ static void igb_tx_map(struct igb_ring *tx_ring, const u8 hdr_len) { struct sk_buff *skb = first->skb; - struct igb_tx_buffer *tx_buffer; + struct igb_tx_buffer *tx_buffer_info; union e1000_adv_tx_desc *tx_desc; dma_addr_t dma; struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; @@ -4228,8 +4306,8 @@ static void igb_tx_map(struct igb_ring *tx_ring, goto dma_error; /* record length, and DMA address */ - dma_unmap_len_set(first, len, size); - dma_unmap_addr_set(first, dma, dma); + first->length = size; + first->dma = dma; tx_desc->read.buffer_addr = cpu_to_le64(dma); for (;;) { @@ -4271,9 +4349,9 @@ static void igb_tx_map(struct igb_ring *tx_ring, if (dma_mapping_error(tx_ring->dev, dma)) goto dma_error; - tx_buffer = &tx_ring->tx_buffer_info[i]; - dma_unmap_len_set(tx_buffer, len, size); - dma_unmap_addr_set(tx_buffer, dma, dma); + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + tx_buffer_info->length = size; + tx_buffer_info->dma = dma; tx_desc->read.olinfo_status = 0; tx_desc->read.buffer_addr = cpu_to_le64(dma); @@ -4324,9 +4402,9 @@ static void igb_tx_map(struct igb_ring *tx_ring, /* clear dma mappings for failed tx_buffer_info map */ for (;;) { - tx_buffer = &tx_ring->tx_buffer_info[i]; - igb_unmap_and_free_tx_resource(tx_ring, tx_buffer); - if (tx_buffer == first) + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); + if (tx_buffer_info == first) break; if (i == 0) i = tx_ring->count; @@ -4699,11 +4777,7 @@ void igb_update_stats(struct igb_adapter *adapter, reg = rd32(E1000_CTRL_EXT); if (!(reg & E1000_CTRL_EXT_LINK_MODE_MASK)) { adapter->stats.rxerrc += rd32(E1000_RXERRC); - - /* this stat has invalid values on i210/i211 */ - if ((hw->mac.type != e1000_i210) && - (hw->mac.type != e1000_i211)) - adapter->stats.tncrs += rd32(E1000_TNCRS); + adapter->stats.tncrs += rd32(E1000_TNCRS); } adapter->stats.tsctc += rd32(E1000_TSCTC); @@ -4963,43 +5037,102 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event, static int igb_vf_configure(struct igb_adapter *adapter, int vf) { unsigned char mac_addr[ETH_ALEN]; + struct pci_dev *pdev = adapter->pdev; + struct e1000_hw *hw = &adapter->hw; + struct pci_dev *pvfdev; + unsigned int device_id; + u16 thisvf_devfn; eth_random_addr(mac_addr); igb_set_vf_mac(adapter, vf, mac_addr); - return 0; + switch (adapter->hw.mac.type) { + case e1000_82576: + device_id = IGB_82576_VF_DEV_ID; + /* VF Stride for 82576 is 2 */ + thisvf_devfn = (pdev->devfn + 0x80 + (vf << 1)) | + (pdev->devfn & 1); + break; + case e1000_i350: + device_id = IGB_I350_VF_DEV_ID; + /* VF Stride for I350 is 4 */ + thisvf_devfn = (pdev->devfn + 0x80 + (vf << 2)) | + (pdev->devfn & 3); + break; + default: + device_id = 0; + thisvf_devfn = 0; + break; + } + + pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); + while (pvfdev) { + if (pvfdev->devfn == thisvf_devfn) + break; + pvfdev = pci_get_device(hw->vendor_id, + device_id, pvfdev); + } + + if (pvfdev) + adapter->vf_data[vf].vfdev = pvfdev; + else + dev_err(&pdev->dev, + "Couldn't find pci dev ptr for VF %4.4x\n", + thisvf_devfn); + return pvfdev != NULL; } -static bool igb_vfs_are_assigned(struct igb_adapter *adapter) +static int igb_find_enabled_vfs(struct igb_adapter *adapter) { + struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; - struct pci_dev *vfdev; - int dev_id; + struct pci_dev *pvfdev; + u16 vf_devfn = 0; + u16 vf_stride; + unsigned int device_id; + int vfs_found = 0; switch (adapter->hw.mac.type) { case e1000_82576: - dev_id = IGB_82576_VF_DEV_ID; + device_id = IGB_82576_VF_DEV_ID; + /* VF Stride for 82576 is 2 */ + vf_stride = 2; break; case e1000_i350: - dev_id = IGB_I350_VF_DEV_ID; + device_id = IGB_I350_VF_DEV_ID; + /* VF Stride for I350 is 4 */ + vf_stride = 4; break; default: - return false; + device_id = 0; + vf_stride = 0; + break; } - /* loop through all the VFs to see if we own any that are assigned */ - vfdev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL); - while (vfdev) { - /* if we don't own it we don't care */ - if (vfdev->is_virtfn && vfdev->physfn == pdev) { - /* if it is assigned we cannot release it */ - if (vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) + vf_devfn = pdev->devfn + 0x80; + pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); + while (pvfdev) { + if (pvfdev->devfn == vf_devfn && + (pvfdev->bus->number >= pdev->bus->number)) + vfs_found++; + vf_devfn += vf_stride; + pvfdev = pci_get_device(hw->vendor_id, + device_id, pvfdev); + } + + return vfs_found; +} + +static int igb_check_vf_assignment(struct igb_adapter *adapter) +{ + int i; + for (i = 0; i < adapter->vfs_allocated_count; i++) { + if (adapter->vf_data[i].vfdev) { + if (adapter->vf_data[i].vfdev->dev_flags & + PCI_DEV_FLAGS_ASSIGNED) return true; } - - vfdev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, vfdev); } - return false; } @@ -5682,7 +5815,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) struct igb_adapter *adapter = q_vector->adapter; struct igb_ring *tx_ring = q_vector->tx.ring; struct igb_tx_buffer *tx_buffer; - union e1000_adv_tx_desc *tx_desc; + union e1000_adv_tx_desc *tx_desc, *eop_desc; unsigned int total_bytes = 0, total_packets = 0; unsigned int budget = q_vector->tx.work_limit; unsigned int i = tx_ring->next_to_clean; @@ -5694,16 +5827,16 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) tx_desc = IGB_TX_DESC(tx_ring, i); i -= tx_ring->count; - do { - union e1000_adv_tx_desc *eop_desc = tx_buffer->next_to_watch; + for (; budget; budget--) { + eop_desc = tx_buffer->next_to_watch; + + /* prevent any other reads prior to eop_desc */ + rmb(); /* if next_to_watch is not set then there is no work pending */ if (!eop_desc) break; - /* prevent any other reads prior to eop_desc */ - rmb(); - /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) break; @@ -5717,19 +5850,18 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) /* free the skb */ dev_kfree_skb_any(tx_buffer->skb); + tx_buffer->skb = NULL; /* unmap skb header data */ dma_unmap_single(tx_ring->dev, - dma_unmap_addr(tx_buffer, dma), - dma_unmap_len(tx_buffer, len), + tx_buffer->dma, + tx_buffer->length, DMA_TO_DEVICE); - /* clear tx_buffer data */ - tx_buffer->skb = NULL; - dma_unmap_len_set(tx_buffer, len, 0); - /* clear last DMA location and unmap remaining buffers */ while (tx_desc != eop_desc) { + tx_buffer->dma = 0; + tx_buffer++; tx_desc++; i++; @@ -5740,15 +5872,17 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) } /* unmap any remaining paged data */ - if (dma_unmap_len(tx_buffer, len)) { + if (tx_buffer->dma) { dma_unmap_page(tx_ring->dev, - dma_unmap_addr(tx_buffer, dma), - dma_unmap_len(tx_buffer, len), + tx_buffer->dma, + tx_buffer->length, DMA_TO_DEVICE); - dma_unmap_len_set(tx_buffer, len, 0); } } + /* clear last DMA location */ + tx_buffer->dma = 0; + /* move us one more past the eop_desc for start of next pkt */ tx_buffer++; tx_desc++; @@ -5758,13 +5892,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) tx_buffer = tx_ring->tx_buffer_info; tx_desc = IGB_TX_DESC(tx_ring, 0); } - - /* issue prefetch for next Tx descriptor */ - prefetch(tx_desc); - - /* update budget accounting */ - budget--; - } while (likely(budget)); + } netdev_tx_completed_queue(txring_txq(tx_ring), total_packets, total_bytes); @@ -5780,10 +5908,12 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { struct e1000_hw *hw = &adapter->hw; + eop_desc = tx_buffer->next_to_watch; + /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ clear_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); - if (tx_buffer->next_to_watch && + if (eop_desc && time_after(jiffies, tx_buffer->time_stamp + (adapter->tx_timeout_factor * HZ)) && !(rd32(E1000_STATUS) & E1000_STATUS_TXOFF)) { @@ -5807,9 +5937,9 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) tx_ring->next_to_use, tx_ring->next_to_clean, tx_buffer->time_stamp, - tx_buffer->next_to_watch, + eop_desc, jiffies, - tx_buffer->next_to_watch->wb.status); + eop_desc->wb.status); netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); diff --git a/trunk/drivers/net/ethernet/intel/igb/igb_ptp.c b/trunk/drivers/net/ethernet/intel/igb/igb_ptp.c index ee21445157a3..e13ba1d5369f 100644 --- a/trunk/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/trunk/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -752,8 +752,7 @@ void igb_ptp_init(struct igb_adapter *adapter) wr32(E1000_IMS, E1000_IMS_TS); } - adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, - &adapter->pdev->dev); + adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps); if (IS_ERR(adapter->ptp_clock)) { adapter->ptp_clock = NULL; dev_err(&adapter->pdev->dev, "ptp_clock_register failed\n"); diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 0ba6d9561bdb..70d27a361857 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -5560,9 +5560,8 @@ static void ixgbe_spoof_check(struct ixgbe_adapter *adapter) { u32 ssvpc; - /* Do not perform spoof check for 82598 or if not in IOV mode */ - if (adapter->hw.mac.type == ixgbe_mac_82598EB || - adapter->num_vfs == 0) + /* Do not perform spoof check for 82598 */ + if (adapter->hw.mac.type == ixgbe_mac_82598EB) return; ssvpc = IXGBE_READ_REG(&adapter->hw, IXGBE_SSVPC); @@ -6889,7 +6888,7 @@ static int ixgbe_set_features(struct net_device *netdev, return 0; } -static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], +static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct net_device *dev, const unsigned char *addr, u16 flags) diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 39881cb17a4b..3456d5617143 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -960,8 +960,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) /* (Re)start the overflow check */ adapter->flags2 |= IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED; - adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, - &adapter->pdev->dev); + adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps); if (IS_ERR(adapter->ptp_clock)) { adapter->ptp_clock = NULL; e_dev_err("ptp_clock_register failed\n"); diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 383b4e1cd175..eb26fda63c99 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -261,11 +261,6 @@ enum ixbgevf_state_t { __IXGBEVF_DOWN }; -struct ixgbevf_cb { - struct sk_buff *prev; -}; -#define IXGBE_CB(skb) ((struct ixgbevf_cb *)(skb)->cb) - enum ixgbevf_boards { board_82599_vf, board_X540_vf, diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index cf372ee49d0c..c5ffe1dd3fcd 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -263,8 +263,6 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, tx_ring->total_bytes += total_bytes; tx_ring->total_packets += total_packets; u64_stats_update_end(&tx_ring->syncp); - q_vector->tx.total_bytes += total_bytes; - q_vector->tx.total_packets += total_packets; return count < tx_ring->count; } @@ -274,10 +272,12 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, * @q_vector: structure containing interrupt and ring information * @skb: packet to send up * @status: hardware indication of status of receive + * @rx_ring: rx descriptor ring (for a specific queue) to setup * @rx_desc: rx descriptor **/ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector, struct sk_buff *skb, u8 status, + struct ixgbevf_ring *ring, union ixgbe_adv_rx_desc *rx_desc) { struct ixgbevf_adapter *adapter = q_vector->adapter; @@ -433,21 +433,11 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, if (!(staterr & IXGBE_RXD_STAT_EOP)) { skb->next = next_buffer->skb; - IXGBE_CB(skb->next)->prev = skb; + skb->next->prev = skb; adapter->non_eop_descs++; goto next_desc; } - /* we should not be chaining buffers, if we did drop the skb */ - if (IXGBE_CB(skb)->prev) { - do { - struct sk_buff *this = skb; - skb = IXGBE_CB(skb)->prev; - dev_kfree_skb(this); - } while (skb); - goto next_desc; - } - /* ERR_MASK will only have valid bits if EOP set */ if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) { dev_kfree_skb_irq(skb); @@ -471,7 +461,7 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, } skb->protocol = eth_type_trans(skb, rx_ring->netdev); - ixgbevf_receive_skb(q_vector, skb, staterr, rx_desc); + ixgbevf_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc); next_desc: rx_desc->wb.upper.status_error = 0; @@ -500,8 +490,6 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, rx_ring->total_packets += total_rx_packets; rx_ring->total_bytes += total_rx_bytes; u64_stats_update_end(&rx_ring->syncp); - q_vector->rx.total_packets += total_rx_packets; - q_vector->rx.total_bytes += total_rx_bytes; return !!budget; } @@ -728,15 +716,40 @@ static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector) } } -static irqreturn_t ixgbevf_msix_other(int irq, void *data) +static irqreturn_t ixgbevf_msix_mbx(int irq, void *data) { struct ixgbevf_adapter *adapter = data; struct ixgbe_hw *hw = &adapter->hw; + u32 msg; + bool got_ack = false; - hw->mac.get_link_status = 1; + if (!hw->mbx.ops.check_for_ack(hw)) + got_ack = true; - if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies); + if (!hw->mbx.ops.check_for_msg(hw)) { + hw->mbx.ops.read(hw, &msg, 1); + + if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG) + mod_timer(&adapter->watchdog_timer, + round_jiffies(jiffies + 1)); + + if (msg & IXGBE_VT_MSGTYPE_NACK) + pr_warn("Last Request of type %2.2x to PF Nacked\n", + msg & 0xFF); + /* + * Restore the PFSTS bit in case someone is polling for a + * return message from the PF + */ + hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFSTS; + } + + /* + * checking for the ack clears the PFACK bit. Place + * it back in the v2p_mailbox cache so that anyone + * polling for an ack will not miss it + */ + if (got_ack) + hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK; IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_other); @@ -886,10 +899,10 @@ static int ixgbevf_request_msix_irqs(struct ixgbevf_adapter *adapter) } err = request_irq(adapter->msix_entries[vector].vector, - &ixgbevf_msix_other, 0, netdev->name, adapter); + &ixgbevf_msix_mbx, 0, netdev->name, adapter); if (err) { hw_dbg(&adapter->hw, - "request_irq for msix_other failed: %d\n", err); + "request_irq for msix_mbx failed: %d\n", err); goto free_queue_irqs; } @@ -1126,47 +1139,36 @@ static int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; - int err; - - if (!hw->mac.ops.set_vfta) - return -EOPNOTSUPP; spin_lock(&adapter->mbx_lock); /* add VID to filter table */ - err = hw->mac.ops.set_vfta(hw, vid, 0, true); + if (hw->mac.ops.set_vfta) + hw->mac.ops.set_vfta(hw, vid, 0, true); spin_unlock(&adapter->mbx_lock); - /* translate error return types so error makes sense */ - if (err == IXGBE_ERR_MBX) - return -EIO; - - if (err == IXGBE_ERR_INVALID_ARGUMENT) - return -EACCES; - set_bit(vid, adapter->active_vlans); - return err; + return 0; } static int ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; - int err = -EOPNOTSUPP; spin_lock(&adapter->mbx_lock); /* remove VID from filter table */ if (hw->mac.ops.set_vfta) - err = hw->mac.ops.set_vfta(hw, vid, 0, false); + hw->mac.ops.set_vfta(hw, vid, 0, false); spin_unlock(&adapter->mbx_lock); clear_bit(vid, adapter->active_vlans); - return err; + return 0; } static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter) @@ -1409,7 +1411,6 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) ixgbevf_save_reset_stats(adapter); ixgbevf_init_last_counter_stats(adapter); - hw->mac.get_link_status = 1; mod_timer(&adapter->watchdog_timer, jiffies); } @@ -1460,7 +1461,7 @@ static void ixgbevf_clean_rx_ring(struct ixgbevf_adapter *adapter, rx_buffer_info->skb = NULL; do { struct sk_buff *this = skb; - skb = IXGBE_CB(skb)->prev; + skb = skb->prev; dev_kfree_skb(this); } while (skb); } @@ -1588,6 +1589,8 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter) void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter) { + struct ixgbe_hw *hw = &adapter->hw; + WARN_ON(in_interrupt()); while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) @@ -1600,8 +1603,10 @@ void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter) * watchdog task will continue to schedule reset tasks until * the PF is up and running. */ - ixgbevf_down(adapter); - ixgbevf_up(adapter); + if (!hw->mac.ops.reset_hw(hw)) { + ixgbevf_down(adapter); + ixgbevf_up(adapter); + } clear_bit(__IXGBEVF_RESETTING, &adapter->state); } diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/mbx.c b/trunk/drivers/net/ethernet/intel/ixgbevf/mbx.c index d5028ddf4b31..9c955900fe64 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/mbx.c +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/mbx.c @@ -86,17 +86,14 @@ static s32 ixgbevf_poll_for_ack(struct ixgbe_hw *hw) static s32 ixgbevf_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) { struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = -IXGBE_ERR_MBX; - - if (!mbx->ops.read) - goto out; + s32 ret_val = IXGBE_ERR_MBX; ret_val = ixgbevf_poll_for_msg(hw); /* if ack received read message, otherwise we timed out */ if (!ret_val) ret_val = mbx->ops.read(hw, msg, size); -out: + return ret_val; } @@ -112,11 +109,7 @@ static s32 ixgbevf_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) static s32 ixgbevf_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) { struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = -IXGBE_ERR_MBX; - - /* exit if either we can't write or there isn't a defined timeout */ - if (!mbx->ops.write || !mbx->timeout) - goto out; + s32 ret_val; /* send msg */ ret_val = mbx->ops.write(hw, msg, size); @@ -124,7 +117,7 @@ static s32 ixgbevf_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) /* if msg sent wait until we receive an ack */ if (!ret_val) ret_val = ixgbevf_poll_for_ack(hw); -out: + return ret_val; } diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/vf.c b/trunk/drivers/net/ethernet/intel/ixgbevf/vf.c index 0c7447e6fcc8..87b3f3bf1c1f 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/vf.c +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/vf.c @@ -349,32 +349,16 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw, static s32 ixgbevf_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) { - struct ixgbe_mbx_info *mbx = &hw->mbx; u32 msgbuf[2]; - s32 err; msgbuf[0] = IXGBE_VF_SET_VLAN; msgbuf[1] = vlan; /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */ msgbuf[0] |= vlan_on << IXGBE_VT_MSGINFO_SHIFT; - err = mbx->ops.write_posted(hw, msgbuf, 2); - if (err) - goto mbx_err; - - err = mbx->ops.read_posted(hw, msgbuf, 2); - if (err) - goto mbx_err; - - /* remove extra bits from the message */ - msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS; - msgbuf[0] &= ~(0xFF << IXGBE_VT_MSGINFO_SHIFT); - - if (msgbuf[0] != (IXGBE_VF_SET_VLAN | IXGBE_VT_MSGTYPE_ACK)) - err = IXGBE_ERR_INVALID_ARGUMENT; + ixgbevf_write_msg_read_ack(hw, msgbuf, 2); -mbx_err: - return err; + return 0; } /** @@ -408,23 +392,20 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw, bool *link_up, bool autoneg_wait_to_complete) { - struct ixgbe_mbx_info *mbx = &hw->mbx; - struct ixgbe_mac_info *mac = &hw->mac; - s32 ret_val = 0; u32 links_reg; - u32 in_msg = 0; - - /* If we were hit with a reset drop the link */ - if (!mbx->ops.check_for_rst(hw) || !mbx->timeout) - mac->get_link_status = true; - if (!mac->get_link_status) - goto out; + if (!(hw->mbx.ops.check_for_rst(hw))) { + *link_up = false; + *speed = 0; + return -1; + } - /* if link status is down no point in checking to see if pf is up */ links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS); - if (!(links_reg & IXGBE_LINKS_UP)) - goto out; + + if (links_reg & IXGBE_LINKS_UP) + *link_up = true; + else + *link_up = false; switch (links_reg & IXGBE_LINKS_SPEED_82599) { case IXGBE_LINKS_SPEED_10G_82599: @@ -438,31 +419,7 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw, break; } - /* if the read failed it could just be a mailbox collision, best wait - * until we are called again and don't report an error */ - if (mbx->ops.read(hw, &in_msg, 1)) - goto out; - - if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) { - /* msg is not CTS and is NACK we must have lost CTS status */ - if (in_msg & IXGBE_VT_MSGTYPE_NACK) - ret_val = -1; - goto out; - } - - /* the pf is talking, if we timed out in the past we reinit */ - if (!mbx->timeout) { - ret_val = -1; - goto out; - } - - /* if we passed all the tests above then the link is up and we no - * longer need to check for link */ - mac->get_link_status = false; - -out: - *link_up = !mac->get_link_status; - return ret_val; + return 0; } /** diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c index c10e3a6de09f..10bba09c44ea 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -712,6 +712,10 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) if (bounce) tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size); + /* Run destructor before passing skb to HW */ + if (likely(!skb_shared(skb))) + skb_orphan(skb); + if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) { *(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn); op_own |= htonl((bf_index & 0xffff) << 8); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c index 31d02649be41..daf417923661 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -227,10 +227,9 @@ int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev) MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); } -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) +int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) { - u32 i = (obj & (table->num_obj - 1)) / - (MLX4_TABLE_CHUNK_SIZE / table->obj_size); + int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); int ret = 0; mutex_lock(&table->mutex); @@ -263,18 +262,16 @@ int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) return ret; } -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) +void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) { - u32 i; - u64 offset; + int i; i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); mutex_lock(&table->mutex); if (--table->icm[i]->refcount == 0) { - offset = (u64) i * MLX4_TABLE_CHUNK_SIZE; - mlx4_UNMAP_ICM(dev, table->virt + offset, + mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); mlx4_free_icm(dev, table->icm[i], table->coherent); table->icm[i] = NULL; @@ -283,11 +280,9 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) mutex_unlock(&table->mutex); } -void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, - dma_addr_t *dma_handle) +void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle) { - int offset, dma_offset, i; - u64 idx; + int idx, offset, dma_offset, i; struct mlx4_icm_chunk *chunk; struct mlx4_icm *icm; struct page *page = NULL; @@ -297,7 +292,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, mutex_lock(&table->mutex); - idx = (u64) (obj & (table->num_obj - 1)) * table->obj_size; + idx = (obj & (table->num_obj - 1)) * table->obj_size; icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE]; dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE; @@ -331,11 +326,10 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, } int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u32 start, u32 end) + int start, int end) { int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size; - int err; - u32 i; + int i, err; for (i = start; i <= end; i += inc) { err = mlx4_table_get(dev, table, i); @@ -355,9 +349,9 @@ int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, } void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u32 start, u32 end) + int start, int end) { - u32 i; + int i; for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size) mlx4_table_put(dev, table, i); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.h b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.h index dee67fa39107..a67744f53506 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.h @@ -71,17 +71,17 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, gfp_t gfp_mask, int coherent); void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); +int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); +void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u32 start, u32 end); + int start, int end); void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u32 start, u32 end); + int start, int end); int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, u64 virt, int obj_size, u32 nobj, int reserved, int use_lowmem, int use_coherent); void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); -void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle); +void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle); static inline void mlx4_icm_first(struct mlx4_icm *icm, struct mlx4_icm_iter *iter) diff --git a/trunk/drivers/net/ethernet/mipsnet.c b/trunk/drivers/net/ethernet/mipsnet.c new file mode 100644 index 000000000000..db5285befe2a --- /dev/null +++ b/trunk/drivers/net/ethernet/mipsnet.c @@ -0,0 +1,345 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MIPSNET_VERSION "2007-11-17" + +/* + * Net status/control block as seen by sw in the core. + */ +struct mipsnet_regs { + /* + * Device info for probing, reads as MIPSNET%d where %d is some + * form of version. + */ + u64 devId; /*0x00 */ + + /* + * read only busy flag. + * Set and cleared by the Net Device to indicate that an rx or a tx + * is in progress. + */ + u32 busy; /*0x08 */ + + /* + * Set by the Net Device. + * The device will set it once data has been received. + * The value is the number of bytes that should be read from + * rxDataBuffer. The value will decrease till 0 until all the data + * from rxDataBuffer has been read. + */ + u32 rxDataCount; /*0x0c */ +#define MIPSNET_MAX_RXTX_DATACOUNT (1 << 16) + + /* + * Settable from the MIPS core, cleared by the Net Device. + * The core should set the number of bytes it wants to send, + * then it should write those bytes of data to txDataBuffer. + * The device will clear txDataCount has been processed (not + * necessarily sent). + */ + u32 txDataCount; /*0x10 */ + + /* + * Interrupt control + * + * Used to clear the interrupted generated by this dev. + * Write a 1 to clear the interrupt. (except bit31). + * + * Bit0 is set if it was a tx-done interrupt. + * Bit1 is set when new rx-data is available. + * Until this bit is cleared there will be no other RXs. + * + * Bit31 is used for testing, it clears after a read. + * Writing 1 to this bit will cause an interrupt to be generated. + * To clear the test interrupt, write 0 to this register. + */ + u32 interruptControl; /*0x14 */ +#define MIPSNET_INTCTL_TXDONE (1u << 0) +#define MIPSNET_INTCTL_RXDONE (1u << 1) +#define MIPSNET_INTCTL_TESTBIT (1u << 31) + + /* + * Readonly core-specific interrupt info for the device to signal + * the core. The meaning of the contents of this field might change. + */ + /* XXX: the whole memIntf interrupt scheme is messy: the device + * should have no control what so ever of what VPE/register set is + * being used. + * The MemIntf should only expose interrupt lines, and something in + * the config should be responsible for the line<->core/vpe bindings. + */ + u32 interruptInfo; /*0x18 */ + + /* + * This is where the received data is read out. + * There is more data to read until rxDataReady is 0. + * Only 1 byte at this regs offset is used. + */ + u32 rxDataBuffer; /*0x1c */ + + /* + * This is where the data to transmit is written. + * Data should be written for the amount specified in the + * txDataCount register. + * Only 1 byte at this regs offset is used. + */ + u32 txDataBuffer; /*0x20 */ +}; + +#define regaddr(dev, field) \ + (dev->base_addr + offsetof(struct mipsnet_regs, field)) + +static char mipsnet_string[] = "mipsnet"; + +/* + * Copy data from the MIPSNET rx data port + */ +static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata, + int len) +{ + for (; len > 0; len--, kdata++) + *kdata = inb(regaddr(dev, rxDataBuffer)); + + return inl(regaddr(dev, rxDataCount)); +} + +static inline void mipsnet_put_todevice(struct net_device *dev, + struct sk_buff *skb) +{ + int count_to_go = skb->len; + char *buf_ptr = skb->data; + + outl(skb->len, regaddr(dev, txDataCount)); + + for (; count_to_go; buf_ptr++, count_to_go--) + outb(*buf_ptr, regaddr(dev, txDataBuffer)); + + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + dev_kfree_skb(skb); +} + +static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev) +{ + /* + * Only one packet at a time. Once TXDONE interrupt is serviced, the + * queue will be restarted. + */ + netif_stop_queue(dev); + mipsnet_put_todevice(dev, skb); + + return NETDEV_TX_OK; +} + +static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t len) +{ + struct sk_buff *skb; + + if (!len) + return len; + + skb = netdev_alloc_skb(dev, len + NET_IP_ALIGN); + if (!skb) { + dev->stats.rx_dropped++; + return -ENOMEM; + } + + skb_reserve(skb, NET_IP_ALIGN); + if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len)) + return -EFAULT; + + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + + netif_rx(skb); + + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; + + return len; +} + +static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + u32 int_flags; + irqreturn_t ret = IRQ_NONE; + + if (irq != dev->irq) + goto out_badirq; + + /* TESTBIT is cleared on read. */ + int_flags = inl(regaddr(dev, interruptControl)); + if (int_flags & MIPSNET_INTCTL_TESTBIT) { + /* TESTBIT takes effect after a write with 0. */ + outl(0, regaddr(dev, interruptControl)); + ret = IRQ_HANDLED; + } else if (int_flags & MIPSNET_INTCTL_TXDONE) { + /* Only one packet at a time, we are done. */ + dev->stats.tx_packets++; + netif_wake_queue(dev); + outl(MIPSNET_INTCTL_TXDONE, + regaddr(dev, interruptControl)); + ret = IRQ_HANDLED; + } else if (int_flags & MIPSNET_INTCTL_RXDONE) { + mipsnet_get_fromdev(dev, inl(regaddr(dev, rxDataCount))); + outl(MIPSNET_INTCTL_RXDONE, regaddr(dev, interruptControl)); + ret = IRQ_HANDLED; + } + return ret; + +out_badirq: + printk(KERN_INFO "%s: %s(): irq %d for unknown device\n", + dev->name, __func__, irq); + return ret; +} + +static int mipsnet_open(struct net_device *dev) +{ + int err; + + err = request_irq(dev->irq, mipsnet_interrupt, + IRQF_SHARED, dev->name, (void *) dev); + if (err) { + release_region(dev->base_addr, sizeof(struct mipsnet_regs)); + return err; + } + + netif_start_queue(dev); + + /* test interrupt handler */ + outl(MIPSNET_INTCTL_TESTBIT, regaddr(dev, interruptControl)); + + return 0; +} + +static int mipsnet_close(struct net_device *dev) +{ + netif_stop_queue(dev); + free_irq(dev->irq, dev); + return 0; +} + +static void mipsnet_set_mclist(struct net_device *dev) +{ +} + +static const struct net_device_ops mipsnet_netdev_ops = { + .ndo_open = mipsnet_open, + .ndo_stop = mipsnet_close, + .ndo_start_xmit = mipsnet_xmit, + .ndo_set_rx_mode = mipsnet_set_mclist, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + +static int __devinit mipsnet_probe(struct platform_device *dev) +{ + struct net_device *netdev; + int err; + + netdev = alloc_etherdev(0); + if (!netdev) { + err = -ENOMEM; + goto out; + } + + platform_set_drvdata(dev, netdev); + + netdev->netdev_ops = &mipsnet_netdev_ops; + + /* + * TODO: probe for these or load them from PARAM + */ + netdev->base_addr = 0x4200; + netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + + inl(regaddr(netdev, interruptInfo)); + + /* Get the io region now, get irq on open() */ + if (!request_region(netdev->base_addr, sizeof(struct mipsnet_regs), + "mipsnet")) { + err = -EBUSY; + goto out_free_netdev; + } + + /* + * Lacking any better mechanism to allocate a MAC address we use a + * random one ... + */ + eth_hw_addr_random(netdev); + + err = register_netdev(netdev); + if (err) { + printk(KERN_ERR "MIPSNet: failed to register netdev.\n"); + goto out_free_region; + } + + return 0; + +out_free_region: + release_region(netdev->base_addr, sizeof(struct mipsnet_regs)); + +out_free_netdev: + free_netdev(netdev); + +out: + return err; +} + +static int __devexit mipsnet_device_remove(struct platform_device *device) +{ + struct net_device *dev = platform_get_drvdata(device); + + unregister_netdev(dev); + release_region(dev->base_addr, sizeof(struct mipsnet_regs)); + free_netdev(dev); + platform_set_drvdata(device, NULL); + + return 0; +} + +static struct platform_driver mipsnet_driver = { + .driver = { + .name = mipsnet_string, + .owner = THIS_MODULE, + }, + .probe = mipsnet_probe, + .remove = __devexit_p(mipsnet_device_remove), +}; + +static int __init mipsnet_init_module(void) +{ + int err; + + printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. " + "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION); + + err = platform_driver_register(&mipsnet_driver); + if (err) + printk(KERN_ERR "Driver registration failed\n"); + + return err; +} + +static void __exit mipsnet_exit_module(void) +{ + platform_driver_unregister(&mipsnet_driver); +} + +module_init(mipsnet_init_module); +module_exit(mipsnet_exit_module); diff --git a/trunk/drivers/net/ethernet/octeon/octeon_mgmt.c b/trunk/drivers/net/ethernet/octeon/octeon_mgmt.c index a688a2ddcfd6..c42bbb16cdae 100644 --- a/trunk/drivers/net/ethernet/octeon/octeon_mgmt.c +++ b/trunk/drivers/net/ethernet/octeon/octeon_mgmt.c @@ -722,8 +722,10 @@ static int octeon_mgmt_init_phy(struct net_device *netdev) octeon_mgmt_adjust_link, 0, PHY_INTERFACE_MODE_MII); - if (!p->phydev) + if (IS_ERR(p->phydev)) { + p->phydev = NULL; return -1; + } phy_start_aneg(p->phydev); diff --git a/trunk/drivers/net/ethernet/pasemi/pasemi_mac.c b/trunk/drivers/net/ethernet/pasemi/pasemi_mac.c index 6fa74d530e44..e559dfa06d6a 100644 --- a/trunk/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/trunk/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -1101,9 +1101,9 @@ static int pasemi_mac_phy_init(struct net_device *dev) phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII); - if (!phydev) { + if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to phy\n", dev->name); - return -ENODEV; + return PTR_ERR(phydev); } mac->phydev = phydev; diff --git a/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index a77c558d8f40..342b3a79bd0f 100644 --- a/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/trunk/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1378,10 +1378,6 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter) struct pci_dev *root = pdev->bus->self; u32 aer_pos; - /* root bus? */ - if (!root) - return; - if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM && adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP) return; diff --git a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 2a179d087207..b8ead696141e 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -15,7 +15,7 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter) do { /* give atleast 1ms for firmware to respond */ - mdelay(1); + msleep(1); if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT) return QLCNIC_CDRP_RSP_TIMEOUT; @@ -601,7 +601,7 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter) qlcnic_fw_cmd_destroy_tx_ctx(adapter); /* Allow dma queues to drain after context reset */ - mdelay(20); + msleep(20); } } diff --git a/trunk/drivers/net/ethernet/sfc/ptp.c b/trunk/drivers/net/ethernet/sfc/ptp.c index 5b3dd028ce85..2b07a4eae07e 100644 --- a/trunk/drivers/net/ethernet/sfc/ptp.c +++ b/trunk/drivers/net/ethernet/sfc/ptp.c @@ -931,8 +931,7 @@ static int efx_ptp_probe_channel(struct efx_channel *channel) ptp->phc_clock_info.settime = efx_phc_settime; ptp->phc_clock_info.enable = efx_phc_enable; - ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, - &efx->pci_dev->dev); + ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info); if (!ptp->phc_clock) goto fail3; diff --git a/trunk/drivers/net/ethernet/sfc/siena_sriov.c b/trunk/drivers/net/ethernet/sfc/siena_sriov.c index a8f48a455849..d49b53dc2a50 100644 --- a/trunk/drivers/net/ethernet/sfc/siena_sriov.c +++ b/trunk/drivers/net/ethernet/sfc/siena_sriov.c @@ -1035,6 +1035,7 @@ efx_sriov_get_channel_name(struct efx_channel *channel, char *buf, size_t len) static const struct efx_channel_type efx_sriov_channel_type = { .handle_no_channel = efx_sriov_handle_no_channel, .pre_probe = efx_sriov_probe_channel, + .post_remove = efx_channel_dummy_op_void, .get_name = efx_sriov_get_channel_name, /* no copy operation; channel must not be reallocated */ .keep_eventq = true, diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3be88331d17a..c136162e6473 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1066,7 +1066,7 @@ static int stmmac_open(struct net_device *dev) } else priv->tm->enable = 1; #endif - clk_prepare_enable(priv->stmmac_clk); + clk_enable(priv->stmmac_clk); stmmac_check_ether_addr(priv); @@ -1188,7 +1188,7 @@ static int stmmac_open(struct net_device *dev) if (priv->phydev) phy_disconnect(priv->phydev); - clk_disable_unprepare(priv->stmmac_clk); + clk_disable(priv->stmmac_clk); return ret; } @@ -1246,7 +1246,7 @@ static int stmmac_release(struct net_device *dev) #ifdef CONFIG_STMMAC_DEBUG_FS stmmac_exit_fs(); #endif - clk_disable_unprepare(priv->stmmac_clk); + clk_disable(priv->stmmac_clk); return 0; } @@ -2178,7 +2178,7 @@ int stmmac_suspend(struct net_device *ndev) else { stmmac_set_mac(priv->ioaddr, false); /* Disable clock in case of PWM is off */ - clk_disable_unprepare(priv->stmmac_clk); + clk_disable(priv->stmmac_clk); } spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -2203,7 +2203,7 @@ int stmmac_resume(struct net_device *ndev) priv->hw->mac->pmt(priv->ioaddr, 0); else /* enable the clk prevously disabled */ - clk_prepare_enable(priv->stmmac_clk); + clk_enable(priv->stmmac_clk); netif_device_attach(ndev); diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c index 4ccd4e2977b7..2a0e1abde7e7 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c @@ -97,19 +97,19 @@ static struct clk *timer_clock; static void stmmac_tmu_start(unsigned int new_freq) { clk_set_rate(timer_clock, new_freq); - clk_prepare_enable(timer_clock); + clk_enable(timer_clock); } static void stmmac_tmu_stop(void) { - clk_disable_unprepare(timer_clock); + clk_disable(timer_clock); } int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm) { timer_clock = clk_get(NULL, TMU_CHANNEL); - if (IS_ERR(timer_clock)) + if (timer_clock == NULL) return -1; if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) { @@ -126,7 +126,7 @@ int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm) int stmmac_close_ext_timer(void) { - clk_disable_unprepare(timer_clock); + clk_disable(timer_clock); tmu2_unregister_user(); clk_put(timer_clock); return 0; diff --git a/trunk/drivers/net/ethernet/ti/cpsw.c b/trunk/drivers/net/ethernet/ti/cpsw.c index df55e2403746..0cbc0e59252c 100644 --- a/trunk/drivers/net/ethernet/ti/cpsw.c +++ b/trunk/drivers/net/ethernet/ti/cpsw.c @@ -386,11 +386,6 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave, mac_control |= BIT(7); /* GIGABITEN */ if (phy->duplex) mac_control |= BIT(0); /* FULLDUPLEXEN */ - - /* set speed_in input in case RMII mode is used in 100Mbps */ - if (phy->speed == 100) - mac_control |= BIT(15); - *link = true; } else { mac_control = 0; diff --git a/trunk/drivers/net/irda/sh_sir.c b/trunk/drivers/net/irda/sh_sir.c index 795109425568..256eddf1f75a 100644 --- a/trunk/drivers/net/irda/sh_sir.c +++ b/trunk/drivers/net/irda/sh_sir.c @@ -280,7 +280,7 @@ static int sh_sir_set_baudrate(struct sh_sir_self *self, u32 baudrate) } clk = clk_get(NULL, "irda_clk"); - if (IS_ERR(clk)) { + if (!clk) { dev_err(dev, "can not get irda_clk\n"); return -EIO; } diff --git a/trunk/drivers/net/loopback.c b/trunk/drivers/net/loopback.c index 81f8f9e31db5..4a075babe193 100644 --- a/trunk/drivers/net/loopback.c +++ b/trunk/drivers/net/loopback.c @@ -157,7 +157,7 @@ static const struct net_device_ops loopback_ops = { */ static void loopback_setup(struct net_device *dev) { - dev->mtu = 64 * 1024; + dev->mtu = (16 * 1024) + 20 + 20 + 12; dev->hard_header_len = ETH_HLEN; /* 14 */ dev->addr_len = ETH_ALEN; /* 6 */ dev->tx_queue_len = 0; diff --git a/trunk/drivers/net/macvlan.c b/trunk/drivers/net/macvlan.c index 68a43fe602e7..815dfcfbc7b9 100644 --- a/trunk/drivers/net/macvlan.c +++ b/trunk/drivers/net/macvlan.c @@ -546,7 +546,7 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev, return 0; } -static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], +static int macvlan_fdb_add(struct ndmsg *ndm, struct net_device *dev, const unsigned char *addr, u16 flags) diff --git a/trunk/drivers/net/phy/bcm87xx.c b/trunk/drivers/net/phy/bcm87xx.c index 799789518e87..2346b38b9837 100644 --- a/trunk/drivers/net/phy/bcm87xx.c +++ b/trunk/drivers/net/phy/bcm87xx.c @@ -229,5 +229,3 @@ static void __exit bcm87xx_exit(void) ARRAY_SIZE(bcm87xx_driver)); } module_exit(bcm87xx_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/phy/dp83640.c b/trunk/drivers/net/phy/dp83640.c index 24e05c43bff8..b0da0226661f 100644 --- a/trunk/drivers/net/phy/dp83640.c +++ b/trunk/drivers/net/phy/dp83640.c @@ -980,7 +980,7 @@ static int dp83640_probe(struct phy_device *phydev) if (choose_this_phy(clock, phydev)) { clock->chosen = dp83640; - clock->ptp_clock = ptp_clock_register(&clock->caps, &phydev->dev); + clock->ptp_clock = ptp_clock_register(&clock->caps); if (IS_ERR(clock->ptp_clock)) { err = PTR_ERR(clock->ptp_clock); goto no_register; diff --git a/trunk/drivers/net/phy/lxt.c b/trunk/drivers/net/phy/lxt.c index ec40ba882f61..6d1e3fcc43e2 100644 --- a/trunk/drivers/net/phy/lxt.c +++ b/trunk/drivers/net/phy/lxt.c @@ -122,123 +122,6 @@ static int lxt971_config_intr(struct phy_device *phydev) return err; } -/* - * A2 version of LXT973 chip has an ERRATA: it randomly return the contents - * of the previous even register when you read a odd register regularly - */ - -static int lxt973a2_update_link(struct phy_device *phydev) -{ - int status; - int control; - int retry = 8; /* we try 8 times */ - - /* Do a fake read */ - status = phy_read(phydev, MII_BMSR); - - if (status < 0) - return status; - - control = phy_read(phydev, MII_BMCR); - if (control < 0) - return control; - - do { - /* Read link and autonegotiation status */ - status = phy_read(phydev, MII_BMSR); - } while (status >= 0 && retry-- && status == control); - - if (status < 0) - return status; - - if ((status & BMSR_LSTATUS) == 0) - phydev->link = 0; - else - phydev->link = 1; - - return 0; -} - -int lxt973a2_read_status(struct phy_device *phydev) -{ - int adv; - int err; - int lpa; - int lpagb = 0; - - /* Update the link, but return if there was an error */ - err = lxt973a2_update_link(phydev); - if (err) - return err; - - if (AUTONEG_ENABLE == phydev->autoneg) { - int retry = 1; - - adv = phy_read(phydev, MII_ADVERTISE); - - if (adv < 0) - return adv; - - do { - lpa = phy_read(phydev, MII_LPA); - - if (lpa < 0) - return lpa; - - /* If both registers are equal, it is suspect but not - * impossible, hence a new try - */ - } while (lpa == adv && retry--); - - lpa &= adv; - - phydev->speed = SPEED_10; - phydev->duplex = DUPLEX_HALF; - phydev->pause = phydev->asym_pause = 0; - - if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { - phydev->speed = SPEED_1000; - - if (lpagb & LPA_1000FULL) - phydev->duplex = DUPLEX_FULL; - } else if (lpa & (LPA_100FULL | LPA_100HALF)) { - phydev->speed = SPEED_100; - - if (lpa & LPA_100FULL) - phydev->duplex = DUPLEX_FULL; - } else { - if (lpa & LPA_10FULL) - phydev->duplex = DUPLEX_FULL; - } - - if (phydev->duplex == DUPLEX_FULL) { - phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; - phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; - } - } else { - int bmcr = phy_read(phydev, MII_BMCR); - - if (bmcr < 0) - return bmcr; - - if (bmcr & BMCR_FULLDPLX) - phydev->duplex = DUPLEX_FULL; - else - phydev->duplex = DUPLEX_HALF; - - if (bmcr & BMCR_SPEED1000) - phydev->speed = SPEED_1000; - else if (bmcr & BMCR_SPEED100) - phydev->speed = SPEED_100; - else - phydev->speed = SPEED_10; - - phydev->pause = phydev->asym_pause = 0; - } - - return 0; -} - static int lxt973_probe(struct phy_device *phydev) { int val = phy_read(phydev, MII_LXT973_PCR); @@ -290,16 +173,6 @@ static struct phy_driver lxt97x_driver[] = { .ack_interrupt = lxt971_ack_interrupt, .config_intr = lxt971_config_intr, .driver = { .owner = THIS_MODULE,}, -}, { - .phy_id = 0x00137a10, - .name = "LXT973-A2", - .phy_id_mask = 0xffffffff, - .features = PHY_BASIC_FEATURES, - .flags = 0, - .probe = lxt973_probe, - .config_aneg = lxt973_config_aneg, - .read_status = lxt973a2_read_status, - .driver = { .owner = THIS_MODULE,}, }, { .phy_id = 0x00137a10, .name = "LXT973", diff --git a/trunk/drivers/net/phy/micrel.c b/trunk/drivers/net/phy/micrel.c index 2165d5fdb8c0..cf287e0eb408 100644 --- a/trunk/drivers/net/phy/micrel.c +++ b/trunk/drivers/net/phy/micrel.c @@ -21,12 +21,6 @@ #include #include -/* Operation Mode Strap Override */ -#define MII_KSZPHY_OMSO 0x16 -#define KSZPHY_OMSO_B_CAST_OFF (1 << 9) -#define KSZPHY_OMSO_RMII_OVERRIDE (1 << 1) -#define KSZPHY_OMSO_MII_OVERRIDE (1 << 0) - /* general Interrupt control/status reg in vendor specific block. */ #define MII_KSZPHY_INTCS 0x1B #define KSZPHY_INTCS_JABBER (1 << 15) @@ -107,13 +101,6 @@ static int kszphy_config_init(struct phy_device *phydev) return 0; } -static int ksz8021_config_init(struct phy_device *phydev) -{ - const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE; - phy_write(phydev, MII_KSZPHY_OMSO, val); - return 0; -} - static int ks8051_config_init(struct phy_device *phydev) { int regval; @@ -141,22 +128,9 @@ static struct phy_driver ksphy_driver[] = { .config_intr = ks8737_config_intr, .driver = { .owner = THIS_MODULE,}, }, { - .phy_id = PHY_ID_KSZ8021, - .phy_id_mask = 0x00ffffff, - .name = "Micrel KSZ8021", - .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | - SUPPORTED_Asym_Pause), - .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, - .config_init = ksz8021_config_init, - .config_aneg = genphy_config_aneg, - .read_status = genphy_read_status, - .ack_interrupt = kszphy_ack_interrupt, - .config_intr = kszphy_config_intr, - .driver = { .owner = THIS_MODULE,}, -}, { - .phy_id = PHY_ID_KSZ8041, + .phy_id = PHY_ID_KS8041, .phy_id_mask = 0x00fffff0, - .name = "Micrel KSZ8041", + .name = "Micrel KS8041", .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -167,9 +141,9 @@ static struct phy_driver ksphy_driver[] = { .config_intr = kszphy_config_intr, .driver = { .owner = THIS_MODULE,}, }, { - .phy_id = PHY_ID_KSZ8051, + .phy_id = PHY_ID_KS8051, .phy_id_mask = 0x00fffff0, - .name = "Micrel KSZ8051", + .name = "Micrel KS8051", .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -180,8 +154,8 @@ static struct phy_driver ksphy_driver[] = { .config_intr = kszphy_config_intr, .driver = { .owner = THIS_MODULE,}, }, { - .phy_id = PHY_ID_KSZ8001, - .name = "Micrel KSZ8001 or KS8721", + .phy_id = PHY_ID_KS8001, + .name = "Micrel KS8001 or KS8721", .phy_id_mask = 0x00ffffff, .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -227,11 +201,10 @@ MODULE_LICENSE("GPL"); static struct mdio_device_id __maybe_unused micrel_tbl[] = { { PHY_ID_KSZ9021, 0x000ffffe }, - { PHY_ID_KSZ8001, 0x00ffffff }, + { PHY_ID_KS8001, 0x00ffffff }, { PHY_ID_KS8737, 0x00fffff0 }, - { PHY_ID_KSZ8021, 0x00ffffff }, - { PHY_ID_KSZ8041, 0x00fffff0 }, - { PHY_ID_KSZ8051, 0x00fffff0 }, + { PHY_ID_KS8041, 0x00fffff0 }, + { PHY_ID_KS8051, 0x00fffff0 }, { } }; diff --git a/trunk/drivers/net/phy/smsc.c b/trunk/drivers/net/phy/smsc.c index 88e3991464e7..6d6192316b30 100644 --- a/trunk/drivers/net/phy/smsc.c +++ b/trunk/drivers/net/phy/smsc.c @@ -56,32 +56,6 @@ static int smsc_phy_config_init(struct phy_device *phydev) return smsc_phy_ack_interrupt (phydev); } -static int lan87xx_config_init(struct phy_device *phydev) -{ - /* - * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on - * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due - * to a bug on the chip. - * - * When the system is powered on with the network cable being - * disconnected all the way until after ifconfig ethX up is - * issued for the LAN port with this PHY, connecting the cable - * afterwards does not cause LINK change detection, while the - * expected behavior is the Link UP being detected. - */ - int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); - if (rc < 0) - return rc; - - rc &= ~MII_LAN83C185_EDPWRDOWN; - - rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc); - if (rc < 0) - return rc; - - return smsc_phy_ack_interrupt(phydev); -} - static int lan911x_config_init(struct phy_device *phydev) { return smsc_phy_ack_interrupt(phydev); @@ -188,7 +162,7 @@ static struct phy_driver smsc_phy_driver[] = { /* basic functions */ .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .config_init = lan87xx_config_init, + .config_init = smsc_phy_config_init, /* IRQ related */ .ack_interrupt = smsc_phy_ack_interrupt, diff --git a/trunk/drivers/net/ppp/pppoe.c b/trunk/drivers/net/ppp/pppoe.c index 20f31d0d1536..cbf7047decc0 100644 --- a/trunk/drivers/net/ppp/pppoe.c +++ b/trunk/drivers/net/ppp/pppoe.c @@ -570,7 +570,7 @@ static int pppoe_release(struct socket *sock) po = pppox_sk(sk); - if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { + if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { dev_put(po->pppoe_dev); po->pppoe_dev = NULL; } diff --git a/trunk/drivers/net/team/team.c b/trunk/drivers/net/team/team.c index 5c7547c4f802..9ce0c51a04d5 100644 --- a/trunk/drivers/net/team/team.c +++ b/trunk/drivers/net/team/team.c @@ -967,6 +967,7 @@ static struct netpoll_info *team_netpoll_info(struct team *team) #endif static void __team_port_change_port_added(struct team_port *port, bool linkup); + static int team_dev_type_check_change(struct net_device *dev, struct net_device *port_dev); @@ -1889,8 +1890,8 @@ static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &team_nl_family, 0, TEAM_CMD_NOOP); - if (!hdr) { - err = -EMSGSIZE; + if (IS_ERR(hdr)) { + err = PTR_ERR(hdr); goto err_msg_put; } @@ -2090,8 +2091,8 @@ static int team_nl_send_options_get(struct team *team, u32 portid, u32 seq, hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI, TEAM_CMD_OPTIONS_GET); - if (!hdr) - return -EMSGSIZE; + if (IS_ERR(hdr)) + return PTR_ERR(hdr); if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; @@ -2316,8 +2317,8 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags, TEAM_CMD_PORT_LIST_GET); - if (!hdr) - return -EMSGSIZE; + if (IS_ERR(hdr)) + return PTR_ERR(hdr); if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; diff --git a/trunk/drivers/net/usb/asix_devices.c b/trunk/drivers/net/usb/asix_devices.c index 33ab824773c5..8d5fdf103bcd 100644 --- a/trunk/drivers/net/usb/asix_devices.c +++ b/trunk/drivers/net/usb/asix_devices.c @@ -933,10 +933,6 @@ static const struct usb_device_id products [] = { // JVC MP-PRX1 Port Replicator USB_DEVICE (0x04f1, 0x3008), .driver_info = (unsigned long) &ax8817x_info, -}, { - // Lenovo U2L100P 10/100 - USB_DEVICE (0x17ef, 0x7203), - .driver_info = (unsigned long) &ax88772_info, }, { // ASIX AX88772B 10/100 USB_DEVICE (0x0b95, 0x772b), @@ -969,10 +965,6 @@ static const struct usb_device_id products [] = { // DLink DUB-E100 H/W Ver B1 Alternate USB_DEVICE (0x2001, 0x3c05), .driver_info = (unsigned long) &ax88772_info, -}, { - // DLink DUB-E100 H/W Ver C1 - USB_DEVICE (0x2001, 0x1a02), - .driver_info = (unsigned long) &ax88772_info, }, { // Linksys USB1000 USB_DEVICE (0x1737, 0x0039), diff --git a/trunk/drivers/net/usb/qmi_wwan.c b/trunk/drivers/net/usb/qmi_wwan.c index 6883c371c59f..ca253206b73f 100644 --- a/trunk/drivers/net/usb/qmi_wwan.c +++ b/trunk/drivers/net/usb/qmi_wwan.c @@ -353,7 +353,7 @@ static const struct usb_device_id products[] = { }, /* 2. Combined interface devices matching on class+protocol */ - { /* Huawei E367 and possibly others in "Windows mode" */ + { /* Huawei E367 and possibly others in "Windows mode" */ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 7), .driver_info = (unsigned long)&qmi_wwan_info, }, @@ -361,7 +361,7 @@ static const struct usb_device_id products[] = { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), .driver_info = (unsigned long)&qmi_wwan_info, }, - { /* Pantech UML290, P4200 and more */ + { /* Pantech UML290, P4200 and more */ USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), .driver_info = (unsigned long)&qmi_wwan_info, }, diff --git a/trunk/drivers/net/usb/smsc75xx.c b/trunk/drivers/net/usb/smsc75xx.c index b77ae76f4aa8..f5ab6e613ec8 100644 --- a/trunk/drivers/net/usb/smsc75xx.c +++ b/trunk/drivers/net/usb/smsc75xx.c @@ -52,7 +52,6 @@ #define USB_PRODUCT_ID_LAN7500 (0x7500) #define USB_PRODUCT_ID_LAN7505 (0x7505) #define RXW_PADDING 2 -#define SUPPORTED_WAKE (WAKE_MAGIC) #define check_warn(ret, fmt, args...) \ ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); }) @@ -66,7 +65,6 @@ struct smsc75xx_priv { struct usbnet *dev; u32 rfe_ctl; - u32 wolopts; u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN]; struct mutex dataport_mutex; spinlock_t rfe_ctl_lock; @@ -137,30 +135,6 @@ static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index, return ret; } -static int smsc75xx_set_feature(struct usbnet *dev, u32 feature) -{ - if (WARN_ON_ONCE(!dev)) - return -EINVAL; - - cpu_to_le32s(&feature); - - return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0, - USB_CTRL_SET_TIMEOUT); -} - -static int smsc75xx_clear_feature(struct usbnet *dev, u32 feature) -{ - if (WARN_ON_ONCE(!dev)) - return -EINVAL; - - cpu_to_le32s(&feature); - - return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0, - USB_CTRL_SET_TIMEOUT); -} - /* Loop until the read is completed with timeout * called with phy_mutex held */ static int smsc75xx_phy_wait_not_busy(struct usbnet *dev) @@ -604,26 +578,6 @@ static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev, return smsc75xx_write_eeprom(dev, ee->offset, ee->len, data); } -static void smsc75xx_ethtool_get_wol(struct net_device *net, - struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); - - wolinfo->supported = SUPPORTED_WAKE; - wolinfo->wolopts = pdata->wolopts; -} - -static int smsc75xx_ethtool_set_wol(struct net_device *net, - struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); - - pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE; - return 0; -} - static const struct ethtool_ops smsc75xx_ethtool_ops = { .get_link = usbnet_get_link, .nway_reset = usbnet_nway_reset, @@ -635,8 +589,6 @@ static const struct ethtool_ops smsc75xx_ethtool_ops = { .get_eeprom_len = smsc75xx_ethtool_get_eeprom_len, .get_eeprom = smsc75xx_ethtool_get_eeprom, .set_eeprom = smsc75xx_ethtool_set_eeprom, - .get_wol = smsc75xx_ethtool_get_wol, - .set_wol = smsc75xx_ethtool_set_wol, }; static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) @@ -804,26 +756,6 @@ static int smsc75xx_set_features(struct net_device *netdev, return 0; } -static int smsc75xx_wait_ready(struct usbnet *dev) -{ - int timeout = 0; - - do { - u32 buf; - int ret = smsc75xx_read_reg(dev, PMT_CTL, &buf); - check_warn_return(ret, "Failed to read PMT_CTL: %d", ret); - - if (buf & PMT_CTL_DEV_RDY) - return 0; - - msleep(10); - timeout++; - } while (timeout < 100); - - netdev_warn(dev->net, "timeout waiting for device ready"); - return -EIO; -} - static int smsc75xx_reset(struct usbnet *dev) { struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); @@ -832,9 +764,6 @@ static int smsc75xx_reset(struct usbnet *dev) netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset"); - ret = smsc75xx_wait_ready(dev); - check_warn_return(ret, "device not ready in smsc75xx_reset"); - ret = smsc75xx_read_reg(dev, HW_CFG, &buf); check_warn_return(ret, "Failed to read HW_CFG: %d", ret); @@ -1154,169 +1083,6 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf) } } -static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usbnet *dev = usb_get_intfdata(intf); - struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); - int ret; - u32 val; - - ret = usbnet_suspend(intf, message); - check_warn_return(ret, "usbnet_suspend error"); - - /* if no wol options set, enter lowest power SUSPEND2 mode */ - if (!(pdata->wolopts & SUPPORTED_WAKE)) { - netdev_info(dev->net, "entering SUSPEND2 mode"); - - /* disable energy detect (link up) & wake up events */ - ret = smsc75xx_read_reg(dev, WUCSR, &val); - check_warn_return(ret, "Error reading WUCSR"); - - val &= ~(WUCSR_MPEN | WUCSR_WUEN); - - ret = smsc75xx_write_reg(dev, WUCSR, val); - check_warn_return(ret, "Error writing WUCSR"); - - ret = smsc75xx_read_reg(dev, PMT_CTL, &val); - check_warn_return(ret, "Error reading PMT_CTL"); - - val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN); - - ret = smsc75xx_write_reg(dev, PMT_CTL, val); - check_warn_return(ret, "Error writing PMT_CTL"); - - /* enter suspend2 mode */ - ret = smsc75xx_read_reg(dev, PMT_CTL, &val); - check_warn_return(ret, "Error reading PMT_CTL"); - - val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST); - val |= PMT_CTL_SUS_MODE_2; - - ret = smsc75xx_write_reg(dev, PMT_CTL, val); - check_warn_return(ret, "Error writing PMT_CTL"); - - return 0; - } - - if (pdata->wolopts & WAKE_MAGIC) { - /* clear any pending magic packet status */ - ret = smsc75xx_read_reg(dev, WUCSR, &val); - check_warn_return(ret, "Error reading WUCSR"); - - val |= WUCSR_MPR; - - ret = smsc75xx_write_reg(dev, WUCSR, val); - check_warn_return(ret, "Error writing WUCSR"); - } - - /* enable/disable magic packup wake */ - ret = smsc75xx_read_reg(dev, WUCSR, &val); - check_warn_return(ret, "Error reading WUCSR"); - - if (pdata->wolopts & WAKE_MAGIC) { - netdev_info(dev->net, "enabling magic packet wakeup"); - val |= WUCSR_MPEN; - } else { - netdev_info(dev->net, "disabling magic packet wakeup"); - val &= ~WUCSR_MPEN; - } - - ret = smsc75xx_write_reg(dev, WUCSR, val); - check_warn_return(ret, "Error writing WUCSR"); - - /* enable wol wakeup source */ - ret = smsc75xx_read_reg(dev, PMT_CTL, &val); - check_warn_return(ret, "Error reading PMT_CTL"); - - val |= PMT_CTL_WOL_EN; - - ret = smsc75xx_write_reg(dev, PMT_CTL, val); - check_warn_return(ret, "Error writing PMT_CTL"); - - /* enable receiver */ - ret = smsc75xx_read_reg(dev, MAC_RX, &val); - check_warn_return(ret, "Failed to read MAC_RX: %d", ret); - - val |= MAC_RX_RXEN; - - ret = smsc75xx_write_reg(dev, MAC_RX, val); - check_warn_return(ret, "Failed to write MAC_RX: %d", ret); - - /* some wol options are enabled, so enter SUSPEND0 */ - netdev_info(dev->net, "entering SUSPEND0 mode"); - - ret = smsc75xx_read_reg(dev, PMT_CTL, &val); - check_warn_return(ret, "Error reading PMT_CTL"); - - val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST)); - val |= PMT_CTL_SUS_MODE_0; - - ret = smsc75xx_write_reg(dev, PMT_CTL, val); - check_warn_return(ret, "Error writing PMT_CTL"); - - /* clear wol status */ - val &= ~PMT_CTL_WUPS; - val |= PMT_CTL_WUPS_WOL; - ret = smsc75xx_write_reg(dev, PMT_CTL, val); - check_warn_return(ret, "Error writing PMT_CTL"); - - /* read back PMT_CTL */ - ret = smsc75xx_read_reg(dev, PMT_CTL, &val); - check_warn_return(ret, "Error reading PMT_CTL"); - - smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP); - - return 0; -} - -static int smsc75xx_resume(struct usb_interface *intf) -{ - struct usbnet *dev = usb_get_intfdata(intf); - struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); - int ret; - u32 val; - - if (pdata->wolopts & WAKE_MAGIC) { - netdev_info(dev->net, "resuming from SUSPEND0"); - - smsc75xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP); - - /* Disable magic packup wake */ - ret = smsc75xx_read_reg(dev, WUCSR, &val); - check_warn_return(ret, "Error reading WUCSR"); - - val &= ~WUCSR_MPEN; - - ret = smsc75xx_write_reg(dev, WUCSR, val); - check_warn_return(ret, "Error writing WUCSR"); - - /* clear wake-up status */ - ret = smsc75xx_read_reg(dev, PMT_CTL, &val); - check_warn_return(ret, "Error reading PMT_CTL"); - - val &= ~PMT_CTL_WOL_EN; - val |= PMT_CTL_WUPS; - - ret = smsc75xx_write_reg(dev, PMT_CTL, val); - check_warn_return(ret, "Error writing PMT_CTL"); - } else { - netdev_info(dev->net, "resuming from SUSPEND2"); - - ret = smsc75xx_read_reg(dev, PMT_CTL, &val); - check_warn_return(ret, "Error reading PMT_CTL"); - - val |= PMT_CTL_PHY_PWRUP; - - ret = smsc75xx_write_reg(dev, PMT_CTL, val); - check_warn_return(ret, "Error writing PMT_CTL"); - } - - ret = smsc75xx_wait_ready(dev); - check_warn_return(ret, "device not ready in smsc75xx_resume"); - - return usbnet_resume(intf); -} - static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb, u32 rx_cmd_a, u32 rx_cmd_b) { @@ -1485,9 +1251,8 @@ static struct usb_driver smsc75xx_driver = { .name = SMSC_CHIPNAME, .id_table = products, .probe = usbnet_probe, - .suspend = smsc75xx_suspend, - .resume = smsc75xx_resume, - .reset_resume = smsc75xx_resume, + .suspend = usbnet_suspend, + .resume = usbnet_resume, .disconnect = usbnet_disconnect, .disable_hub_initiated_lpm = 1, }; diff --git a/trunk/drivers/net/usb/smsc95xx.c b/trunk/drivers/net/usb/smsc95xx.c index 7479a5761d0d..d45e539a84b7 100644 --- a/trunk/drivers/net/usb/smsc95xx.c +++ b/trunk/drivers/net/usb/smsc95xx.c @@ -46,22 +46,11 @@ #define SMSC95XX_INTERNAL_PHY_ID (1) #define SMSC95XX_TX_OVERHEAD (8) #define SMSC95XX_TX_OVERHEAD_CSUM (12) -#define SUPPORTED_WAKE (WAKE_MAGIC) - -#define check_warn(ret, fmt, args...) \ - ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); }) - -#define check_warn_return(ret, fmt, args...) \ - ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); return ret; } }) - -#define check_warn_goto_done(ret, fmt, args...) \ - ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); goto done; } }) struct smsc95xx_priv { u32 mac_cr; u32 hash_hi; u32 hash_lo; - u32 wolopts; spinlock_t mac_cr_lock; }; @@ -74,8 +63,7 @@ static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); -static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index, - u32 *data) +static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data) { u32 *buf = kmalloc(4, GFP_KERNEL); int ret; @@ -100,8 +88,7 @@ static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index, return ret; } -static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index, - u32 data) +static int smsc95xx_write_reg(struct usbnet *dev, u32 index, u32 data) { u32 *buf = kmalloc(4, GFP_KERNEL); int ret; @@ -127,41 +114,15 @@ static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index, return ret; } -static int smsc95xx_set_feature(struct usbnet *dev, u32 feature) -{ - if (WARN_ON_ONCE(!dev)) - return -EINVAL; - - cpu_to_le32s(&feature); - - return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0, - USB_CTRL_SET_TIMEOUT); -} - -static int smsc95xx_clear_feature(struct usbnet *dev, u32 feature) -{ - if (WARN_ON_ONCE(!dev)) - return -EINVAL; - - cpu_to_le32s(&feature); - - return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0, - USB_CTRL_SET_TIMEOUT); -} - /* Loop until the read is completed with timeout * called with phy_mutex held */ -static int __must_check smsc95xx_phy_wait_not_busy(struct usbnet *dev) +static int smsc95xx_phy_wait_not_busy(struct usbnet *dev) { unsigned long start_time = jiffies; u32 val; - int ret; do { - ret = smsc95xx_read_reg(dev, MII_ADDR, &val); - check_warn_return(ret, "Error reading MII_ACCESS"); + smsc95xx_read_reg(dev, MII_ADDR, &val); if (!(val & MII_BUSY_)) return 0; } while (!time_after(jiffies, start_time + HZ)); @@ -173,32 +134,33 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx) { struct usbnet *dev = netdev_priv(netdev); u32 val, addr; - int ret; mutex_lock(&dev->phy_mutex); /* confirm MII not busy */ - ret = smsc95xx_phy_wait_not_busy(dev); - check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_read"); + if (smsc95xx_phy_wait_not_busy(dev)) { + netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_read\n"); + mutex_unlock(&dev->phy_mutex); + return -EIO; + } /* set the address, index & direction (read from PHY) */ phy_id &= dev->mii.phy_id_mask; idx &= dev->mii.reg_num_mask; addr = (phy_id << 11) | (idx << 6) | MII_READ_; - ret = smsc95xx_write_reg(dev, MII_ADDR, addr); - check_warn_goto_done(ret, "Error writing MII_ADDR"); - - ret = smsc95xx_phy_wait_not_busy(dev); - check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx); + smsc95xx_write_reg(dev, MII_ADDR, addr); - ret = smsc95xx_read_reg(dev, MII_DATA, &val); - check_warn_goto_done(ret, "Error reading MII_DATA"); + if (smsc95xx_phy_wait_not_busy(dev)) { + netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx); + mutex_unlock(&dev->phy_mutex); + return -EIO; + } - ret = (u16)(val & 0xFFFF); + smsc95xx_read_reg(dev, MII_DATA, &val); -done: mutex_unlock(&dev->phy_mutex); - return ret; + + return (u16)(val & 0xFFFF); } static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx, @@ -206,41 +168,38 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx, { struct usbnet *dev = netdev_priv(netdev); u32 val, addr; - int ret; mutex_lock(&dev->phy_mutex); /* confirm MII not busy */ - ret = smsc95xx_phy_wait_not_busy(dev); - check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_write"); + if (smsc95xx_phy_wait_not_busy(dev)) { + netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_write\n"); + mutex_unlock(&dev->phy_mutex); + return; + } val = regval; - ret = smsc95xx_write_reg(dev, MII_DATA, val); - check_warn_goto_done(ret, "Error writing MII_DATA"); + smsc95xx_write_reg(dev, MII_DATA, val); /* set the address, index & direction (write to PHY) */ phy_id &= dev->mii.phy_id_mask; idx &= dev->mii.reg_num_mask; addr = (phy_id << 11) | (idx << 6) | MII_WRITE_; - ret = smsc95xx_write_reg(dev, MII_ADDR, addr); - check_warn_goto_done(ret, "Error writing MII_ADDR"); + smsc95xx_write_reg(dev, MII_ADDR, addr); - ret = smsc95xx_phy_wait_not_busy(dev); - check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx); + if (smsc95xx_phy_wait_not_busy(dev)) + netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx); -done: mutex_unlock(&dev->phy_mutex); } -static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev) +static int smsc95xx_wait_eeprom(struct usbnet *dev) { unsigned long start_time = jiffies; u32 val; - int ret; do { - ret = smsc95xx_read_reg(dev, E2P_CMD, &val); - check_warn_return(ret, "Error reading E2P_CMD"); + smsc95xx_read_reg(dev, E2P_CMD, &val); if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_)) break; udelay(40); @@ -254,15 +213,13 @@ static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev) return 0; } -static int __must_check smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev) +static int smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev) { unsigned long start_time = jiffies; u32 val; - int ret; do { - ret = smsc95xx_read_reg(dev, E2P_CMD, &val); - check_warn_return(ret, "Error reading E2P_CMD"); + smsc95xx_read_reg(dev, E2P_CMD, &val); if (!(val & E2P_CMD_BUSY_)) return 0; @@ -289,15 +246,13 @@ static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length, for (i = 0; i < length; i++) { val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_); - ret = smsc95xx_write_reg(dev, E2P_CMD, val); - check_warn_return(ret, "Error writing E2P_CMD"); + smsc95xx_write_reg(dev, E2P_CMD, val); ret = smsc95xx_wait_eeprom(dev); if (ret < 0) return ret; - ret = smsc95xx_read_reg(dev, E2P_DATA, &val); - check_warn_return(ret, "Error reading E2P_DATA"); + smsc95xx_read_reg(dev, E2P_DATA, &val); data[i] = val & 0xFF; offset++; @@ -321,8 +276,7 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length, /* Issue write/erase enable command */ val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_; - ret = smsc95xx_write_reg(dev, E2P_CMD, val); - check_warn_return(ret, "Error writing E2P_DATA"); + smsc95xx_write_reg(dev, E2P_CMD, val); ret = smsc95xx_wait_eeprom(dev); if (ret < 0) @@ -332,13 +286,11 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length, /* Fill data register */ val = data[i]; - ret = smsc95xx_write_reg(dev, E2P_DATA, val); - check_warn_return(ret, "Error writing E2P_DATA"); + smsc95xx_write_reg(dev, E2P_DATA, val); /* Send "write" command */ val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_); - ret = smsc95xx_write_reg(dev, E2P_CMD, val); - check_warn_return(ret, "Error writing E2P_CMD"); + smsc95xx_write_reg(dev, E2P_CMD, val); ret = smsc95xx_wait_eeprom(dev); if (ret < 0) @@ -356,14 +308,14 @@ static void smsc95xx_async_cmd_callback(struct urb *urb) struct usbnet *dev = usb_context->dev; int status = urb->status; - check_warn(status, "async callback failed with %d\n", status); + if (status < 0) + netdev_warn(dev->net, "async callback failed with %d\n", status); kfree(usb_context); usb_free_urb(urb); } -static int __must_check smsc95xx_write_reg_async(struct usbnet *dev, u16 index, - u32 *data) +static int smsc95xx_write_reg_async(struct usbnet *dev, u16 index, u32 *data) { struct usb_context *usb_context; int status; @@ -419,7 +371,6 @@ static void smsc95xx_set_multicast(struct net_device *netdev) struct usbnet *dev = netdev_priv(netdev); struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); unsigned long flags; - int ret; pdata->hash_hi = 0; pdata->hash_lo = 0; @@ -460,23 +411,21 @@ static void smsc95xx_set_multicast(struct net_device *netdev) spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); /* Initiate async writes, as we can't wait for completion here */ - ret = smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi); - check_warn(ret, "failed to initiate async write to HASHH"); - - ret = smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo); - check_warn(ret, "failed to initiate async write to HASHL"); - - ret = smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr); - check_warn(ret, "failed to initiate async write to MAC_CR"); + smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi); + smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo); + smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr); } -static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, - u16 lcladv, u16 rmtadv) +static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, + u16 lcladv, u16 rmtadv) { u32 flow, afc_cfg = 0; int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg); - check_warn_return(ret, "Error reading AFC_CFG"); + if (ret < 0) { + netdev_warn(dev->net, "error reading AFC_CFG\n"); + return; + } if (duplex == DUPLEX_FULL) { u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv); @@ -500,13 +449,8 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, afc_cfg |= 0xF; } - ret = smsc95xx_write_reg(dev, FLOW, flow); - check_warn_return(ret, "Error writing FLOW"); - - ret = smsc95xx_write_reg(dev, AFC_CFG, afc_cfg); - check_warn_return(ret, "Error writing AFC_CFG"); - - return 0; + smsc95xx_write_reg(dev, FLOW, flow); + smsc95xx_write_reg(dev, AFC_CFG, afc_cfg); } static int smsc95xx_link_reset(struct usbnet *dev) @@ -516,14 +460,12 @@ static int smsc95xx_link_reset(struct usbnet *dev) struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; unsigned long flags; u16 lcladv, rmtadv; - int ret; + u32 intdata; /* clear interrupt status */ - ret = smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC); - check_warn_return(ret, "Error reading PHY_INT_SRC"); - - ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_); - check_warn_return(ret, "Error writing INT_STS"); + smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC); + intdata = 0xFFFFFFFF; + smsc95xx_write_reg(dev, INT_STS, intdata); mii_check_media(mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); @@ -544,11 +486,9 @@ static int smsc95xx_link_reset(struct usbnet *dev) } spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); - ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); - check_warn_return(ret, "Error writing MAC_CR"); + smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); - ret = smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv); - check_warn_return(ret, "Error updating PHY flow control"); + smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv); return 0; } @@ -584,7 +524,10 @@ static int smsc95xx_set_features(struct net_device *netdev, int ret; ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); - check_warn_return(ret, "Failed to read COE_CR: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read COE_CR: %d\n", ret); + return ret; + } if (features & NETIF_F_HW_CSUM) read_buf |= Tx_COE_EN_; @@ -597,7 +540,10 @@ static int smsc95xx_set_features(struct net_device *netdev, read_buf &= ~Rx_COE_EN_; ret = smsc95xx_write_reg(dev, COE_CR, read_buf); - check_warn_return(ret, "Failed to write COE_CR: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write COE_CR: %d\n", ret); + return ret; + } netif_dbg(dev, hw, dev->net, "COE_CR = 0x%08x\n", read_buf); return 0; @@ -662,26 +608,6 @@ smsc95xx_ethtool_getregs(struct net_device *netdev, struct ethtool_regs *regs, } } -static void smsc95xx_ethtool_get_wol(struct net_device *net, - struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - - wolinfo->supported = SUPPORTED_WAKE; - wolinfo->wolopts = pdata->wolopts; -} - -static int smsc95xx_ethtool_set_wol(struct net_device *net, - struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - - pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE; - return 0; -} - static const struct ethtool_ops smsc95xx_ethtool_ops = { .get_link = usbnet_get_link, .nway_reset = usbnet_nway_reset, @@ -695,8 +621,6 @@ static const struct ethtool_ops smsc95xx_ethtool_ops = { .set_eeprom = smsc95xx_ethtool_set_eeprom, .get_regs_len = smsc95xx_ethtool_getregslen, .get_regs = smsc95xx_ethtool_getregs, - .get_wol = smsc95xx_ethtool_get_wol, - .set_wol = smsc95xx_ethtool_set_wol, }; static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) @@ -734,56 +658,55 @@ static int smsc95xx_set_mac_address(struct usbnet *dev) int ret; ret = smsc95xx_write_reg(dev, ADDRL, addr_lo); - check_warn_return(ret, "Failed to write ADDRL: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write ADDRL: %d\n", ret); + return ret; + } ret = smsc95xx_write_reg(dev, ADDRH, addr_hi); - check_warn_return(ret, "Failed to write ADDRH: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write ADDRH: %d\n", ret); + return ret; + } return 0; } /* starts the TX path */ -static int smsc95xx_start_tx_path(struct usbnet *dev) +static void smsc95xx_start_tx_path(struct usbnet *dev) { struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); unsigned long flags; - int ret; + u32 reg_val; /* Enable Tx at MAC */ spin_lock_irqsave(&pdata->mac_cr_lock, flags); pdata->mac_cr |= MAC_CR_TXEN_; spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); - ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); - check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret); + smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); /* Enable Tx at SCSRs */ - ret = smsc95xx_write_reg(dev, TX_CFG, TX_CFG_ON_); - check_warn_return(ret, "Failed to write TX_CFG: %d\n", ret); - - return 0; + reg_val = TX_CFG_ON_; + smsc95xx_write_reg(dev, TX_CFG, reg_val); } /* Starts the Receive path */ -static int smsc95xx_start_rx_path(struct usbnet *dev) +static void smsc95xx_start_rx_path(struct usbnet *dev) { struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); unsigned long flags; - int ret; spin_lock_irqsave(&pdata->mac_cr_lock, flags); pdata->mac_cr |= MAC_CR_RXEN_; spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); - ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); - check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret); - - return 0; + smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); } static int smsc95xx_phy_initialize(struct usbnet *dev) { - int bmcr, ret, timeout = 0; + int bmcr, timeout = 0; /* Initialize MII structure */ dev->mii.dev = dev->net; @@ -812,8 +735,7 @@ static int smsc95xx_phy_initialize(struct usbnet *dev) ADVERTISE_PAUSE_ASYM); /* read to clear */ - ret = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC); - check_warn_return(ret, "Failed to read PHY_INT_SRC during init"); + smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC); smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK, PHY_INT_MASK_DEFAULT_); @@ -831,14 +753,22 @@ static int smsc95xx_reset(struct usbnet *dev) netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n"); - ret = smsc95xx_write_reg(dev, HW_CFG, HW_CFG_LRST_); - check_warn_return(ret, "Failed to write HW_CFG_LRST_ bit in HW_CFG\n"); + write_buf = HW_CFG_LRST_; + ret = smsc95xx_write_reg(dev, HW_CFG, write_buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = %d\n", + ret); + return ret; + } timeout = 0; do { - msleep(10); ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); + return ret; + } + msleep(10); timeout++; } while ((read_buf & HW_CFG_LRST_) && (timeout < 100)); @@ -847,14 +777,21 @@ static int smsc95xx_reset(struct usbnet *dev) return ret; } - ret = smsc95xx_write_reg(dev, PM_CTRL, PM_CTL_PHY_RST_); - check_warn_return(ret, "Failed to write PM_CTRL: %d\n", ret); + write_buf = PM_CTL_PHY_RST_; + ret = smsc95xx_write_reg(dev, PM_CTRL, write_buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write PM_CTRL: %d\n", ret); + return ret; + } timeout = 0; do { - msleep(10); ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf); - check_warn_return(ret, "Failed to read PM_CTRL: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read PM_CTRL: %d\n", ret); + return ret; + } + msleep(10); timeout++; } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100)); @@ -871,7 +808,10 @@ static int smsc95xx_reset(struct usbnet *dev) "MAC Address: %pM\n", dev->net->dev_addr); ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); + return ret; + } netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n", read_buf); @@ -879,10 +819,17 @@ static int smsc95xx_reset(struct usbnet *dev) read_buf |= HW_CFG_BIR_; ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); - check_warn_return(ret, "Failed to write HW_CFG_BIR_ bit in HW_CFG\n"); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write HW_CFG_BIR_ bit in HW_CFG register, ret = %d\n", + ret); + return ret; + } ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); + return ret; + } netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n", read_buf); @@ -902,28 +849,41 @@ static int smsc95xx_reset(struct usbnet *dev) "rx_urb_size=%ld\n", (ulong)dev->rx_urb_size); ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap); - check_warn_return(ret, "Failed to write BURST_CAP: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret); + return ret; + } ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf); - check_warn_return(ret, "Failed to read BURST_CAP: %d\n", ret); - + if (ret < 0) { + netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret); + return ret; + } netif_dbg(dev, ifup, dev->net, "Read Value from BURST_CAP after writing: 0x%08x\n", read_buf); - ret = smsc95xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY); - check_warn_return(ret, "Failed to write BULK_IN_DLY: %d\n", ret); + read_buf = DEFAULT_BULK_IN_DELAY; + ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf); + if (ret < 0) { + netdev_warn(dev->net, "ret = %d\n", ret); + return ret; + } ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf); - check_warn_return(ret, "Failed to read BULK_IN_DLY: %d\n", ret); - + if (ret < 0) { + netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret); + return ret; + } netif_dbg(dev, ifup, dev->net, "Read Value from BULK_IN_DLY after writing: 0x%08x\n", read_buf); ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret); - + if (ret < 0) { + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); + return ret; + } netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG: 0x%08x\n", read_buf); @@ -936,66 +896,101 @@ static int smsc95xx_reset(struct usbnet *dev) read_buf |= NET_IP_ALIGN << 9; ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); - check_warn_return(ret, "Failed to write HW_CFG: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write HW_CFG register, ret=%d\n", + ret); + return ret; + } ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret); - + if (ret < 0) { + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); + return ret; + } netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after writing: 0x%08x\n", read_buf); - ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_); - check_warn_return(ret, "Failed to write INT_STS: %d\n", ret); + write_buf = 0xFFFFFFFF; + ret = smsc95xx_write_reg(dev, INT_STS, write_buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write INT_STS register, ret=%d\n", + ret); + return ret; + } ret = smsc95xx_read_reg(dev, ID_REV, &read_buf); - check_warn_return(ret, "Failed to read ID_REV: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret); + return ret; + } netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf); /* Configure GPIO pins as LED outputs */ write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED | LED_GPIO_CFG_FDX_LED; ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf); - check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write LED_GPIO_CFG register, ret=%d\n", + ret); + return ret; + } /* Init Tx */ - ret = smsc95xx_write_reg(dev, FLOW, 0); - check_warn_return(ret, "Failed to write FLOW: %d\n", ret); + write_buf = 0; + ret = smsc95xx_write_reg(dev, FLOW, write_buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret); + return ret; + } - ret = smsc95xx_write_reg(dev, AFC_CFG, AFC_CFG_DEFAULT); - check_warn_return(ret, "Failed to write AFC_CFG: %d\n", ret); + read_buf = AFC_CFG_DEFAULT; + ret = smsc95xx_write_reg(dev, AFC_CFG, read_buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write AFC_CFG: %d\n", ret); + return ret; + } /* Don't need mac_cr_lock during initialisation */ ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr); - check_warn_return(ret, "Failed to read MAC_CR: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret); + return ret; + } /* Init Rx */ /* Set Vlan */ - ret = smsc95xx_write_reg(dev, VLAN1, (u32)ETH_P_8021Q); - check_warn_return(ret, "Failed to write VLAN1: %d\n", ret); + write_buf = (u32)ETH_P_8021Q; + ret = smsc95xx_write_reg(dev, VLAN1, write_buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write VAN1: %d\n", ret); + return ret; + } /* Enable or disable checksum offload engines */ - ret = smsc95xx_set_features(dev->net, dev->net->features); - check_warn_return(ret, "Failed to set checksum offload features"); + smsc95xx_set_features(dev->net, dev->net->features); smsc95xx_set_multicast(dev->net); - ret = smsc95xx_phy_initialize(dev); - check_warn_return(ret, "Failed to init PHY"); + if (smsc95xx_phy_initialize(dev) < 0) + return -EIO; ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf); - check_warn_return(ret, "Failed to read INT_EP_CTL: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret); + return ret; + } /* enable PHY interrupts */ read_buf |= INT_EP_CTL_PHY_INT_; ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf); - check_warn_return(ret, "Failed to write INT_EP_CTL: %d\n", ret); - - ret = smsc95xx_start_tx_path(dev); - check_warn_return(ret, "Failed to start TX path"); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret); + return ret; + } - ret = smsc95xx_start_rx_path(dev); - check_warn_return(ret, "Failed to start RX path"); + smsc95xx_start_tx_path(dev); + smsc95xx_start_rx_path(dev); netif_dbg(dev, ifup, dev->net, "smsc95xx_reset, return 0\n"); return 0; @@ -1022,7 +1017,10 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n"); ret = usbnet_get_endpoints(dev, intf); - check_warn_return(ret, "usbnet_get_endpoints failed: %d\n", ret); + if (ret < 0) { + netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret); + return ret; + } dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv), GFP_KERNEL); @@ -1066,153 +1064,6 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) } } -static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usbnet *dev = usb_get_intfdata(intf); - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - int ret; - u32 val; - - ret = usbnet_suspend(intf, message); - check_warn_return(ret, "usbnet_suspend error"); - - /* if no wol options set, enter lowest power SUSPEND2 mode */ - if (!(pdata->wolopts & SUPPORTED_WAKE)) { - netdev_info(dev->net, "entering SUSPEND2 mode"); - - /* disable energy detect (link up) & wake up events */ - ret = smsc95xx_read_reg(dev, WUCSR, &val); - check_warn_return(ret, "Error reading WUCSR"); - - val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_); - - ret = smsc95xx_write_reg(dev, WUCSR, val); - check_warn_return(ret, "Error writing WUCSR"); - - ret = smsc95xx_read_reg(dev, PM_CTRL, &val); - check_warn_return(ret, "Error reading PM_CTRL"); - - val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_); - - ret = smsc95xx_write_reg(dev, PM_CTRL, val); - check_warn_return(ret, "Error writing PM_CTRL"); - - /* enter suspend2 mode */ - ret = smsc95xx_read_reg(dev, PM_CTRL, &val); - check_warn_return(ret, "Error reading PM_CTRL"); - - val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_); - val |= PM_CTL_SUS_MODE_2; - - ret = smsc95xx_write_reg(dev, PM_CTRL, val); - check_warn_return(ret, "Error writing PM_CTRL"); - - return 0; - } - - if (pdata->wolopts & WAKE_MAGIC) { - /* clear any pending magic packet status */ - ret = smsc95xx_read_reg(dev, WUCSR, &val); - check_warn_return(ret, "Error reading WUCSR"); - - val |= WUCSR_MPR_; - - ret = smsc95xx_write_reg(dev, WUCSR, val); - check_warn_return(ret, "Error writing WUCSR"); - } - - /* enable/disable magic packup wake */ - ret = smsc95xx_read_reg(dev, WUCSR, &val); - check_warn_return(ret, "Error reading WUCSR"); - - if (pdata->wolopts & WAKE_MAGIC) { - netdev_info(dev->net, "enabling magic packet wakeup"); - val |= WUCSR_MPEN_; - } else { - netdev_info(dev->net, "disabling magic packet wakeup"); - val &= ~WUCSR_MPEN_; - } - - ret = smsc95xx_write_reg(dev, WUCSR, val); - check_warn_return(ret, "Error writing WUCSR"); - - /* enable wol wakeup source */ - ret = smsc95xx_read_reg(dev, PM_CTRL, &val); - check_warn_return(ret, "Error reading PM_CTRL"); - - val |= PM_CTL_WOL_EN_; - - ret = smsc95xx_write_reg(dev, PM_CTRL, val); - check_warn_return(ret, "Error writing PM_CTRL"); - - /* enable receiver */ - smsc95xx_start_rx_path(dev); - - /* some wol options are enabled, so enter SUSPEND0 */ - netdev_info(dev->net, "entering SUSPEND0 mode"); - - ret = smsc95xx_read_reg(dev, PM_CTRL, &val); - check_warn_return(ret, "Error reading PM_CTRL"); - - val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_)); - val |= PM_CTL_SUS_MODE_0; - - ret = smsc95xx_write_reg(dev, PM_CTRL, val); - check_warn_return(ret, "Error writing PM_CTRL"); - - /* clear wol status */ - val &= ~PM_CTL_WUPS_; - val |= PM_CTL_WUPS_WOL_; - ret = smsc95xx_write_reg(dev, PM_CTRL, val); - check_warn_return(ret, "Error writing PM_CTRL"); - - /* read back PM_CTRL */ - ret = smsc95xx_read_reg(dev, PM_CTRL, &val); - check_warn_return(ret, "Error reading PM_CTRL"); - - smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP); - - return 0; -} - -static int smsc95xx_resume(struct usb_interface *intf) -{ - struct usbnet *dev = usb_get_intfdata(intf); - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - int ret; - u32 val; - - BUG_ON(!dev); - - if (pdata->wolopts & WAKE_MAGIC) { - smsc95xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP); - - /* Disable magic packup wake */ - ret = smsc95xx_read_reg(dev, WUCSR, &val); - check_warn_return(ret, "Error reading WUCSR"); - - val &= ~WUCSR_MPEN_; - - ret = smsc95xx_write_reg(dev, WUCSR, val); - check_warn_return(ret, "Error writing WUCSR"); - - /* clear wake-up status */ - ret = smsc95xx_read_reg(dev, PM_CTRL, &val); - check_warn_return(ret, "Error reading PM_CTRL"); - - val &= ~PM_CTL_WOL_EN_; - val |= PM_CTL_WUPS_; - - ret = smsc95xx_write_reg(dev, PM_CTRL, val); - check_warn_return(ret, "Error writing PM_CTRL"); - } - - return usbnet_resume(intf); - check_warn_return(ret, "usbnet_resume error"); - - return 0; -} - static void smsc95xx_rx_csum_offload(struct sk_buff *skb) { skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2); @@ -1475,9 +1326,8 @@ static struct usb_driver smsc95xx_driver = { .name = "smsc95xx", .id_table = products, .probe = usbnet_probe, - .suspend = smsc95xx_suspend, - .resume = smsc95xx_resume, - .reset_resume = smsc95xx_resume, + .suspend = usbnet_suspend, + .resume = usbnet_resume, .disconnect = usbnet_disconnect, .disable_hub_initiated_lpm = 1, }; diff --git a/trunk/drivers/net/usb/smsc95xx.h b/trunk/drivers/net/usb/smsc95xx.h index 2ff9815aa27c..86bc44977fbd 100644 --- a/trunk/drivers/net/usb/smsc95xx.h +++ b/trunk/drivers/net/usb/smsc95xx.h @@ -63,7 +63,6 @@ #define INT_STS_TDFO_ (0x00001000) #define INT_STS_RXDF_ (0x00000800) #define INT_STS_GPIOS_ (0x000007FF) -#define INT_STS_CLEAR_ALL_ (0xFFFFFFFF) #define RX_CFG (0x0C) #define RX_FIFO_FLUSH_ (0x00000001) @@ -84,16 +83,12 @@ #define HW_CFG_BCE_ (0x00000002) #define HW_CFG_SRST_ (0x00000001) -#define RX_FIFO_INF (0x18) - #define PM_CTRL (0x20) -#define PM_CTL_RES_CLR_WKP_STS (0x00000200) #define PM_CTL_DEV_RDY_ (0x00000080) #define PM_CTL_SUS_MODE_ (0x00000060) #define PM_CTL_SUS_MODE_0 (0x00000000) #define PM_CTL_SUS_MODE_1 (0x00000020) -#define PM_CTL_SUS_MODE_2 (0x00000040) -#define PM_CTL_SUS_MODE_3 (0x00000060) +#define PM_CTL_SUS_MODE_2 (0x00000060) #define PM_CTL_PHY_RST_ (0x00000010) #define PM_CTL_WOL_EN_ (0x00000008) #define PM_CTL_ED_EN_ (0x00000004) @@ -205,11 +200,6 @@ #define WUFF (0x128) #define WUCSR (0x12C) -#define WUCSR_GUE_ (0x00000200) -#define WUCSR_WUFR_ (0x00000040) -#define WUCSR_MPR_ (0x00000020) -#define WUCSR_WAKE_EN_ (0x00000004) -#define WUCSR_MPEN_ (0x00000002) #define COE_CR (0x130) #define Tx_COE_EN_ (0x00010000) diff --git a/trunk/drivers/net/vxlan.c b/trunk/drivers/net/vxlan.c deleted file mode 100644 index f87a98f1aec2..000000000000 --- a/trunk/drivers/net/vxlan.c +++ /dev/null @@ -1,1217 +0,0 @@ -/* - * VXLAN: Virtual eXtensiable Local Area Network - * - * Copyright (c) 2012 Vyatta Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO - * - use IANA UDP port number (when defined) - * - IPv6 (not in RFC) - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define VXLAN_VERSION "0.1" - -#define VNI_HASH_BITS 10 -#define VNI_HASH_SIZE (1<vni_list[hash_32(id, VNI_HASH_BITS)]; -} - -/* Look up VNI in a per net namespace table */ -static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id) -{ - struct vxlan_dev *vxlan; - struct hlist_node *node; - - hlist_for_each_entry_rcu(vxlan, node, vni_head(net, id), hlist) { - if (vxlan->vni == id) - return vxlan; - } - - return NULL; -} - -/* Fill in neighbour message in skbuff. */ -static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, - const struct vxlan_fdb *fdb, - u32 portid, u32 seq, int type, unsigned int flags) -{ - unsigned long now = jiffies; - struct nda_cacheinfo ci; - struct nlmsghdr *nlh; - struct ndmsg *ndm; - - nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags); - if (nlh == NULL) - return -EMSGSIZE; - - ndm = nlmsg_data(nlh); - memset(ndm, 0, sizeof(*ndm)); - ndm->ndm_family = AF_BRIDGE; - ndm->ndm_state = fdb->state; - ndm->ndm_ifindex = vxlan->dev->ifindex; - ndm->ndm_flags = NTF_SELF; - ndm->ndm_type = NDA_DST; - - if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr)) - goto nla_put_failure; - - if (nla_put_be32(skb, NDA_DST, fdb->remote_ip)) - goto nla_put_failure; - - ci.ndm_used = jiffies_to_clock_t(now - fdb->used); - ci.ndm_confirmed = 0; - ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); - ci.ndm_refcnt = 0; - - if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) - goto nla_put_failure; - - return nlmsg_end(skb, nlh); - -nla_put_failure: - nlmsg_cancel(skb, nlh); - return -EMSGSIZE; -} - -static inline size_t vxlan_nlmsg_size(void) -{ - return NLMSG_ALIGN(sizeof(struct ndmsg)) - + nla_total_size(ETH_ALEN) /* NDA_LLADDR */ - + nla_total_size(sizeof(__be32)) /* NDA_DST */ - + nla_total_size(sizeof(struct nda_cacheinfo)); -} - -static void vxlan_fdb_notify(struct vxlan_dev *vxlan, - const struct vxlan_fdb *fdb, int type) -{ - struct net *net = dev_net(vxlan->dev); - struct sk_buff *skb; - int err = -ENOBUFS; - - skb = nlmsg_new(vxlan_nlmsg_size(), GFP_ATOMIC); - if (skb == NULL) - goto errout; - - err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0); - if (err < 0) { - /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */ - WARN_ON(err == -EMSGSIZE); - kfree_skb(skb); - goto errout; - } - - rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); - return; -errout: - if (err < 0) - rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); -} - -/* Hash Ethernet address */ -static u32 eth_hash(const unsigned char *addr) -{ - u64 value = get_unaligned((u64 *)addr); - - /* only want 6 bytes */ -#ifdef __BIG_ENDIAN - value <<= 16; -#else - value >>= 16; -#endif - return hash_64(value, FDB_HASH_BITS); -} - -/* Hash chain to use given mac address */ -static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan, - const u8 *mac) -{ - return &vxlan->fdb_head[eth_hash(mac)]; -} - -/* Look up Ethernet address in forwarding table */ -static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, - const u8 *mac) - -{ - struct hlist_head *head = vxlan_fdb_head(vxlan, mac); - struct vxlan_fdb *f; - struct hlist_node *node; - - hlist_for_each_entry_rcu(f, node, head, hlist) { - if (compare_ether_addr(mac, f->eth_addr) == 0) - return f; - } - - return NULL; -} - -/* Add new entry to forwarding table -- assumes lock held */ -static int vxlan_fdb_create(struct vxlan_dev *vxlan, - const u8 *mac, __be32 ip, - __u16 state, __u16 flags) -{ - struct vxlan_fdb *f; - int notify = 0; - - f = vxlan_find_mac(vxlan, mac); - if (f) { - if (flags & NLM_F_EXCL) { - netdev_dbg(vxlan->dev, - "lost race to create %pM\n", mac); - return -EEXIST; - } - if (f->state != state) { - f->state = state; - f->updated = jiffies; - notify = 1; - } - } else { - if (!(flags & NLM_F_CREATE)) - return -ENOENT; - - if (vxlan->addrmax && vxlan->addrcnt >= vxlan->addrmax) - return -ENOSPC; - - netdev_dbg(vxlan->dev, "add %pM -> %pI4\n", mac, &ip); - f = kmalloc(sizeof(*f), GFP_ATOMIC); - if (!f) - return -ENOMEM; - - notify = 1; - f->remote_ip = ip; - f->state = state; - f->updated = f->used = jiffies; - memcpy(f->eth_addr, mac, ETH_ALEN); - - ++vxlan->addrcnt; - hlist_add_head_rcu(&f->hlist, - vxlan_fdb_head(vxlan, mac)); - } - - if (notify) - vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); - - return 0; -} - -static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f) -{ - netdev_dbg(vxlan->dev, - "delete %pM\n", f->eth_addr); - - --vxlan->addrcnt; - vxlan_fdb_notify(vxlan, f, RTM_DELNEIGH); - - hlist_del_rcu(&f->hlist); - kfree_rcu(f, rcu); -} - -/* Add static entry (via netlink) */ -static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], - struct net_device *dev, - const unsigned char *addr, u16 flags) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - __be32 ip; - int err; - - if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) { - pr_info("RTM_NEWNEIGH with invalid state %#x\n", - ndm->ndm_state); - return -EINVAL; - } - - if (tb[NDA_DST] == NULL) - return -EINVAL; - - if (nla_len(tb[NDA_DST]) != sizeof(__be32)) - return -EAFNOSUPPORT; - - ip = nla_get_be32(tb[NDA_DST]); - - spin_lock_bh(&vxlan->hash_lock); - err = vxlan_fdb_create(vxlan, addr, ip, ndm->ndm_state, flags); - spin_unlock_bh(&vxlan->hash_lock); - - return err; -} - -/* Delete entry (via netlink) */ -static int vxlan_fdb_delete(struct ndmsg *ndm, struct net_device *dev, - const unsigned char *addr) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_fdb *f; - int err = -ENOENT; - - spin_lock_bh(&vxlan->hash_lock); - f = vxlan_find_mac(vxlan, addr); - if (f) { - vxlan_fdb_destroy(vxlan, f); - err = 0; - } - spin_unlock_bh(&vxlan->hash_lock); - - return err; -} - -/* Dump forwarding table */ -static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct net_device *dev, int idx) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - unsigned int h; - - for (h = 0; h < FDB_HASH_SIZE; ++h) { - struct vxlan_fdb *f; - struct hlist_node *n; - int err; - - hlist_for_each_entry_rcu(f, n, &vxlan->fdb_head[h], hlist) { - if (idx < cb->args[0]) - goto skip; - - err = vxlan_fdb_info(skb, vxlan, f, - NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, - RTM_NEWNEIGH, - NLM_F_MULTI); - if (err < 0) - break; -skip: - ++idx; - } - } - - return idx; -} - -/* Watch incoming packets to learn mapping between Ethernet address - * and Tunnel endpoint. - */ -static void vxlan_snoop(struct net_device *dev, - __be32 src_ip, const u8 *src_mac) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_fdb *f; - int err; - - f = vxlan_find_mac(vxlan, src_mac); - if (likely(f)) { - f->used = jiffies; - if (likely(f->remote_ip == src_ip)) - return; - - if (net_ratelimit()) - netdev_info(dev, - "%pM migrated from %pI4 to %pI4\n", - src_mac, &f->remote_ip, &src_ip); - - f->remote_ip = src_ip; - f->updated = jiffies; - } else { - /* learned new entry */ - spin_lock(&vxlan->hash_lock); - err = vxlan_fdb_create(vxlan, src_mac, src_ip, - NUD_REACHABLE, - NLM_F_EXCL|NLM_F_CREATE); - spin_unlock(&vxlan->hash_lock); - } -} - - -/* See if multicast group is already in use by other ID */ -static bool vxlan_group_used(struct vxlan_net *vn, - const struct vxlan_dev *this) -{ - const struct vxlan_dev *vxlan; - struct hlist_node *node; - unsigned h; - - for (h = 0; h < VNI_HASH_SIZE; ++h) - hlist_for_each_entry(vxlan, node, &vn->vni_list[h], hlist) { - if (vxlan == this) - continue; - - if (!netif_running(vxlan->dev)) - continue; - - if (vxlan->gaddr == this->gaddr) - return true; - } - - return false; -} - -/* kernel equivalent to IP_ADD_MEMBERSHIP */ -static int vxlan_join_group(struct net_device *dev) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); - struct sock *sk = vn->sock->sk; - struct ip_mreqn mreq = { - .imr_multiaddr.s_addr = vxlan->gaddr, - }; - int err; - - /* Already a member of group */ - if (vxlan_group_used(vn, vxlan)) - return 0; - - /* Need to drop RTNL to call multicast join */ - rtnl_unlock(); - lock_sock(sk); - err = ip_mc_join_group(sk, &mreq); - release_sock(sk); - rtnl_lock(); - - return err; -} - - -/* kernel equivalent to IP_DROP_MEMBERSHIP */ -static int vxlan_leave_group(struct net_device *dev) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); - int err = 0; - struct sock *sk = vn->sock->sk; - struct ip_mreqn mreq = { - .imr_multiaddr.s_addr = vxlan->gaddr, - }; - - /* Only leave group when last vxlan is done. */ - if (vxlan_group_used(vn, vxlan)) - return 0; - - /* Need to drop RTNL to call multicast leave */ - rtnl_unlock(); - lock_sock(sk); - err = ip_mc_leave_group(sk, &mreq); - release_sock(sk); - rtnl_lock(); - - return err; -} - -/* Callback from net/ipv4/udp.c to receive packets */ -static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) -{ - struct iphdr *oip; - struct vxlanhdr *vxh; - struct vxlan_dev *vxlan; - struct vxlan_stats *stats; - __u32 vni; - int err; - - /* pop off outer UDP header */ - __skb_pull(skb, sizeof(struct udphdr)); - - /* Need Vxlan and inner Ethernet header to be present */ - if (!pskb_may_pull(skb, sizeof(struct vxlanhdr))) - goto error; - - /* Drop packets with reserved bits set */ - vxh = (struct vxlanhdr *) skb->data; - if (vxh->vx_flags != htonl(VXLAN_FLAGS) || - (vxh->vx_vni & htonl(0xff))) { - netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n", - ntohl(vxh->vx_flags), ntohl(vxh->vx_vni)); - goto error; - } - - __skb_pull(skb, sizeof(struct vxlanhdr)); - skb_postpull_rcsum(skb, eth_hdr(skb), sizeof(struct vxlanhdr)); - - /* Is this VNI defined? */ - vni = ntohl(vxh->vx_vni) >> 8; - vxlan = vxlan_find_vni(sock_net(sk), vni); - if (!vxlan) { - netdev_dbg(skb->dev, "unknown vni %d\n", vni); - goto drop; - } - - if (!pskb_may_pull(skb, ETH_HLEN)) { - vxlan->dev->stats.rx_length_errors++; - vxlan->dev->stats.rx_errors++; - goto drop; - } - - /* Re-examine inner Ethernet packet */ - oip = ip_hdr(skb); - skb->protocol = eth_type_trans(skb, vxlan->dev); - skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); - - /* Ignore packet loops (and multicast echo) */ - if (compare_ether_addr(eth_hdr(skb)->h_source, - vxlan->dev->dev_addr) == 0) - goto drop; - - if (vxlan->learn) - vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source); - - __skb_tunnel_rx(skb, vxlan->dev); - skb_reset_network_header(skb); - - err = IP_ECN_decapsulate(oip, skb); - if (unlikely(err)) { - if (log_ecn_error) - net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", - &oip->saddr, oip->tos); - if (err > 1) { - ++vxlan->dev->stats.rx_frame_errors; - ++vxlan->dev->stats.rx_errors; - goto drop; - } - } - - stats = this_cpu_ptr(vxlan->stats); - u64_stats_update_begin(&stats->syncp); - stats->rx_packets++; - stats->rx_bytes += skb->len; - u64_stats_update_end(&stats->syncp); - - netif_rx(skb); - - return 0; -error: - /* Put UDP header back */ - __skb_push(skb, sizeof(struct udphdr)); - - return 1; -drop: - /* Consume bad packet */ - kfree_skb(skb); - return 0; -} - -/* Extract dsfield from inner protocol */ -static inline u8 vxlan_get_dsfield(const struct iphdr *iph, - const struct sk_buff *skb) -{ - if (skb->protocol == htons(ETH_P_IP)) - return iph->tos; - else if (skb->protocol == htons(ETH_P_IPV6)) - return ipv6_get_dsfield((const struct ipv6hdr *)iph); - else - return 0; -} - -/* Propogate ECN bits out */ -static inline u8 vxlan_ecn_encap(u8 tos, - const struct iphdr *iph, - const struct sk_buff *skb) -{ - u8 inner = vxlan_get_dsfield(iph, skb); - - return INET_ECN_encapsulate(tos, inner); -} - -/* Transmit local packets over Vxlan - * - * Outer IP header inherits ECN and DF from inner header. - * Outer UDP destination is the VXLAN assigned port. - * source port is based on hash of flow if available - * otherwise use a random value - */ -static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct rtable *rt; - const struct ethhdr *eth; - const struct iphdr *old_iph; - struct iphdr *iph; - struct vxlanhdr *vxh; - struct udphdr *uh; - struct flowi4 fl4; - struct vxlan_fdb *f; - unsigned int pkt_len = skb->len; - u32 hash; - __be32 dst; - __be16 df = 0; - __u8 tos, ttl; - int err; - - /* Need space for new headers (invalidates iph ptr) */ - if (skb_cow_head(skb, VXLAN_HEADROOM)) - goto drop; - - eth = (void *)skb->data; - old_iph = ip_hdr(skb); - - if (!is_multicast_ether_addr(eth->h_dest) && - (f = vxlan_find_mac(vxlan, eth->h_dest))) - dst = f->remote_ip; - else if (vxlan->gaddr) { - dst = vxlan->gaddr; - } else - goto drop; - - ttl = vxlan->ttl; - if (!ttl && IN_MULTICAST(ntohl(dst))) - ttl = 1; - - tos = vxlan->tos; - if (tos == 1) - tos = vxlan_get_dsfield(old_iph, skb); - - hash = skb_get_rxhash(skb); - - rt = ip_route_output_gre(dev_net(dev), &fl4, dst, - vxlan->saddr, vxlan->vni, - RT_TOS(tos), vxlan->link); - if (IS_ERR(rt)) { - netdev_dbg(dev, "no route to %pI4\n", &dst); - dev->stats.tx_carrier_errors++; - goto tx_error; - } - - if (rt->dst.dev == dev) { - netdev_dbg(dev, "circular route to %pI4\n", &dst); - ip_rt_put(rt); - dev->stats.collisions++; - goto tx_error; - } - - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | - IPSKB_REROUTED); - skb_dst_drop(skb); - skb_dst_set(skb, &rt->dst); - - vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); - vxh->vx_flags = htonl(VXLAN_FLAGS); - vxh->vx_vni = htonl(vxlan->vni << 8); - - __skb_push(skb, sizeof(*uh)); - skb_reset_transport_header(skb); - uh = udp_hdr(skb); - - uh->dest = htons(vxlan_port); - uh->source = hash ? :random32(); - - uh->len = htons(skb->len); - uh->check = 0; - - __skb_push(skb, sizeof(*iph)); - skb_reset_network_header(skb); - iph = ip_hdr(skb); - iph->version = 4; - iph->ihl = sizeof(struct iphdr) >> 2; - iph->frag_off = df; - iph->protocol = IPPROTO_UDP; - iph->tos = vxlan_ecn_encap(tos, old_iph, skb); - iph->daddr = fl4.daddr; - iph->saddr = fl4.saddr; - iph->ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); - - /* See __IPTUNNEL_XMIT */ - skb->ip_summed = CHECKSUM_NONE; - ip_select_ident(iph, &rt->dst, NULL); - - err = ip_local_out(skb); - if (likely(net_xmit_eval(err) == 0)) { - struct vxlan_stats *stats = this_cpu_ptr(vxlan->stats); - - u64_stats_update_begin(&stats->syncp); - stats->tx_packets++; - stats->tx_bytes += pkt_len; - u64_stats_update_end(&stats->syncp); - } else { - dev->stats.tx_errors++; - dev->stats.tx_aborted_errors++; - } - return NETDEV_TX_OK; - -drop: - dev->stats.tx_dropped++; - goto tx_free; - -tx_error: - dev->stats.tx_errors++; -tx_free: - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -/* Walk the forwarding table and purge stale entries */ -static void vxlan_cleanup(unsigned long arg) -{ - struct vxlan_dev *vxlan = (struct vxlan_dev *) arg; - unsigned long next_timer = jiffies + FDB_AGE_INTERVAL; - unsigned int h; - - if (!netif_running(vxlan->dev)) - return; - - spin_lock_bh(&vxlan->hash_lock); - for (h = 0; h < FDB_HASH_SIZE; ++h) { - struct hlist_node *p, *n; - hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { - struct vxlan_fdb *f - = container_of(p, struct vxlan_fdb, hlist); - unsigned long timeout; - - if (f->state == NUD_PERMANENT) - continue; - - timeout = f->used + vxlan->age_interval * HZ; - if (time_before_eq(timeout, jiffies)) { - netdev_dbg(vxlan->dev, - "garbage collect %pM\n", - f->eth_addr); - f->state = NUD_STALE; - vxlan_fdb_destroy(vxlan, f); - } else if (time_before(timeout, next_timer)) - next_timer = timeout; - } - } - spin_unlock_bh(&vxlan->hash_lock); - - mod_timer(&vxlan->age_timer, next_timer); -} - -/* Setup stats when device is created */ -static int vxlan_init(struct net_device *dev) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - - vxlan->stats = alloc_percpu(struct vxlan_stats); - if (!vxlan->stats) - return -ENOMEM; - - return 0; -} - -/* Start ageing timer and join group when device is brought up */ -static int vxlan_open(struct net_device *dev) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - int err; - - if (vxlan->gaddr) { - err = vxlan_join_group(dev); - if (err) - return err; - } - - if (vxlan->age_interval) - mod_timer(&vxlan->age_timer, jiffies + FDB_AGE_INTERVAL); - - return 0; -} - -/* Purge the forwarding table */ -static void vxlan_flush(struct vxlan_dev *vxlan) -{ - unsigned h; - - spin_lock_bh(&vxlan->hash_lock); - for (h = 0; h < FDB_HASH_SIZE; ++h) { - struct hlist_node *p, *n; - hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { - struct vxlan_fdb *f - = container_of(p, struct vxlan_fdb, hlist); - vxlan_fdb_destroy(vxlan, f); - } - } - spin_unlock_bh(&vxlan->hash_lock); -} - -/* Cleanup timer and forwarding table on shutdown */ -static int vxlan_stop(struct net_device *dev) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - - if (vxlan->gaddr) - vxlan_leave_group(dev); - - del_timer_sync(&vxlan->age_timer); - - vxlan_flush(vxlan); - - return 0; -} - -/* Merge per-cpu statistics */ -static struct rtnl_link_stats64 *vxlan_stats64(struct net_device *dev, - struct rtnl_link_stats64 *stats) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_stats tmp, sum = { 0 }; - unsigned int cpu; - - for_each_possible_cpu(cpu) { - unsigned int start; - const struct vxlan_stats *stats - = per_cpu_ptr(vxlan->stats, cpu); - - do { - start = u64_stats_fetch_begin_bh(&stats->syncp); - memcpy(&tmp, stats, sizeof(tmp)); - } while (u64_stats_fetch_retry_bh(&stats->syncp, start)); - - sum.tx_bytes += tmp.tx_bytes; - sum.tx_packets += tmp.tx_packets; - sum.rx_bytes += tmp.rx_bytes; - sum.rx_packets += tmp.rx_packets; - } - - stats->tx_bytes = sum.tx_bytes; - stats->tx_packets = sum.tx_packets; - stats->rx_bytes = sum.rx_bytes; - stats->rx_packets = sum.rx_packets; - - stats->multicast = dev->stats.multicast; - stats->rx_length_errors = dev->stats.rx_length_errors; - stats->rx_frame_errors = dev->stats.rx_frame_errors; - stats->rx_errors = dev->stats.rx_errors; - - stats->tx_dropped = dev->stats.tx_dropped; - stats->tx_carrier_errors = dev->stats.tx_carrier_errors; - stats->tx_aborted_errors = dev->stats.tx_aborted_errors; - stats->collisions = dev->stats.collisions; - stats->tx_errors = dev->stats.tx_errors; - - return stats; -} - -/* Stub, nothing needs to be done. */ -static void vxlan_set_multicast_list(struct net_device *dev) -{ -} - -static const struct net_device_ops vxlan_netdev_ops = { - .ndo_init = vxlan_init, - .ndo_open = vxlan_open, - .ndo_stop = vxlan_stop, - .ndo_start_xmit = vxlan_xmit, - .ndo_get_stats64 = vxlan_stats64, - .ndo_set_rx_mode = vxlan_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, - .ndo_fdb_add = vxlan_fdb_add, - .ndo_fdb_del = vxlan_fdb_delete, - .ndo_fdb_dump = vxlan_fdb_dump, -}; - -/* Info for udev, that this is a virtual tunnel endpoint */ -static struct device_type vxlan_type = { - .name = "vxlan", -}; - -static void vxlan_free(struct net_device *dev) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - - free_percpu(vxlan->stats); - free_netdev(dev); -} - -/* Initialize the device structure. */ -static void vxlan_setup(struct net_device *dev) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - unsigned h; - - eth_hw_addr_random(dev); - ether_setup(dev); - - dev->netdev_ops = &vxlan_netdev_ops; - dev->destructor = vxlan_free; - SET_NETDEV_DEVTYPE(dev, &vxlan_type); - - dev->tx_queue_len = 0; - dev->features |= NETIF_F_LLTX; - dev->features |= NETIF_F_NETNS_LOCAL; - dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; - - spin_lock_init(&vxlan->hash_lock); - - init_timer_deferrable(&vxlan->age_timer); - vxlan->age_timer.function = vxlan_cleanup; - vxlan->age_timer.data = (unsigned long) vxlan; - - vxlan->dev = dev; - - for (h = 0; h < FDB_HASH_SIZE; ++h) - INIT_HLIST_HEAD(&vxlan->fdb_head[h]); -} - -static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { - [IFLA_VXLAN_ID] = { .type = NLA_U32 }, - [IFLA_VXLAN_GROUP] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, - [IFLA_VXLAN_LINK] = { .type = NLA_U32 }, - [IFLA_VXLAN_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, - [IFLA_VXLAN_TOS] = { .type = NLA_U8 }, - [IFLA_VXLAN_TTL] = { .type = NLA_U8 }, - [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 }, - [IFLA_VXLAN_AGEING] = { .type = NLA_U32 }, - [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 }, -}; - -static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) -{ - if (tb[IFLA_ADDRESS]) { - if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { - pr_debug("invalid link address (not ethernet)\n"); - return -EINVAL; - } - - if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) { - pr_debug("invalid all zero ethernet address\n"); - return -EADDRNOTAVAIL; - } - } - - if (!data) - return -EINVAL; - - if (data[IFLA_VXLAN_ID]) { - __u32 id = nla_get_u32(data[IFLA_VXLAN_ID]); - if (id >= VXLAN_VID_MASK) - return -ERANGE; - } - - if (data[IFLA_VXLAN_GROUP]) { - __be32 gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]); - if (!IN_MULTICAST(ntohl(gaddr))) { - pr_debug("group address is not IPv4 multicast\n"); - return -EADDRNOTAVAIL; - } - } - return 0; -} - -static int vxlan_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[]) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - __u32 vni; - int err; - - if (!data[IFLA_VXLAN_ID]) - return -EINVAL; - - vni = nla_get_u32(data[IFLA_VXLAN_ID]); - if (vxlan_find_vni(net, vni)) { - pr_info("duplicate VNI %u\n", vni); - return -EEXIST; - } - vxlan->vni = vni; - - if (data[IFLA_VXLAN_GROUP]) - vxlan->gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]); - - if (data[IFLA_VXLAN_LOCAL]) - vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]); - - if (data[IFLA_VXLAN_LINK]) { - vxlan->link = nla_get_u32(data[IFLA_VXLAN_LINK]); - - if (!tb[IFLA_MTU]) { - struct net_device *lowerdev; - lowerdev = __dev_get_by_index(net, vxlan->link); - dev->mtu = lowerdev->mtu - VXLAN_HEADROOM; - } - } - - if (data[IFLA_VXLAN_TOS]) - vxlan->tos = nla_get_u8(data[IFLA_VXLAN_TOS]); - - if (!data[IFLA_VXLAN_LEARNING] || nla_get_u8(data[IFLA_VXLAN_LEARNING])) - vxlan->learn = true; - - if (data[IFLA_VXLAN_AGEING]) - vxlan->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]); - else - vxlan->age_interval = FDB_AGE_DEFAULT; - - if (data[IFLA_VXLAN_LIMIT]) - vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]); - - err = register_netdevice(dev); - if (!err) - hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->vni)); - - return err; -} - -static void vxlan_dellink(struct net_device *dev, struct list_head *head) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - - hlist_del_rcu(&vxlan->hlist); - - unregister_netdevice_queue(dev, head); -} - -static size_t vxlan_get_size(const struct net_device *dev) -{ - - return nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_ID */ - nla_total_size(sizeof(__be32)) +/* IFLA_VXLAN_GROUP */ - nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LINK */ - nla_total_size(sizeof(__be32))+ /* IFLA_VXLAN_LOCAL */ - nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */ - nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TOS */ - nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */ - nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */ - nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */ - 0; -} - -static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) -{ - const struct vxlan_dev *vxlan = netdev_priv(dev); - - if (nla_put_u32(skb, IFLA_VXLAN_ID, vxlan->vni)) - goto nla_put_failure; - - if (vxlan->gaddr && nla_put_u32(skb, IFLA_VXLAN_GROUP, vxlan->gaddr)) - goto nla_put_failure; - - if (vxlan->link && nla_put_u32(skb, IFLA_VXLAN_LINK, vxlan->link)) - goto nla_put_failure; - - if (vxlan->saddr && nla_put_u32(skb, IFLA_VXLAN_LOCAL, vxlan->saddr)) - goto nla_put_failure; - - if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->ttl) || - nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->tos) || - nla_put_u8(skb, IFLA_VXLAN_LEARNING, vxlan->learn) || - nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) || - nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax)) - goto nla_put_failure; - - return 0; - -nla_put_failure: - return -EMSGSIZE; -} - -static struct rtnl_link_ops vxlan_link_ops __read_mostly = { - .kind = "vxlan", - .maxtype = IFLA_VXLAN_MAX, - .policy = vxlan_policy, - .priv_size = sizeof(struct vxlan_dev), - .setup = vxlan_setup, - .validate = vxlan_validate, - .newlink = vxlan_newlink, - .dellink = vxlan_dellink, - .get_size = vxlan_get_size, - .fill_info = vxlan_fill_info, -}; - -static __net_init int vxlan_init_net(struct net *net) -{ - struct vxlan_net *vn = net_generic(net, vxlan_net_id); - struct sock *sk; - struct sockaddr_in vxlan_addr = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_ANY), - }; - int rc; - unsigned h; - - /* Create UDP socket for encapsulation receive. */ - rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vn->sock); - if (rc < 0) { - pr_debug("UDP socket create failed\n"); - return rc; - } - - vxlan_addr.sin_port = htons(vxlan_port); - - rc = kernel_bind(vn->sock, (struct sockaddr *) &vxlan_addr, - sizeof(vxlan_addr)); - if (rc < 0) { - pr_debug("bind for UDP socket %pI4:%u (%d)\n", - &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc); - sock_release(vn->sock); - vn->sock = NULL; - return rc; - } - - /* Disable multicast loopback */ - sk = vn->sock->sk; - inet_sk(sk)->mc_loop = 0; - - /* Mark socket as an encapsulation socket. */ - udp_sk(sk)->encap_type = 1; - udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv; - udp_encap_enable(); - - for (h = 0; h < VNI_HASH_SIZE; ++h) - INIT_HLIST_HEAD(&vn->vni_list[h]); - - return 0; -} - -static __net_exit void vxlan_exit_net(struct net *net) -{ - struct vxlan_net *vn = net_generic(net, vxlan_net_id); - - if (vn->sock) { - sock_release(vn->sock); - vn->sock = NULL; - } -} - -static struct pernet_operations vxlan_net_ops = { - .init = vxlan_init_net, - .exit = vxlan_exit_net, - .id = &vxlan_net_id, - .size = sizeof(struct vxlan_net), -}; - -static int __init vxlan_init_module(void) -{ - int rc; - - get_random_bytes(&vxlan_salt, sizeof(vxlan_salt)); - - rc = register_pernet_device(&vxlan_net_ops); - if (rc) - goto out1; - - rc = rtnl_link_register(&vxlan_link_ops); - if (rc) - goto out2; - - return 0; - -out2: - unregister_pernet_device(&vxlan_net_ops); -out1: - return rc; -} -module_init(vxlan_init_module); - -static void __exit vxlan_cleanup_module(void) -{ - rtnl_link_unregister(&vxlan_link_ops); - unregister_pernet_device(&vxlan_net_ops); -} -module_exit(vxlan_cleanup_module); - -MODULE_LICENSE("GPL"); -MODULE_VERSION(VXLAN_VERSION); -MODULE_AUTHOR("Stephen Hemminger "); -MODULE_ALIAS_RTNL_LINK("vxlan"); diff --git a/trunk/drivers/net/wireless/ath/ath.h b/trunk/drivers/net/wireless/ath/ath.h index 4521342c62cc..6169fbd23ed1 100644 --- a/trunk/drivers/net/wireless/ath/ath.h +++ b/trunk/drivers/net/wireless/ath/ath.h @@ -159,7 +159,6 @@ struct ath_common { bool btcoex_enabled; bool disable_ani; - bool antenna_diversity; }; struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.c b/trunk/drivers/net/wireless/ath/ath5k/base.c index 9fd6d9a9942e..a0a202de1109 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/base.c +++ b/trunk/drivers/net/wireless/ath/ath5k/base.c @@ -2446,7 +2446,6 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_REPORTS_TX_ACK_STATUS; hw->wiphy->interface_modes = diff --git a/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 7a28538e6e05..df61a09adb6d 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -489,9 +489,6 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (ath5k_modparam_nohwcrypt) return -EOPNOTSUPP; - if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) - return -EOPNOTSUPP; - if (vif->type == NL80211_IFTYPE_ADHOC && (key->cipher == WLAN_CIPHER_SUITE_TKIP || key->cipher == WLAN_CIPHER_SUITE_CCMP) && @@ -526,7 +523,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (key->cipher == WLAN_CIPHER_SUITE_TKIP) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; if (key->cipher == WLAN_CIPHER_SUITE_CCMP) - key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; ret = 0; } break; diff --git a/trunk/drivers/net/wireless/ath/ath5k/phy.c b/trunk/drivers/net/wireless/ath/ath5k/phy.c index ab363f34b4df..01c90ed58453 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/phy.c +++ b/trunk/drivers/net/wireless/ath/ath5k/phy.c @@ -1975,13 +1975,11 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, spur_delta_phase = (spur_offset << 18) / 25; spur_freq_sigma_delta = (spur_delta_phase >> 10); symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2; - break; case AR5K_BWMODE_5MHZ: /* Both sample_freq and chip_freq are 10MHz (?) */ spur_delta_phase = (spur_offset << 19) / 25; spur_freq_sigma_delta = (spur_delta_phase >> 10); symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; - break; default: if (channel->band == IEEE80211_BAND_5GHZ) { /* Both sample_freq and chip_freq are 40MHz */ diff --git a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c index 7089f8160ad5..86aeef4b9d7e 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1488,7 +1488,7 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy, } static struct wireless_dev *ath6kl_cfg80211_add_iface(struct wiphy *wiphy, - const char *name, + char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params) @@ -3477,7 +3477,7 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif) ar->num_vif--; } -struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, +struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name, enum nl80211_iftype type, u8 fw_vif_idx, u8 nw_type) { diff --git a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.h b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.h index 780f77775a91..56b1ebe79812 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.h @@ -25,7 +25,7 @@ enum ath6kl_cfg_suspend_mode { ATH6KL_CFG_SUSPEND_SCHED_SCAN, }; -struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, +struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name, enum nl80211_iftype type, u8 fw_vif_idx, u8 nw_type); void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, diff --git a/trunk/drivers/net/wireless/ath/ath9k/antenna.c b/trunk/drivers/net/wireless/ath/ath9k/antenna.c index 664844c5d3d5..bbcfeb3b2a60 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/antenna.c +++ b/trunk/drivers/net/wireless/ath/ath9k/antenna.c @@ -311,9 +311,6 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, struct ath_ant_comb *antcomb, int alt_ratio) { - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - if (ant_conf->div_group == 0) { /* Adjust the fast_div_bias based on main and alt lna conf */ switch ((ant_conf->main_lna_conf << 4) | @@ -363,12 +360,18 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->alt_lna_conf) { case 0x01: /* A-B LNA2 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x02: /* A-B LNA1 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x03: /* A-B A+B */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x10: /* LNA2 A-B */ if (!(antcomb->scan) && @@ -376,9 +379,13 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->fast_div_bias = 0x3f; else ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x12: /* LNA2 LNA1 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x13: /* LNA2 A+B */ if (!(antcomb->scan) && @@ -386,6 +393,8 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->fast_div_bias = 0x3f; else ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x20: /* LNA1 A-B */ if (!(antcomb->scan) && @@ -393,9 +402,13 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->fast_div_bias = 0x3f; else ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x21: /* LNA1 LNA2 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x23: /* LNA1 A+B */ if (!(antcomb->scan) && @@ -403,15 +416,23 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->fast_div_bias = 0x3f; else ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x30: /* A+B A-B */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x31: /* A+B LNA2 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x32: /* A+B LNA1 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; default: break; @@ -422,12 +443,18 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->alt_lna_conf) { case 0x01: /* A-B LNA2 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x02: /* A-B LNA1 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x03: /* A-B A+B */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x10: /* LNA2 A-B */ if (!(antcomb->scan) && @@ -435,9 +462,13 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->fast_div_bias = 0x1; else ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x12: /* LNA2 LNA1 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x13: /* LNA2 A+B */ if (!(antcomb->scan) && @@ -445,6 +476,8 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->fast_div_bias = 0x1; else ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x20: /* LNA1 A-B */ if (!(antcomb->scan) && @@ -452,9 +485,13 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->fast_div_bias = 0x1; else ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x21: /* LNA1 LNA2 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x23: /* LNA1 A+B */ if (!(antcomb->scan) && @@ -462,77 +499,23 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, ant_conf->fast_div_bias = 0x1; else ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x30: /* A+B A-B */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x31: /* A+B LNA2 */ ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; case 0x32: /* A+B LNA1 */ ant_conf->fast_div_bias = 0x1; - break; - default: - break; - } - } else if (ant_conf->div_group == 3) { - switch ((ant_conf->main_lna_conf << 4) | - ant_conf->alt_lna_conf) { - case 0x01: /* A-B LNA2 */ - ant_conf->fast_div_bias = 0x1; - break; - case 0x02: /* A-B LNA1 */ - ant_conf->fast_div_bias = 0x39; - break; - case 0x03: /* A-B A+B */ - ant_conf->fast_div_bias = 0x1; - break; - case 0x10: /* LNA2 A-B */ - if ((antcomb->scan == 0) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { - ant_conf->fast_div_bias = 0x3f; - } else { - ant_conf->fast_div_bias = 0x1; - } - break; - case 0x12: /* LNA2 LNA1 */ - ant_conf->fast_div_bias = 0x39; - break; - case 0x13: /* LNA2 A+B */ - if ((antcomb->scan == 0) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { - ant_conf->fast_div_bias = 0x3f; - } else { - ant_conf->fast_div_bias = 0x1; - } - break; - case 0x20: /* LNA1 A-B */ - if ((antcomb->scan == 0) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { - ant_conf->fast_div_bias = 0x3f; - } else { - ant_conf->fast_div_bias = 0x4; - } - break; - case 0x21: /* LNA1 LNA2 */ - ant_conf->fast_div_bias = 0x6; - break; - case 0x23: /* LNA1 A+B */ - if ((antcomb->scan == 0) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { - ant_conf->fast_div_bias = 0x3f; - } else { - ant_conf->fast_div_bias = 0x6; - } - break; - case 0x30: /* A+B A-B */ - ant_conf->fast_div_bias = 0x1; - break; - case 0x31: /* A+B LNA2 */ - ant_conf->fast_div_bias = 0x6; - break; - case 0x32: /* A+B LNA1 */ - ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; break; default: break; @@ -776,7 +759,6 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) void ath_ant_comb_update(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); struct ath_hw_antcomb_conf div_ant_conf; u8 lna_conf; @@ -791,7 +773,4 @@ void ath_ant_comb_update(struct ath_softc *sc) div_ant_conf.alt_lna_conf = lna_conf; ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); - - if (common->antenna_diversity) - ath9k_hw_antctrl_shared_chain_lnadiv(ah, true); } diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 5bbe5057ba18..b5659cb688fe 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -2987,10 +2987,6 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, case EEP_RX_MASK: return pBase->txrxMask & 0xf; case EEP_PAPRD: - if (AR_SREV_9462(ah)) - return false; - if (!ah->config.enable_paprd); - return false; return !!(pBase->featureEnable & BIT(5)); case EEP_CHAIN_MASK_REDUCE: return (pBase->miscConfiguration >> 0x3) & 0x1; @@ -3566,9 +3562,9 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, int chain, static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) { - struct ath9k_hw_capabilities *pCap = &ah->caps; int chain; u32 regval; + u32 ant_div_ctl1; static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { AR_PHY_SWITCH_CHAIN_0, AR_PHY_SWITCH_CHAIN_1, @@ -3633,16 +3629,6 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) /* enable_lnadiv */ regval &= (~AR_PHY_ANT_DIV_LNADIV); regval |= ((value >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S; - - if (AR_SREV_9565(ah)) { - if (ah->shared_chain_lnadiv) { - regval |= (1 << AR_PHY_ANT_SW_RX_PROT_S); - } else { - regval &= ~(1 << AR_PHY_ANT_DIV_LNADIV_S); - regval &= ~(1 << AR_PHY_ANT_SW_RX_PROT_S); - } - } - REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); /*enable fast_div */ @@ -3650,8 +3636,9 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) regval &= (~AR_FAST_DIV_ENABLE); regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); - - if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) { + ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); + /* check whether antenna diversity is enabled */ + if ((ant_div_ctl1 >> 0x6) == 0x3) { regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); /* * clear bits 25-30 main_lnaconf, alt_lnaconf, @@ -3668,7 +3655,10 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) AR_PHY_ANT_DIV_ALT_LNACONF_S); REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); } + + } + } static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 301bf72c53bf..d5b2e0ecc21c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -182,7 +182,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ; - bool fatal_int; if (ath9k_hw_mci_is_enabled(ah)) async_mask |= AR_INTR_ASYNC_MASK_MCI; @@ -311,22 +310,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) if (sync_cause) { ath9k_debug_sync_cause(common, sync_cause); - fatal_int = - (sync_cause & - (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) - ? true : false; - - if (fatal_int) { - if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { - ath_dbg(common, ANY, - "received PCI FATAL interrupt\n"); - } - if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { - ath_dbg(common, ANY, - "received PCI PERR interrupt\n"); - } - *masked |= ATH9K_INT_FATAL; - } if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c index 44c202ce6c66..b2e39e8a21b5 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c @@ -813,8 +813,8 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable) AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); } -int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, - bool is_full_sleep) +void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, + bool is_full_sleep) { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; @@ -824,13 +824,14 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, is_full_sleep, is_2g); if (!mci->gpm_addr && !mci->sched_addr) { - ath_err(common, "MCI GPM and schedule buffers are not allocated\n"); - return -ENOMEM; + ath_dbg(common, MCI, + "MCI GPM and schedule buffers are not allocated\n"); + return; } if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) { - ath_err(common, "BTCOEX control register is dead\n"); - return -EINVAL; + ath_dbg(common, MCI, "BTCOEX control register is dead\n"); + return; } /* Program MCI DMA related registers */ @@ -912,8 +913,6 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, if (en_int) ar9003_mci_enable_interrupt(ah); - - return 0; } void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep) @@ -1028,7 +1027,6 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) ar9003_mci_osla_setup(ah, true); - REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); } else { ar9003_mci_send_lna_take(ah, true); udelay(5); @@ -1145,8 +1143,8 @@ void ar9003_mci_init_cal_done(struct ath_hw *ah) ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); } -int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, - u16 len, u32 sched_addr) +void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, + u16 len, u32 sched_addr) { struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; @@ -1155,7 +1153,7 @@ int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, mci->gpm_len = len; mci->sched_addr = sched_addr; - return ar9003_mci_reset(ah, true, true, true); + ar9003_mci_reset(ah, true, true, true); } EXPORT_SYMBOL(ar9003_mci_setup); @@ -1237,10 +1235,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) case MCI_STATE_NEED_FTP_STOMP: value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); break; - case MCI_STATE_NEED_FLUSH_BT_INFO: - value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; - mci->need_flush_btinfo = false; - break; default: break; } @@ -1290,7 +1284,7 @@ void ar9003_mci_set_power_awake(struct ath_hw *ah) } REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18))); lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3; - bt_sleep = MS(REG_READ(ah, AR_MCI_RX_STATUS), AR_MCI_RX_REMOTE_SLEEP); + bt_sleep = REG_READ(ah, AR_MCI_RX_STATUS) & AR_MCI_RX_REMOTE_SLEEP; REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2); REG_WRITE(ah, AR_DIAG_SW, diag_sw); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h index 2a2d01889613..f3bef8d69edd 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h @@ -200,7 +200,6 @@ enum mci_state_type { MCI_STATE_RECOVER_RX, MCI_STATE_NEED_FTP_STOMP, MCI_STATE_DEBUG, - MCI_STATE_NEED_FLUSH_BT_INFO, MCI_STATE_MAX }; @@ -212,8 +211,7 @@ enum mci_gpm_coex_opcode { MCI_GPM_COEX_WLAN_CHANNELS, MCI_GPM_COEX_BT_PROFILE_INFO, MCI_GPM_COEX_BT_STATUS_UPDATE, - MCI_GPM_COEX_BT_UPDATE_FLAGS, - MCI_GPM_COEX_NOOP, + MCI_GPM_COEX_BT_UPDATE_FLAGS }; #define MCI_GPM_NOMORE 0 @@ -249,8 +247,8 @@ bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, u32 *payload, u8 len, bool wait_done, bool check_bt); u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type); -int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, - u16 len, u32 sched_addr); +void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, + u16 len, u32 sched_addr); void ar9003_mci_cleanup(struct ath_hw *ah); void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, u32 *rx_msg_intr); @@ -272,8 +270,8 @@ void ar9003_mci_check_bt(struct ath_hw *ah); bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan); int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, struct ath9k_hw_cal_data *caldata); -int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, - bool is_full_sleep); +void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, + bool is_full_sleep); void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); void ar9003_mci_set_power_awake(struct ath_hw *ah); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 759f5f5a7154..0d800c62e227 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -605,6 +605,9 @@ static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); + else if (AR_SREV_9462(ah)) + /* xxx only when MCI support is enabled */ + REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); else REG_WRITE(ah, AR_SELFGEN_MASK, tx); @@ -1291,9 +1294,6 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah, } else if (AR_SREV_9485(ah)) { antconf->lna1_lna2_delta = -9; antconf->div_group = 2; - } else if (AR_SREV_9565(ah)) { - antconf->lna1_lna2_delta = -3; - antconf->div_group = 3; } else { antconf->lna1_lna2_delta = -3; antconf->div_group = 0; @@ -1325,65 +1325,6 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); } -static void ar9003_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah, - bool enable) -{ - u8 ant_div_ctl1; - u32 regval; - - if (!AR_SREV_9565(ah)) - return; - - ah->shared_chain_lnadiv = enable; - ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); - - regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); - regval &= (~AR_ANT_DIV_CTRL_ALL); - regval |= (ant_div_ctl1 & 0x3f) << AR_ANT_DIV_CTRL_ALL_S; - regval &= ~AR_PHY_ANT_DIV_LNADIV; - regval |= ((ant_div_ctl1 >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S; - - if (enable) - regval |= AR_ANT_DIV_ENABLE; - - REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); - - regval = REG_READ(ah, AR_PHY_CCK_DETECT); - regval &= ~AR_FAST_DIV_ENABLE; - regval |= ((ant_div_ctl1 >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; - - if (enable) - regval |= AR_FAST_DIV_ENABLE; - - REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); - - if (enable) { - REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, - (1 << AR_PHY_ANT_SW_RX_PROT_S)); - if (ah->curchan && IS_CHAN_2GHZ(ah->curchan)) - REG_SET_BIT(ah, AR_PHY_RESTART, - AR_PHY_RESTART_ENABLE_DIV_M2FLAG); - REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, - AR_BTCOEX_WL_LNADIV_FORCE_ON); - } else { - REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE); - REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, - (1 << AR_PHY_ANT_SW_RX_PROT_S)); - REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE); - REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV, - AR_BTCOEX_WL_LNADIV_FORCE_ON); - - regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); - regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF | - AR_PHY_ANT_DIV_ALT_LNACONF | - AR_PHY_ANT_DIV_MAIN_GAINTB | - AR_PHY_ANT_DIV_ALT_GAINTB); - regval |= (AR_PHY_ANT_DIV_LNA1 << AR_PHY_ANT_DIV_MAIN_LNACONF_S); - regval |= (AR_PHY_ANT_DIV_LNA2 << AR_PHY_ANT_DIV_ALT_LNACONF_S); - REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); - } -} - static int ar9003_hw_fast_chan_change(struct ath_hw *ah, struct ath9k_channel *chan, u8 *ini_reloaded) @@ -1482,7 +1423,6 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; - ops->antctrl_shared_chain_lnadiv = ar9003_hw_antctrl_shared_chain_lnadiv; ar9003_hw_set_nf_limits(ah); ar9003_hw_set_radar_conf(ah); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 9a48e3d2f231..fdabc9a28a96 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -282,8 +282,6 @@ #define AR_PHY_ANT_FAST_DIV_BIAS 0x00007e00 #define AR_PHY_ANT_FAST_DIV_BIAS_S 9 -#define AR_PHY_ANT_SW_RX_PROT 0x00800000 -#define AR_PHY_ANT_SW_RX_PROT_S 23 #define AR_PHY_ANT_DIV_LNADIV 0x01000000 #define AR_PHY_ANT_DIV_LNADIV_S 24 #define AR_PHY_ANT_DIV_ALT_LNACONF 0x06000000 @@ -424,8 +422,6 @@ #define AR_PHY_FIND_SIG_RELSTEP 0x1f #define AR_PHY_FIND_SIG_RELSTEP_S 0 #define AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT 5 -#define AR_PHY_RESTART_ENABLE_DIV_M2FLAG 0x00200000 -#define AR_PHY_RESTART_ENABLE_DIV_M2FLAG_S 21 #define AR_PHY_RESTART_DIV_GC 0x001C0000 #define AR_PHY_RESTART_DIV_GC_S 18 #define AR_PHY_RESTART_ENA 0x01 @@ -1265,24 +1261,4 @@ #define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f #define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0 -#define AR_BTCOEX_WL_LNADIV 0x1a64 -#define AR_BTCOEX_WL_LNADIV_PREDICTED_PERIOD 0x00003FFF -#define AR_BTCOEX_WL_LNADIV_PREDICTED_PERIOD_S 0 -#define AR_BTCOEX_WL_LNADIV_DPDT_IGNORE_PRIORITY 0x00004000 -#define AR_BTCOEX_WL_LNADIV_DPDT_IGNORE_PRIORITY_S 14 -#define AR_BTCOEX_WL_LNADIV_FORCE_ON 0x00008000 -#define AR_BTCOEX_WL_LNADIV_FORCE_ON_S 15 -#define AR_BTCOEX_WL_LNADIV_MODE_OPTION 0x00030000 -#define AR_BTCOEX_WL_LNADIV_MODE_OPTION_S 16 -#define AR_BTCOEX_WL_LNADIV_MODE 0x007c0000 -#define AR_BTCOEX_WL_LNADIV_MODE_S 18 -#define AR_BTCOEX_WL_LNADIV_ALLOWED_TX_ANTDIV_WL_TX_REQ 0x00800000 -#define AR_BTCOEX_WL_LNADIV_ALLOWED_TX_ANTDIV_WL_TX_REQ_S 23 -#define AR_BTCOEX_WL_LNADIV_DISABLE_TX_ANTDIV_ENABLE 0x01000000 -#define AR_BTCOEX_WL_LNADIV_DISABLE_TX_ANTDIV_ENABLE_S 24 -#define AR_BTCOEX_WL_LNADIV_CONTINUOUS_BT_ACTIVE_PROTECT 0x02000000 -#define AR_BTCOEX_WL_LNADIV_CONTINUOUS_BT_ACTIVE_PROTECT_S 25 -#define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD 0xFC000000 -#define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD_S 26 - #endif /* AR9003_PHY_H */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h index 843e79f67ff2..fa9e0932769c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h @@ -58,6 +58,8 @@ static const u32 ar9565_1p0_mac_core[][2] = { {0x00008040, 0x00000000}, {0x00008044, 0x00000000}, {0x00008048, 0x00000000}, + {0x0000804c, 0xffffffff}, + {0x00008050, 0xffffffff}, {0x00008054, 0x00000000}, {0x00008058, 0x00000000}, {0x0000805c, 0x000fc78f}, @@ -244,7 +246,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = { {0x00009e50, 0x00ff03f1}, {0x00009e54, 0xe4c355c7}, {0x00009e5c, 0xe9198724}, - {0x00009fc0, 0x823e4fc8}, + {0x00009fc0, 0x823e4788}, {0x00009fc4, 0x0001efb5}, {0x00009fcc, 0x40000014}, {0x0000a20c, 0x00000000}, @@ -289,7 +291,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = { {0x0000a3ec, 0x20202020}, {0x0000a3f0, 0x00000000}, {0x0000a3f4, 0x00000006}, - {0x0000a3f8, 0x0c9bd380}, + {0x0000a3f8, 0x0cdbd380}, {0x0000a3fc, 0x000f0f01}, {0x0000a400, 0x8fa91f01}, {0x0000a404, 0x00000000}, @@ -353,11 +355,11 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, - {0x0000a204, 0x07318fc0, 0x07318fc4, 0x07318fc4, 0x07318fc0}, + {0x0000a204, 0x033187c0, 0x033187c4, 0x033187c4, 0x033187c0}, {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f}, {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, @@ -373,9 +375,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a288, 0x00100510, 0x00100510, 0x00100510, 0x00100510}, {0x0000a28c, 0x00021551, 0x00021551, 0x00021551, 0x00021551}, - {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982}, - {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, + {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -415,7 +417,7 @@ static const u32 ar9565_1p0_radio_core[][2] = { {0x00016144, 0x02084080}, {0x00016148, 0x000080c0}, {0x00016280, 0x050a0001}, - {0x00016284, 0x3d841440}, + {0x00016284, 0x3d841400}, {0x00016288, 0x00000000}, {0x0001628c, 0xe3000000}, {0x00016290, 0xa1004080}, @@ -838,27 +840,27 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = { {0x0000a0b4, 0x00000000}, {0x0000a0b8, 0x00000000}, {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x00bf00a0}, - {0x0000a0c4, 0x11a011a1}, - {0x0000a0c8, 0x11be11bf}, - {0x0000a0cc, 0x11bc11bd}, - {0x0000a0d0, 0x22632264}, - {0x0000a0d4, 0x22612262}, - {0x0000a0d8, 0x227f2260}, - {0x0000a0dc, 0x4322227e}, - {0x0000a0e0, 0x43204321}, - {0x0000a0e4, 0x433e433f}, - {0x0000a0e8, 0x4462433d}, - {0x0000a0ec, 0x44604461}, - {0x0000a0f0, 0x447e447f}, - {0x0000a0f4, 0x5582447d}, - {0x0000a0f8, 0x55805581}, - {0x0000a0fc, 0x559e559f}, - {0x0000a100, 0x66816682}, - {0x0000a104, 0x669f6680}, - {0x0000a108, 0x669d669e}, - {0x0000a10c, 0x77627763}, - {0x0000a110, 0x77607761}, + {0x0000a0c0, 0x301f3000}, + {0x0000a0c4, 0x41004101}, + {0x0000a0c8, 0x411e411f}, + {0x0000a0cc, 0x411c411d}, + {0x0000a0d0, 0x42434244}, + {0x0000a0d4, 0x42414242}, + {0x0000a0d8, 0x425f4240}, + {0x0000a0dc, 0x5342425e}, + {0x0000a0e0, 0x53405341}, + {0x0000a0e4, 0x535e535f}, + {0x0000a0e8, 0x7402535d}, + {0x0000a0ec, 0x74007401}, + {0x0000a0f0, 0x741e741f}, + {0x0000a0f4, 0x7522741d}, + {0x0000a0f8, 0x75207521}, + {0x0000a0fc, 0x753e753f}, + {0x0000a100, 0x76617662}, + {0x0000a104, 0x767f7660}, + {0x0000a108, 0x767d767e}, + {0x0000a10c, 0x77e277e3}, + {0x0000a110, 0x77e077e1}, {0x0000a114, 0x00000000}, {0x0000a118, 0x00000000}, {0x0000a11c, 0x00000000}, @@ -870,27 +872,27 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = { {0x0000a134, 0x00000000}, {0x0000a138, 0x00000000}, {0x0000a13c, 0x00000000}, - {0x0000a140, 0x00bf00a0}, - {0x0000a144, 0x11a011a1}, - {0x0000a148, 0x11be11bf}, - {0x0000a14c, 0x11bc11bd}, - {0x0000a150, 0x22632264}, - {0x0000a154, 0x22612262}, - {0x0000a158, 0x227f2260}, - {0x0000a15c, 0x4322227e}, - {0x0000a160, 0x43204321}, - {0x0000a164, 0x433e433f}, - {0x0000a168, 0x4462433d}, - {0x0000a16c, 0x44604461}, - {0x0000a170, 0x447e447f}, - {0x0000a174, 0x5582447d}, - {0x0000a178, 0x55805581}, - {0x0000a17c, 0x559e559f}, - {0x0000a180, 0x66816682}, - {0x0000a184, 0x669f6680}, - {0x0000a188, 0x669d669e}, - {0x0000a18c, 0x77627763}, - {0x0000a190, 0x77607761}, + {0x0000a140, 0x301f3000}, + {0x0000a144, 0x41004101}, + {0x0000a148, 0x411e411f}, + {0x0000a14c, 0x411c411d}, + {0x0000a150, 0x42434244}, + {0x0000a154, 0x42414242}, + {0x0000a158, 0x425f4240}, + {0x0000a15c, 0x5342425e}, + {0x0000a160, 0x53405341}, + {0x0000a164, 0x535e535f}, + {0x0000a168, 0x7402535d}, + {0x0000a16c, 0x74007401}, + {0x0000a170, 0x741e741f}, + {0x0000a174, 0x7522741d}, + {0x0000a178, 0x75207521}, + {0x0000a17c, 0x753e753f}, + {0x0000a180, 0x76617662}, + {0x0000a184, 0x767f7660}, + {0x0000a188, 0x767d767e}, + {0x0000a18c, 0x77e277e3}, + {0x0000a190, 0x77e077e1}, {0x0000a194, 0x00000000}, {0x0000a198, 0x00000000}, {0x0000a19c, 0x00000000}, diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index dfe6a4707fd2..96b8331ef9e7 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -173,8 +173,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) -#define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e)) - #define ATH_TX_COMPLETE_POLL_INT 1000 enum ATH_AGGR_STATUS { @@ -539,7 +537,6 @@ struct ath9k_wow_pattern { #ifdef CONFIG_MAC80211_LEDS void ath_init_leds(struct ath_softc *sc); void ath_deinit_leds(struct ath_softc *sc); -void ath_fill_led_pin(struct ath_softc *sc); #else static inline void ath_init_leds(struct ath_softc *sc) { @@ -548,9 +545,6 @@ static inline void ath_init_leds(struct ath_softc *sc) static inline void ath_deinit_leds(struct ath_softc *sc) { } -static inline void ath_fill_led_pin(struct ath_softc *sc) -{ -} #endif /*******************************/ @@ -602,6 +596,8 @@ struct ath_ant_comb { int main_conf; enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf; enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf; + int first_bias; + int second_bias; bool first_ratio; bool second_ratio; unsigned long scan_start_time; diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c index 419e9a3f2fed..acd437384fe4 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c @@ -43,8 +43,8 @@ static const u32 ar9003_wlan_weights[ATH_BTCOEX_STOMP_MAX] { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* STOMP_NONE */ }; -static const u32 mci_wlan_weights[ATH_BTCOEX_STOMP_MAX] - [AR9300_NUM_WLAN_WEIGHTS] = { +static const u32 ar9462_wlan_weights[ATH_BTCOEX_STOMP_MAX] + [AR9300_NUM_WLAN_WEIGHTS] = { { 0x01017d01, 0x41414101, 0x41414101, 0x41414141 }, /* STOMP_ALL */ { 0x01017d01, 0x3b3b3b01, 0x3b3b3b01, 0x3b3b3b3b }, /* STOMP_LOW */ { 0x01017d01, 0x01010101, 0x01010101, 0x01010101 }, /* STOMP_NONE */ @@ -208,37 +208,14 @@ static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah) AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); } -/* - * For AR9002, bt_weight/wlan_weight are used. - * For AR9003 and above, stomp_type is used. - */ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, u32 bt_weight, - u32 wlan_weight, - enum ath_stomp_type stomp_type) + u32 wlan_weight) { struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - if (AR_SREV_9300_20_OR_LATER(ah)) { - const u32 *weight = ar9003_wlan_weights[stomp_type]; - int i; - - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { - if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && - btcoex_hw->mci.stomp_ftp) - stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; - weight = mci_wlan_weights[stomp_type]; - } - - for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { - btcoex_hw->bt_weight[i] = AR9300_BT_WGHT; - btcoex_hw->wlan_weight[i] = weight[i]; - } - } else { - btcoex_hw->bt_coex_weights = - SM(bt_weight, AR_BTCOEX_BT_WGHT) | - SM(wlan_weight, AR_BTCOEX_WL_WGHT); - } + btcoex_hw->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) | + SM(wlan_weight, AR_BTCOEX_WL_WGHT); } EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); @@ -305,7 +282,7 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah) ath9k_hw_btcoex_enable_2wire(ah); break; case ATH_BTCOEX_CFG_3WIRE: - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { + if (AR_SREV_9462(ah)) { ath9k_hw_btcoex_enable_mci(ah); return; } @@ -327,7 +304,7 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) int i; btcoex_hw->enabled = false; - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { + if (AR_SREV_9462(ah)) { ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i), @@ -355,6 +332,26 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_btcoex_disable); +static void ar9003_btcoex_bt_stomp(struct ath_hw *ah, + enum ath_stomp_type stomp_type) +{ + struct ath_btcoex_hw *btcoex = &ah->btcoex_hw; + const u32 *weight = ar9003_wlan_weights[stomp_type]; + int i; + + if (AR_SREV_9462(ah)) { + if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && + btcoex->mci.stomp_ftp) + stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; + weight = ar9462_wlan_weights[stomp_type]; + } + + for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { + btcoex->bt_weight[i] = AR9300_BT_WGHT; + btcoex->wlan_weight[i] = weight[i]; + } +} + /* * Configures appropriate weight based on stomp type. */ @@ -362,22 +359,22 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, enum ath_stomp_type stomp_type) { if (AR_SREV_9300_20_OR_LATER(ah)) { - ath9k_hw_btcoex_set_weight(ah, 0, 0, stomp_type); + ar9003_btcoex_bt_stomp(ah, stomp_type); return; } switch (stomp_type) { case ATH_BTCOEX_STOMP_ALL: ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_ALL_WLAN_WGHT, 0); + AR_STOMP_ALL_WLAN_WGHT); break; case ATH_BTCOEX_STOMP_LOW: ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT, 0); + AR_STOMP_LOW_WLAN_WGHT); break; case ATH_BTCOEX_STOMP_NONE: ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_NONE_WLAN_WGHT, 0); + AR_STOMP_NONE_WLAN_WGHT); break; default: ath_dbg(ath9k_hw_common(ah), BTCOEX, "Invalid Stomptype\n"); diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h index 385197ad79b0..20092f98658f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h @@ -107,8 +107,7 @@ void ath9k_hw_btcoex_init_mci(struct ath_hw *ah); void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, u32 bt_weight, - u32 wlan_weight, - enum ath_stomp_type stomp_type); + u32 wlan_weight); void ath9k_hw_btcoex_disable(struct ath_hw *ah); void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, enum ath_stomp_type stomp_type); diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index 6727b566d294..ab3bc85a1f8a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -222,57 +222,6 @@ static const struct file_operations fops_disable_ani = { .llseek = default_llseek, }; -static ssize_t read_file_ant_diversity(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - char buf[32]; - unsigned int len; - - len = sprintf(buf, "%d\n", common->antenna_diversity); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_ant_diversity(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - unsigned long antenna_diversity; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - if (!AR_SREV_9565(sc->sc_ah)) - goto exit; - - buf[len] = '\0'; - if (strict_strtoul(buf, 0, &antenna_diversity)) - return -EINVAL; - - common->antenna_diversity = !!antenna_diversity; - ath9k_ps_wakeup(sc); - ath_ant_comb_update(sc); - ath_dbg(common, CONFIG, "Antenna diversity: %d\n", - common->antenna_diversity); - ath9k_ps_restore(sc); -exit: - return count; -} - -static const struct file_operations fops_ant_diversity = { - .read = read_file_ant_diversity, - .write = write_file_ant_diversity, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - static ssize_t read_file_dma(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1631,8 +1580,6 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy, sc, &fops_tx_chainmask); debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_disable_ani); - debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - &sc->sc_ah->config.enable_paprd); debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_regidx); debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, @@ -1652,12 +1599,12 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_samps); #endif + debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); + debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); - debugfs_create_file("diversity", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_ant_diversity); return 0; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/gpio.c b/trunk/drivers/net/wireless/ath/ath9k/gpio.c index d9ed141a053e..45f24220b16e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/gpio.c @@ -44,6 +44,25 @@ void ath_init_leds(struct ath_softc *sc) if (AR_SREV_9100(sc->sc_ah)) return; + if (sc->sc_ah->led_pin < 0) { + if (AR_SREV_9287(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9287; + else if (AR_SREV_9485(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9485; + else if (AR_SREV_9300(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9300; + else if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9462; + else + sc->sc_ah->led_pin = ATH_LED_PIN_DEF; + } + + /* Configure gpio 1 for output */ + ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + /* LED off, active low */ + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); + if (!led_blink) sc->led_cdev.default_trigger = ieee80211_get_radio_led_name(sc->hw); @@ -59,31 +78,6 @@ void ath_init_leds(struct ath_softc *sc) sc->led_registered = true; } - -void ath_fill_led_pin(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - - if (AR_SREV_9100(ah) || (ah->led_pin >= 0)) - return; - - if (AR_SREV_9287(ah)) - ah->led_pin = ATH_LED_PIN_9287; - else if (AR_SREV_9485(sc->sc_ah)) - ah->led_pin = ATH_LED_PIN_9485; - else if (AR_SREV_9300(sc->sc_ah)) - ah->led_pin = ATH_LED_PIN_9300; - else if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah)) - ah->led_pin = ATH_LED_PIN_9462; - else - ah->led_pin = ATH_LED_PIN_DEF; - - /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - - /* LED off, active low */ - ath9k_hw_set_gpio(ah, ah->led_pin, 1); -} #endif /*******************/ @@ -320,10 +314,8 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n"); /* make sure duty cycle timer is also stopped when resuming */ - if (btcoex->hw_timer_enabled) { + if (btcoex->hw_timer_enabled) ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); - btcoex->hw_timer_enabled = false; - } btcoex->bt_priority_cnt = 0; btcoex->bt_priority_time = jiffies; @@ -344,20 +336,18 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc) del_timer_sync(&btcoex->period_timer); - if (btcoex->hw_timer_enabled) { + if (btcoex->hw_timer_enabled) ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); - btcoex->hw_timer_enabled = false; - } + + btcoex->hw_timer_enabled = false; } void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) { struct ath_btcoex *btcoex = &sc->btcoex; - if (btcoex->hw_timer_enabled) { + if (btcoex->hw_timer_enabled) ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); - btcoex->hw_timer_enabled = false; - } } u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) @@ -395,10 +385,7 @@ void ath9k_start_btcoex(struct ath_softc *sc) !ah->btcoex_hw.enabled) { if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT, 0); - else - ath9k_hw_btcoex_set_weight(ah, 0, 0, - ATH_BTCOEX_STOMP_NONE); + AR_STOMP_LOW_WLAN_WGHT); ath9k_hw_btcoex_enable(ah); if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) @@ -415,7 +402,7 @@ void ath9k_stop_btcoex(struct ath_softc *sc) if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) ath9k_btcoex_timer_pause(sc); ath9k_hw_btcoex_disable(ah); - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + if (AR_SREV_9462(ah)) ath_mci_flush_profile(&sc->btcoex.mci); } } diff --git a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c index 924c4616c3d9..ee6e50aebf8d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1072,15 +1072,14 @@ static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) */ static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev) { - struct device *dev = &hif_dev->udev->dev; - struct device *parent = dev->parent; + struct device *parent = hif_dev->udev->dev.parent; complete(&hif_dev->fw_done); if (parent) device_lock(parent); - device_release_driver(dev); + device_release_driver(&hif_dev->udev->dev); if (parent) device_unlock(parent); diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 0eacfc13c915..8fd64a6f0eb9 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -161,7 +161,7 @@ void ath9k_htc_start_btcoex(struct ath9k_htc_priv *priv) if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) { ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT, 0); + AR_STOMP_LOW_WLAN_WGHT); ath9k_hw_btcoex_enable(ah); ath_htc_resume_btcoex_work(priv); } diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c index ca78e33ca23e..61d096e3596f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1445,7 +1445,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; if (priv->ah->sw_mgmt_crypto && key->cipher == WLAN_CIPHER_SUITE_CCMP) - key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; ret = 0; } break; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h b/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h index 0f2b97f6b739..265bf77598a2 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -78,13 +78,6 @@ static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); } -static inline void ath9k_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah, - bool enable) -{ - if (ath9k_hw_ops(ah)->antctrl_shared_chain_lnadiv) - ath9k_hw_ops(ah)->antctrl_shared_chain_lnadiv(ah, enable); -} - /* Private hardware call ops */ /* PHY ops */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index f9a6ec5cf470..99cab44d2312 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -24,7 +24,6 @@ #include "rc.h" #include "ar9003_mac.h" #include "ar9003_mci.h" -#include "ar9003_phy.h" #include "debug.h" #include "ath9k.h" @@ -1734,12 +1733,12 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) if (!ret) goto fail; - if (ath9k_hw_mci_is_enabled(ah)) - ar9003_mci_2g5g_switch(ah, false); - ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_start_nfcal(ah, true); + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_2g5g_switch(ah, false); + if (AR_SREV_9271(ah)) ar9002_hw_load_ani_reg(ah, chan); @@ -2026,9 +2025,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_apply_gpio_override(ah); - if (AR_SREV_9565(ah) && ah->shared_chain_lnadiv) - REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); - return 0; } EXPORT_SYMBOL(ath9k_hw_reset); @@ -2511,6 +2507,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rx_status_len = sizeof(struct ar9003_rxs); pCap->tx_desc_len = sizeof(struct ar9003_txc); pCap->txs_len = sizeof(struct ar9003_txs); + if (!ah->config.paprd_disable && + ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && + !AR_SREV_9462(ah)) + pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; } else { pCap->tx_desc_len = sizeof(struct ath_desc); if (AR_SREV_9280_20(ah)) @@ -2539,7 +2539,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) } - if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) { + if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) { ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); /* * enable the diversity-combining algorithm only when diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index 566a4ce4f156..0d17ce0b0ff4 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -237,6 +237,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_LDPC = BIT(6), ATH9K_HW_CAP_FASTCLOCK = BIT(7), ATH9K_HW_CAP_SGI_20 = BIT(8), + ATH9K_HW_CAP_PAPRD = BIT(9), ATH9K_HW_CAP_ANT_DIV_COMB = BIT(10), ATH9K_HW_CAP_2GHZ = BIT(11), ATH9K_HW_CAP_5GHZ = BIT(12), @@ -287,12 +288,12 @@ struct ath9k_ops_config { u8 pcie_clock_req; u32 pcie_waen; u8 analog_shiftreg; + u8 paprd_disable; u32 ofdm_trig_low; u32 ofdm_trig_high; u32 cck_trig_high; u32 cck_trig_low; u32 enable_ani; - u32 enable_paprd; int serialize_regmode; bool rx_intr_mitigation; bool tx_intr_mitigation; @@ -686,7 +687,7 @@ struct ath_hw_ops { struct ath_hw_antcomb_conf *antconf); void (*antdiv_comb_conf_set)(struct ath_hw *ah, struct ath_hw_antcomb_conf *antconf); - void (*antctrl_shared_chain_lnadiv)(struct ath_hw *hw, bool enable); + }; struct ath_nf_limits { @@ -730,7 +731,6 @@ struct ath_hw { bool aspm_enabled; bool is_monitoring; bool need_an_top2_fixup; - bool shared_chain_lnadiv; u16 tx_trig_level; u32 nf_regs[6]; diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c index fad3ccd5cd91..f3ce5ca2f1d3 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/init.c @@ -46,10 +46,6 @@ static int ath9k_btcoex_enable; module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); -static int ath9k_enable_diversity; -module_param_named(enable_diversity, ath9k_enable_diversity, int, 0444); -MODULE_PARM_DESC(enable_diversity, "Enable Antenna diversity for AR9565"); - bool is_ath9k_unloaded; /* We use the hw_value as an index into our private channel structure */ @@ -550,14 +546,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, common->debug_mask = ath9k_debug; common->btcoex_enabled = ath9k_btcoex_enable == 1; common->disable_ani = false; - - /* - * Enable Antenna diversity only when BTCOEX is disabled - * and the user manually requests the feature. - */ - if (!common->btcoex_enabled && ath9k_enable_diversity) - common->antenna_diversity = 1; - spin_lock_init(&common->cc_lock); spin_lock_init(&sc->sc_serial_rw); @@ -609,7 +597,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, ath9k_cmn_init_crypto(sc->sc_ah); ath9k_init_misc(sc); - ath_fill_led_pin(sc); if (common->bus_ops->aspm_init) common->bus_ops->aspm_init(common); diff --git a/trunk/drivers/net/wireless/ath/ath9k/link.c b/trunk/drivers/net/wireless/ath/ath9k/link.c index 7b88b9c39ccd..825a29cc9313 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/link.c +++ b/trunk/drivers/net/wireless/ath/ath9k/link.c @@ -423,7 +423,7 @@ void ath_ani_calibrate(unsigned long data) cal_interval = min(cal_interval, (u32)short_cal_interval); mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); - if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && ah->caldata) { + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { if (!ah->caldata->paprd_done) ieee80211_queue_work(sc->hw, &sc->paprd_work); else if (!ah->paprd_table_write_done) diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 31ab82e3ba85..3923ad933aef 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -1406,7 +1406,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; if (sc->sc_ah->sw_mgmt_crypto && key->cipher == WLAN_CIPHER_SUITE_CCMP) - key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; ret = 0; } break; diff --git a/trunk/drivers/net/wireless/ath/ath9k/mci.c b/trunk/drivers/net/wireless/ath/ath9k/mci.c index ec2d7c807567..8f0e8d9c2054 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mci.c @@ -80,7 +80,6 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci) struct ath_mci_profile_info *info, *tinfo; mci->aggr_limit = 0; - mci->num_mgmt = 0; if (list_empty(&mci->info)) return; @@ -121,14 +120,7 @@ static void ath_mci_update_scheme(struct ath_softc *sc) if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING) goto skip_tuning; - mci->aggr_limit = 0; btcoex->duty_cycle = ath_mci_duty_cycle[num_profile]; - btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD; - if (NUM_PROF(mci)) - btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; - else - btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL : - ATH_BTCOEX_STOMP_LOW; if (num_profile == 1) { info = list_first_entry(&mci->info, @@ -140,8 +132,7 @@ static void ath_mci_update_scheme(struct ath_softc *sc) else if (info->T == 6) { mci->aggr_limit = 6; btcoex->duty_cycle = 30; - } else - mci->aggr_limit = 6; + } ath_dbg(common, MCI, "Single SCO, aggregation limit %d 1/4 ms\n", mci->aggr_limit); @@ -250,8 +241,8 @@ static void ath9k_mci_work(struct work_struct *work) ath_mci_update_scheme(sc); } -static u8 ath_mci_process_profile(struct ath_softc *sc, - struct ath_mci_profile_info *info) +static void ath_mci_process_profile(struct ath_softc *sc, + struct ath_mci_profile_info *info) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_btcoex *btcoex = &sc->btcoex; @@ -277,15 +268,25 @@ static u8 ath_mci_process_profile(struct ath_softc *sc, if (info->start) { if (!entry && !ath_mci_add_profile(common, mci, info)) - return 0; + return; } else ath_mci_del_profile(common, mci, entry); - return 1; + btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD; + mci->aggr_limit = mci->num_sco ? 6 : 0; + + btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)]; + if (NUM_PROF(mci)) + btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; + else + btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL : + ATH_BTCOEX_STOMP_LOW; + + ieee80211_queue_work(sc->hw, &sc->mci_work); } -static u8 ath_mci_process_status(struct ath_softc *sc, - struct ath_mci_profile_status *status) +static void ath_mci_process_status(struct ath_softc *sc, + struct ath_mci_profile_status *status) { struct ath_btcoex *btcoex = &sc->btcoex; struct ath_mci_profile *mci = &btcoex->mci; @@ -294,14 +295,14 @@ static u8 ath_mci_process_status(struct ath_softc *sc, /* Link status type are not handled */ if (status->is_link) - return 0; + return; info.conn_handle = status->conn_handle; if (ath_mci_find_profile(mci, &info)) - return 0; + return; if (status->conn_handle >= ATH_MCI_MAX_PROFILE) - return 0; + return; if (status->is_critical) __set_bit(status->conn_handle, mci->status); @@ -315,9 +316,7 @@ static u8 ath_mci_process_status(struct ath_softc *sc, } while (++i < ATH_MCI_MAX_PROFILE); if (old_num_mgmt != mci->num_mgmt) - return 1; - - return 0; + ieee80211_queue_work(sc->hw, &sc->mci_work); } static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) @@ -326,16 +325,9 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) struct ath_mci_profile_info profile_info; struct ath_mci_profile_status profile_status; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - u8 major, minor, update_scheme = 0; + u8 major, minor; u32 seq_num; - if (ar9003_mci_state(ah, MCI_STATE_NEED_FLUSH_BT_INFO) && - ar9003_mci_state(ah, MCI_STATE_ENABLE)) { - ath_dbg(common, MCI, "(MCI) Need to flush BT profiles\n"); - ath_mci_flush_profile(&sc->btcoex.mci); - ar9003_mci_state(ah, MCI_STATE_SEND_STATUS_QUERY); - } - switch (opcode) { case MCI_GPM_COEX_VERSION_QUERY: ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION); @@ -361,7 +353,7 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) break; } - update_scheme += ath_mci_process_profile(sc, &profile_info); + ath_mci_process_profile(sc, &profile_info); break; case MCI_GPM_COEX_BT_STATUS_UPDATE: profile_status.is_link = *(rx_payload + @@ -377,14 +369,12 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) profile_status.is_link, profile_status.conn_handle, profile_status.is_critical, seq_num); - update_scheme += ath_mci_process_status(sc, &profile_status); + ath_mci_process_status(sc, &profile_status); break; default: ath_dbg(common, MCI, "Unknown GPM COEX message = 0x%02x\n", opcode); break; } - if (update_scheme) - ieee80211_queue_work(sc->hw, &sc->mci_work); } int ath_mci_setup(struct ath_softc *sc) @@ -392,7 +382,6 @@ int ath_mci_setup(struct ath_softc *sc) struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_mci_coex *mci = &sc->mci_coex; struct ath_mci_buf *buf = &mci->sched_buf; - int ret; buf->bf_addr = dma_alloc_coherent(sc->dev, ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE, @@ -412,13 +401,9 @@ int ath_mci_setup(struct ath_softc *sc) mci->gpm_buf.bf_addr = (u8 *)mci->sched_buf.bf_addr + mci->sched_buf.bf_len; mci->gpm_buf.bf_paddr = mci->sched_buf.bf_paddr + mci->sched_buf.bf_len; - ret = ar9003_mci_setup(sc->sc_ah, mci->gpm_buf.bf_paddr, - mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4), - mci->sched_buf.bf_paddr); - if (ret) { - ath_err(common, "Failed to initialize MCI\n"); - return ret; - } + ar9003_mci_setup(sc->sc_ah, mci->gpm_buf.bf_paddr, + mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4), + mci->sched_buf.bf_paddr); INIT_WORK(&sc->mci_work, ath9k_mci_work); ath_dbg(common, MCI, "MCI Initialized\n"); @@ -583,11 +568,9 @@ void ath_mci_intr(struct ath_softc *sc) } if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) || - (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) { + (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR | AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT); - ath_mci_msg(sc, MCI_GPM_COEX_NOOP, NULL); - } } void ath_mci_enable(struct ath_softc *sc) diff --git a/trunk/drivers/net/wireless/ath/ath9k/pci.c b/trunk/drivers/net/wireless/ath/ath9k/pci.c index c0c599673eeb..a8f6126f6b2d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/pci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/pci.c @@ -128,9 +128,8 @@ static void ath_pci_aspm_init(struct ath_common *common) if (!parent) return; - if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) && - (AR_SREV_9285(ah))) { - /* Bluetooth coexistance requires disabling ASPM for AR9285. */ + if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { + /* Bluetooth coexistance requires disabling ASPM. */ pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); diff --git a/trunk/drivers/net/wireless/ath/ath9k/rc.c b/trunk/drivers/net/wireless/ath/ath9k/rc.c index 27ed80b54881..4b12c347d188 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/rc.c +++ b/trunk/drivers/net/wireless/ath/ath9k/rc.c @@ -1222,14 +1222,11 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta) caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG; else if (sta->ht_cap.mcs.rx_mask[1]) caps |= WLAN_RC_DS_FLAG; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) caps |= WLAN_RC_40_FLAG; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) - caps |= WLAN_RC_SGI_FLAG; - } else { - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) - caps |= WLAN_RC_SGI_FLAG; - } + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40 || + sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + caps |= WLAN_RC_SGI_FLAG; } return caps; diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index 83d16e7ed272..4480c0cc655f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -424,8 +424,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc) rfilt |= ATH9K_RX_FILTER_COMP_BAR; if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) { - /* This is needed for older chips */ - if (sc->sc_ah->hw_version.macVersion <= AR_SREV_VERSION_9160) + /* The following may also be needed for other older chips */ + if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) rfilt |= ATH9K_RX_FILTER_PROM; rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/wow.c b/trunk/drivers/net/wireless/ath/ath9k/wow.c index a483d518758c..44a08eb53c62 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/wow.c +++ b/trunk/drivers/net/wireless/ath/ath9k/wow.c @@ -497,7 +497,7 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { + if (AR_SREV_9462(ah)) { /* * this is needed to prevent the chip waking up * the host within 3-4 seconds with certain diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index 36618e3a5e60..b088fa0eb022 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -1820,14 +1820,10 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) { struct ath_hw *ah = sc->sc_ah; struct ath9k_channel *curchan = ah->curchan; - if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (curchan->channelFlags & CHANNEL_5GHZ) && (chainmask == 0x7) && (rate < 0x90)) return 0x3; - else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) && - IS_CCK_RATE(rate)) - return 0x2; else return chainmask; } diff --git a/trunk/drivers/net/wireless/ath/carl9170/mac.c b/trunk/drivers/net/wireless/ath/carl9170/mac.c index e3b1b6e87760..f8676280dc36 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/mac.c +++ b/trunk/drivers/net/wireless/ath/carl9170/mac.c @@ -304,8 +304,7 @@ int carl9170_set_operating_mode(struct ar9170 *ar) struct ath_common *common = &ar->common; u8 *mac_addr, *bssid; u32 cam_mode = AR9170_MAC_CAM_DEFAULTS; - u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS | - AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE; + u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS; u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG | AR9170_MAC_RX_CTRL_SHORT_FILTER; u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS; diff --git a/trunk/drivers/net/wireless/ath/carl9170/main.c b/trunk/drivers/net/wireless/ath/carl9170/main.c index 67997b39aba7..18554ab76733 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/main.c +++ b/trunk/drivers/net/wireless/ath/carl9170/main.c @@ -1149,7 +1149,6 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; case WLAN_CIPHER_SUITE_CCMP: ktype = AR9170_ENC_ALG_AESCCMP; - key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; break; default: return -EOPNOTSUPP; @@ -1781,7 +1780,6 @@ void *carl9170_alloc(size_t priv_size) hw->wiphy->interface_modes = 0; hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | diff --git a/trunk/drivers/net/wireless/b43legacy/main.c b/trunk/drivers/net/wireless/b43legacy/main.c index 18e208e3eca1..291cdf654088 100644 --- a/trunk/drivers/net/wireless/b43legacy/main.c +++ b/trunk/drivers/net/wireless/b43legacy/main.c @@ -3895,8 +3895,6 @@ static void b43legacy_remove(struct ssb_device *dev) cancel_work_sync(&wl->firmware_load); B43legacy_WARN_ON(!wl); - if (!wldev->fw.ucode) - return; /* NULL if fw never loaded */ if (wl->current_dev == wldev) ieee80211_unregister_hw(wl->hw); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 3b2c4c20e7fc..8e7e6928c936 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -185,7 +185,7 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) return err; } -int +static int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, void *data, bool write) { @@ -249,9 +249,7 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) int retval; brcmf_dbg(INFO, "addr:0x%08x\n", addr); - sdio_claim_host(sdiodev->func[1]); retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); - sdio_release_host(sdiodev->func[1]); brcmf_dbg(INFO, "data:0x%02x\n", data); if (ret) @@ -266,9 +264,7 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) int retval; brcmf_dbg(INFO, "addr:0x%08x\n", addr); - sdio_claim_host(sdiodev->func[1]); retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); - sdio_release_host(sdiodev->func[1]); brcmf_dbg(INFO, "data:0x%08x\n", data); if (ret) @@ -283,9 +279,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, int retval; brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data); - sdio_claim_host(sdiodev->func[1]); retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); - sdio_release_host(sdiodev->func[1]); if (ret) *ret = retval; @@ -297,9 +291,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, int retval; brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data); - sdio_claim_host(sdiodev->func[1]); retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); - sdio_release_host(sdiodev->func[1]); if (ret) *ret = retval; @@ -364,20 +356,15 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, pkt->len); - sdio_claim_host(sdiodev->func[1]); - width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); if (err) - goto done; + return err; incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, fn, addr, pkt); -done: - sdio_release_host(sdiodev->func[1]); - return err; } @@ -391,20 +378,15 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, pktq->qlen); - sdio_claim_host(sdiodev->func[1]); - width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); if (err) - goto done; + return err; incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr, pktq); -done: - sdio_release_host(sdiodev->func[1]); - return err; } @@ -446,12 +428,10 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, if (flags & SDIO_REQ_ASYNC) return -ENOTSUPP; - sdio_claim_host(sdiodev->func[1]); - if (bar0 != sdiodev->sbwad) { err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); if (err) - goto done; + return err; sdiodev->sbwad = bar0; } @@ -463,13 +443,8 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, if (width == 4) addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, - addr, pkt); - -done: - sdio_release_host(sdiodev->func[1]); - - return err; + return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, + addr, pkt); } int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, @@ -510,10 +485,8 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) brcmf_dbg(TRACE, "Enter\n"); /* issue abort cmd52 command through F0 */ - sdio_claim_host(sdiodev->func[1]); brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT, &t_func); - sdio_release_host(sdiodev->func[1]); brcmf_dbg(TRACE, "Exit\n"); return 0; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index c3247d5b3c22..e0b313c7f5ce 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -103,6 +103,7 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, if (regaddr == SDIO_CCCR_IOEx) { sdfunc = sdiodev->func[2]; if (sdfunc) { + sdio_claim_host(sdfunc); if (*byte & SDIO_FUNC_ENABLE_2) { /* Enable Function 2 */ err_ret = sdio_enable_func(sdfunc); @@ -118,6 +119,7 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, "Disable F2 failed:%d\n", err_ret); } + sdio_release_host(sdfunc); } } else if ((regaddr == SDIO_CCCR_ABORT) || (regaddr == SDIO_CCCR_IENx)) { @@ -126,13 +128,17 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, if (!sdfunc) return -ENOMEM; sdfunc->num = 0; + sdio_claim_host(sdfunc); sdio_writeb(sdfunc, *byte, regaddr, &err_ret); + sdio_release_host(sdfunc); kfree(sdfunc); } else if (regaddr < 0xF0) { brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); err_ret = -EPERM; } else { + sdio_claim_host(sdfunc); sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); + sdio_release_host(sdfunc); } return err_ret; @@ -153,6 +159,7 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, /* handle F0 separately */ err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); } else { + sdio_claim_host(sdiodev->func[func]); if (rw) /* CMD52 Write */ sdio_writeb(sdiodev->func[func], *byte, regaddr, &err_ret); @@ -163,6 +170,7 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, *byte = sdio_readb(sdiodev->func[func], regaddr, &err_ret); } + sdio_release_host(sdiodev->func[func]); } if (err_ret) @@ -189,6 +197,8 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); if (brcmf_pm_resume_error(sdiodev)) return -EIO; + /* Claim host controller */ + sdio_claim_host(sdiodev->func[func]); if (rw) { /* CMD52 Write */ if (nbytes == 4) @@ -209,6 +219,9 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); } + /* Release host controller */ + sdio_release_host(sdiodev->func[func]); + if (err_ret) brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n", rw ? "write" : "read", err_ret); @@ -262,6 +275,9 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, if (brcmf_pm_resume_error(sdiodev)) return -EIO; + /* Claim host controller */ + sdio_claim_host(sdiodev->func[func]); + skb_queue_walk(pktq, pkt) { uint pkt_len = pkt->len; pkt_len += 3; @@ -284,6 +300,9 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, SGCount++; } + /* Release host controller */ + sdio_release_host(sdiodev->func[func]); + brcmf_dbg(TRACE, "Exit\n"); return err_ret; } @@ -309,6 +328,9 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, if (brcmf_pm_resume_error(sdiodev)) return -EIO; + /* Claim host controller */ + sdio_claim_host(sdiodev->func[func]); + pkt_len += 3; pkt_len &= (uint)~3; @@ -322,6 +344,9 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, write ? "TX" : "RX", pkt, addr, pkt_len); } + /* Release host controller */ + sdio_release_host(sdiodev->func[func]); + return status; } @@ -615,8 +640,6 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev) oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq), GFP_KERNEL); - if (!oobirq_entry) - return -ENOMEM; oobirq_entry->irq = res->start; oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK; list_add_tail(&oobirq_entry->list, &oobirq_lh); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 17e7ae73e008..4766d9f35696 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -27,7 +27,6 @@ * IO codes that are interpreted by dongle firmware ******************************************************************************/ #define BRCMF_C_UP 2 -#define BRCMF_C_DOWN 3 #define BRCMF_C_SET_PROMISC 10 #define BRCMF_C_GET_RATE 12 #define BRCMF_C_GET_INFRA 19 @@ -51,10 +50,7 @@ #define BRCMF_C_REASSOC 53 #define BRCMF_C_SET_ROAM_TRIGGER 55 #define BRCMF_C_SET_ROAM_DELTA 57 -#define BRCMF_C_GET_BCNPRD 75 -#define BRCMF_C_SET_BCNPRD 76 #define BRCMF_C_GET_DTIMPRD 77 -#define BRCMF_C_SET_DTIMPRD 78 #define BRCMF_C_SET_COUNTRY 84 #define BRCMF_C_GET_PM 85 #define BRCMF_C_SET_PM 86 @@ -138,9 +134,6 @@ #define WLC_BSS_RSSI_ON_CHANNEL 0x0002 -#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */ -#define BRCMF_STA_ASSOC 0x10 /* Associated */ - struct brcmf_event_msg { __be16 version; __be16 flags; @@ -573,28 +566,6 @@ struct brcmf_channel_info_le { __le32 scan_channel; }; -struct brcmf_sta_info_le { - __le16 ver; /* version of this struct */ - __le16 len; /* length in bytes of this structure */ - __le16 cap; /* sta's advertised capabilities */ - __le32 flags; /* flags defined below */ - __le32 idle; /* time since data pkt rx'd from sta */ - u8 ea[ETH_ALEN]; /* Station address */ - __le32 count; /* # rates in this set */ - u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ - /* w/hi bit set if basic */ - __le32 in; /* seconds elapsed since associated */ - __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ - __le32 tx_pkts; /* # of packets transmitted */ - __le32 tx_failures; /* # of packets failed */ - __le32 rx_ucast_pkts; /* # of unicast packets received */ - __le32 rx_mcast_pkts; /* # of multicast packets received */ - __le32 tx_rate; /* Rate of last successful tx frame */ - __le32 rx_rate; /* Rate of last successful rx frame */ - __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ - __le32 rx_decrypt_failures; /* # of packet decrypted failed */ -}; - /* Bus independent dongle command */ struct brcmf_dcmd { uint cmd; /* common dongle cmd definition */ @@ -614,7 +585,7 @@ struct brcmf_pub { /* Linkage ponters */ struct brcmf_bus *bus_if; struct brcmf_proto *prot; - struct brcmf_cfg80211_info *config; + struct brcmf_cfg80211_dev *config; struct device *dev; /* fullmac dongle device pointer */ /* Internal brcmf items */ @@ -687,8 +658,6 @@ extern const struct bcmevent_name bcmevent_names[]; extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); -extern uint brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen, - char *buf, uint buflen, s32 bssidx); extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); @@ -713,6 +682,10 @@ extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx, extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx); +/* Send packet to dongle via data channel */ +extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\ + struct sk_buff *pkt); + extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg); extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable, int master_mode); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 15c5db5752d1..f6b862d77986 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -80,60 +80,12 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) strncpy(buf, name, buflen); /* append data onto the end of the name string */ - if (data && datalen) { - memcpy(&buf[len], data, datalen); - len += datalen; - } + memcpy(&buf[len], data, datalen); + len += datalen; return len; } -uint -brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen, - char *buf, uint buflen, s32 bssidx) -{ - const s8 *prefix = "bsscfg:"; - s8 *p; - u32 prefixlen; - u32 namelen; - u32 iolen; - __le32 bssidx_le; - - if (bssidx == 0) - return brcmf_c_mkiovar(name, data, datalen, buf, buflen); - - prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */ - namelen = (u32) strlen(name) + 1; /* lengh of iovar name + null */ - iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen; - - if (buflen < 0 || iolen > (u32)buflen) { - brcmf_dbg(ERROR, "buffer is too short\n"); - return 0; - } - - p = buf; - - /* copy prefix, no null */ - memcpy(p, prefix, prefixlen); - p += prefixlen; - - /* copy iovar name including null */ - memcpy(p, name, namelen); - p += namelen; - - /* bss config index as first data */ - bssidx_le = cpu_to_le32(bssidx); - memcpy(p, &bssidx_le, sizeof(bssidx_le)); - p += sizeof(bssidx_le); - - /* parameter buffer follows */ - if (datalen) - memcpy(p, data, datalen); - - return iolen; - -} - bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, int prec) { @@ -479,7 +431,13 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) } /* show any appended data */ - brcmf_dbg_hex_dump(datalen, event_data, datalen, "Received data"); + if (datalen) { + buf = (unsigned char *) event_data; + brcmf_dbg(EVENT, " data (%d) : ", datalen); + for (i = 0; i < datalen; i++) + brcmf_dbg(EVENT, " 0x%02x ", *buf++); + brcmf_dbg(EVENT, "\n"); + } } #endif /* DEBUG */ @@ -570,9 +528,8 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata, } #ifdef DEBUG - if (BRCMF_EVENT_ON()) - brcmf_c_show_host_event(event, event_data); -#endif /* DEBUG */ + brcmf_c_show_host_event(event, event_data); +#endif /* DEBUG */ return 0; } @@ -813,11 +770,8 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) { char iovbuf[32]; int retcode; - __le32 arp_mode_le; - arp_mode_le = cpu_to_le32(arp_mode); - brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf, - sizeof(iovbuf)); + brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); retcode = retcode >= 0 ? 0 : retcode; @@ -833,11 +787,8 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) { char iovbuf[32]; int retcode; - __le32 arp_enable_le; - - arp_enable_le = cpu_to_le32(arp_enable); - brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4, + brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf)); retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -855,10 +806,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ char buf[128], *ptr; - __le32 roaming_le = cpu_to_le32(1); - __le32 bcn_timeout_le = cpu_to_le32(3); - __le32 scan_assoc_time_le = cpu_to_le32(40); - __le32 scan_unassoc_time_le = cpu_to_le32(40); + u32 roaming = 1; + uint bcn_timeout = 3; + int scan_assoc_time = 40; + int scan_unassoc_time = 40; int i; struct brcmf_bus_dcmd *cmdlst; struct list_head *cur, *q; @@ -884,14 +835,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) /* Setup timeout if Beacons are lost and roam is off to report link down */ - brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf, + brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */ - brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4, + brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -903,9 +854,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, - (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le)); + (char *)&scan_assoc_time, sizeof(scan_assoc_time)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, - (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le)); + (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); /* Set and enable ARP offload feature */ brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index fb508c2256dd..b784920532d3 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h @@ -55,7 +55,6 @@ do { \ #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) #define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) -#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) #else /* (defined DEBUG) || (defined DEBUG) */ @@ -66,7 +65,6 @@ do { \ #define BRCMF_HDRS_ON() 0 #define BRCMF_BYTES_ON() 0 #define BRCMF_GLOM_ON() 0 -#define BRCMF_EVENT_ON() 0 #endif /* defined(DEBUG) */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index d7c76ce9d8cb..b08f3474d8e7 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -272,6 +272,30 @@ static void brcmf_netdev_set_multicast_list(struct net_device *ndev) schedule_work(&drvr->multicast_work); } +int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) +{ + /* Reject if down */ + if (!drvr->bus_if->drvr_up || (drvr->bus_if->state == BRCMF_BUS_DOWN)) + return -ENODEV; + + /* Update multicast statistic */ + if (pktbuf->len >= ETH_ALEN) { + u8 *pktdata = (u8 *) (pktbuf->data); + struct ethhdr *eh = (struct ethhdr *)pktdata; + + if (is_multicast_ether_addr(eh->h_dest)) + drvr->tx_multicast++; + if (ntohs(eh->h_proto) == ETH_P_PAE) + atomic_inc(&drvr->pend_8021x_cnt); + } + + /* If the protocol uses a data header, apply it */ + brcmf_proto_hdrpush(drvr, ifidx, pktbuf); + + /* Use bus module to send data frame */ + return drvr->bus_if->brcmf_bus_txdata(drvr->dev, pktbuf); +} + static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) { int ret; @@ -314,22 +338,7 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) } } - /* Update multicast statistic */ - if (skb->len >= ETH_ALEN) { - u8 *pktdata = (u8 *)(skb->data); - struct ethhdr *eh = (struct ethhdr *)pktdata; - - if (is_multicast_ether_addr(eh->h_dest)) - drvr->tx_multicast++; - if (ntohs(eh->h_proto) == ETH_P_PAE) - atomic_inc(&drvr->pend_8021x_cnt); - } - - /* If the protocol uses a data header, apply it */ - brcmf_proto_hdrpush(drvr, ifp->idx, skb); - - /* Use bus module to send data frame */ - ret = drvr->bus_if->brcmf_bus_txdata(drvr->dev, skb); + ret = brcmf_sendpkt(drvr, ifp->idx, skb); done: if (ret) diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 3564686add9a..4580ff34c2d0 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -482,15 +482,6 @@ struct sdpcm_shared_le { __le32 brpt_addr; }; -/* SDIO read frame info */ -struct brcmf_sdio_read { - u8 seq_num; - u8 channel; - u16 len; - u16 len_left; - u16 len_nxtfrm; - u8 dat_offset; -}; /* misc chip info needed by some of the routines */ /* Private data for SDIO bus interaction */ @@ -503,8 +494,9 @@ struct brcmf_sdio { u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ u32 hostintmask; /* Copy of Host Interrupt Mask */ - atomic_t intstatus; /* Intstatus bits (events) pending */ - atomic_t fcstate; /* State of dongle flow-control */ + u32 intstatus; /* Intstatus bits (events) pending */ + bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ + bool fcstate; /* State of dongle flow-control */ uint blocksize; /* Block size of SDIO transfers */ uint roundup; /* Max roundup limit */ @@ -516,11 +508,9 @@ struct brcmf_sdio { u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ + u16 nextlen; /* Next Read Len from last header */ u8 rx_seq; /* Receive sequence number (expected) */ - struct brcmf_sdio_read cur_read; - /* info of current read frame */ bool rxskip; /* Skip receive (awaiting NAK ACK) */ - bool rxpending; /* Data frame pending in dongle */ uint rxbound; /* Rx frames to read before resched */ uint txbound; /* Tx frames to send before resched */ @@ -541,7 +531,7 @@ struct brcmf_sdio { bool intr; /* Use interrupts */ bool poll; /* Use polling */ - atomic_t ipend; /* Device interrupt is pending */ + bool ipend; /* Device interrupt is pending */ uint spurious; /* Count of spurious interrupts */ uint pollrate; /* Ticks between device polls */ uint polltick; /* Tick counter */ @@ -559,9 +549,12 @@ struct brcmf_sdio { s32 idleclock; /* How to set bus driver when idle */ s32 sd_rxchain; bool use_rxchain; /* If brcmf should use PKT chains */ + bool sleeping; /* Is SDIO bus sleeping? */ bool rxflow_mode; /* Rx flow control mode */ bool rxflow; /* Is rx flow control on */ bool alp_only; /* Don't use HT clock (ALP only) */ +/* Field to decide if rx of control frames happen in rxbuf or lb-pool */ + bool usebufpool; u8 *ctrl_frame_buf; u32 ctrl_frame_len; @@ -577,8 +570,8 @@ struct brcmf_sdio { bool wd_timer_valid; uint save_ms; - struct workqueue_struct *brcmf_wq; - struct work_struct datawork; + struct task_struct *dpc_tsk; + struct completion dpc_wait; struct list_head dpc_tsklst; spinlock_t dpc_tl_lock; @@ -664,6 +657,15 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) +/* Packet free applicable unconditionally for sdio and sdspi. + * Conditional if bufpool was present for gspi bus. + */ +static void brcmf_sdbrcm_pktfree2(struct brcmf_sdio *bus, struct sk_buff *pkt) +{ + if (bus->usebufpool) + brcmu_pkt_buf_free_skb(pkt); +} + /* Turn backplane clock on or off */ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) { @@ -851,6 +853,81 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) return 0; } +static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) +{ + int ret; + + brcmf_dbg(INFO, "request %s (currently %s)\n", + sleep ? "SLEEP" : "WAKE", + bus->sleeping ? "SLEEP" : "WAKE"); + + /* Done if we're already in the requested state */ + if (sleep == bus->sleeping) + return 0; + + /* Going to sleep: set the alarm and turn off the lights... */ + if (sleep) { + /* Don't sleep if something is pending */ + if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) + return -EBUSY; + + /* Make sure the controller has the bus up */ + brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); + + /* Tell device to start using OOB wakeup */ + ret = w_sdreg32(bus, SMB_USE_OOB, + offsetof(struct sdpcmd_regs, tosbmailbox)); + if (ret != 0) + brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); + + /* Turn off our contribution to the HT clock request */ + brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); + + brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, + SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); + + /* Isolate the bus */ + brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, + SBSDIO_DEVCTL_PADS_ISO, NULL); + + /* Change state */ + bus->sleeping = true; + + } else { + /* Waking up: bus power up is ok, set local state */ + + brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, + 0, NULL); + + /* Make sure the controller has the bus up */ + brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); + + /* Send misc interrupt to indicate OOB not needed */ + ret = w_sdreg32(bus, 0, + offsetof(struct sdpcmd_regs, tosbmailboxdata)); + if (ret == 0) + ret = w_sdreg32(bus, SMB_DEV_INT, + offsetof(struct sdpcmd_regs, tosbmailbox)); + + if (ret != 0) + brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); + + /* Make sure we have SD bus access */ + brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); + + /* Change state */ + bus->sleeping = false; + } + + return 0; +} + +static void bus_wake(struct brcmf_sdio *bus) +{ + if (bus->sleeping) + brcmf_sdbrcm_bussleep(bus, false); +} + static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) { u32 intstatus = 0; @@ -979,7 +1056,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) } /* Clear partial in any case */ - bus->cur_read.len = 0; + bus->nextlen = 0; /* If we can't reach the device, signal failure */ if (err) @@ -1031,96 +1108,6 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) } } -static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, - struct brcmf_sdio_read *rd) -{ - u16 len, checksum; - u8 rx_seq, fc, tx_seq_max; - - /* - * 4 bytes hardware header (frame tag) - * Byte 0~1: Frame length - * Byte 2~3: Checksum, bit-wise inverse of frame length - */ - len = get_unaligned_le16(header); - checksum = get_unaligned_le16(header + sizeof(u16)); - /* All zero means no more to read */ - if (!(len | checksum)) { - bus->rxpending = false; - return false; - } - if ((u16)(~(len ^ checksum))) { - brcmf_dbg(ERROR, "HW header checksum error\n"); - bus->sdcnt.rx_badhdr++; - brcmf_sdbrcm_rxfail(bus, false, false); - return false; - } - if (len < SDPCM_HDRLEN) { - brcmf_dbg(ERROR, "HW header length error\n"); - return false; - } - rd->len = len; - - /* - * 8 bytes hardware header - * Byte 0: Rx sequence number - * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag - * Byte 2: Length of next data frame - * Byte 3: Data offset - * Byte 4: Flow control bits - * Byte 5: Maximum Sequence number allow for Tx - * Byte 6~7: Reserved - */ - rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]); - rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]); - if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL) { - brcmf_dbg(ERROR, "HW header length too long\n"); - bus->sdiodev->bus_if->dstats.rx_errors++; - bus->sdcnt.rx_toolong++; - brcmf_sdbrcm_rxfail(bus, false, false); - rd->len = 0; - return false; - } - rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]); - if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { - brcmf_dbg(ERROR, "seq %d: bad data offset\n", rx_seq); - bus->sdcnt.rx_badhdr++; - brcmf_sdbrcm_rxfail(bus, false, false); - rd->len = 0; - return false; - } - if (rd->seq_num != rx_seq) { - brcmf_dbg(ERROR, "seq %d: sequence number error, expect %d\n", - rx_seq, rd->seq_num); - bus->sdcnt.rx_badseq++; - rd->seq_num = rx_seq; - } - rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; - if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) { - /* only warm for NON glom packet */ - if (rd->channel != SDPCM_GLOM_CHANNEL) - brcmf_dbg(ERROR, "seq %d: next length error\n", rx_seq); - rd->len_nxtfrm = 0; - } - fc = SDPCM_FCMASK_VALUE(&header[SDPCM_FRAMETAG_LEN]); - if (bus->flowcontrol != fc) { - if (~bus->flowcontrol & fc) - bus->sdcnt.fc_xoff++; - if (bus->flowcontrol & ~fc) - bus->sdcnt.fc_xon++; - bus->sdcnt.fc_rcvd++; - bus->flowcontrol = fc; - } - tx_seq_max = SDPCM_WINDOW_VALUE(&header[SDPCM_FRAMETAG_LEN]); - if ((u8)(tx_seq_max - bus->tx_seq) > 0x40) { - brcmf_dbg(ERROR, "seq %d: max tx seq number error\n", rx_seq); - tx_seq_max = bus->tx_seq + 2; - } - bus->tx_max = tx_seq_max; - - return true; -} - static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) { u16 dlen, totlen; @@ -1135,7 +1122,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) int ifidx = 0; bool usechain = bus->use_rxchain; - u16 next_len; /* If packets, issue read(s) and send up packet chain */ /* Return sequence numbers consumed? */ @@ -1199,10 +1185,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) if (pnext) { brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n", totlen, num); - if (BRCMF_GLOM_ON() && bus->cur_read.len && - totlen != bus->cur_read.len) { + if (BRCMF_GLOM_ON() && bus->nextlen && + totlen != bus->nextlen) { brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n", - bus->cur_read.len, totlen, rxseq); + bus->nextlen, totlen, rxseq); } pfirst = pnext = NULL; } else { @@ -1213,7 +1199,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) /* Done with descriptor packet */ brcmu_pkt_buf_free_skb(bus->glomd); bus->glomd = NULL; - bus->cur_read.len = 0; + bus->nextlen = 0; } /* Ok -- either we just generated a packet chain, @@ -1286,13 +1272,12 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); - next_len = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; - if ((next_len << 4) > MAX_RX_DATASZ) { + bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; + if ((bus->nextlen << 4) > MAX_RX_DATASZ) { brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", - next_len, seq); - next_len = 0; + bus->nextlen, seq); + bus->nextlen = 0; } - bus->cur_read.len = next_len << 4; doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); @@ -1393,7 +1378,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) bus->sdcnt.rxglomfail++; brcmf_sdbrcm_free_glom(bus); } - bus->cur_read.len = 0; + bus->nextlen = 0; return 0; } @@ -1588,166 +1573,422 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) } } -static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) +static void +brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen, + struct sk_buff **pkt, u8 **rxbuf) { + int sdret; /* Return code from calls */ + + *pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN); + if (*pkt == NULL) + return; + + pkt_align(*pkt, rdlen, BRCMF_SDALIGN); + *rxbuf = (u8 *) ((*pkt)->data); + /* Read the entire frame */ + sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, + SDIO_FUNC_2, F2SYNC, *pkt); + bus->sdcnt.f2rxdata++; + + if (sdret < 0) { + brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n", + rdlen, sdret); + brcmu_pkt_buf_free_skb(*pkt); + bus->sdiodev->bus_if->dstats.rx_errors++; + /* Force retry w/normal header read. + * Don't attempt NAK for + * gSPI + */ + brcmf_sdbrcm_rxfail(bus, true, true); + *pkt = NULL; + } +} + +/* Checks the header */ +static int +brcmf_check_rxbuf(struct brcmf_sdio *bus, struct sk_buff *pkt, u8 *rxbuf, + u8 rxseq, u16 nextlen, u16 *len) +{ + u16 check; + bool len_consistent; /* Result of comparing readahead len and + len from hw-hdr */ + + memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN); + + /* Extract hardware header fields */ + *len = get_unaligned_le16(bus->rxhdr); + check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); + + /* All zeros means readahead info was bad */ + if (!(*len | check)) { + brcmf_dbg(INFO, "(nextlen): read zeros in HW header???\n"); + goto fail; + } + + /* Validate check bytes */ + if ((u16)~(*len ^ check)) { + brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n", + nextlen, *len, check); + bus->sdcnt.rx_badhdr++; + brcmf_sdbrcm_rxfail(bus, false, false); + goto fail; + } + + /* Validate frame length */ + if (*len < SDPCM_HDRLEN) { + brcmf_dbg(ERROR, "(nextlen): HW hdr length invalid: %d\n", + *len); + goto fail; + } + + /* Check for consistency with readahead info */ + len_consistent = (nextlen != (roundup(*len, 16) >> 4)); + if (len_consistent) { + /* Mismatch, force retry w/normal + header (may be >4K) */ + brcmf_dbg(ERROR, "(nextlen): mismatch, nextlen %d len %d rnd %d; expected rxseq %d\n", + nextlen, *len, roundup(*len, 16), + rxseq); + brcmf_sdbrcm_rxfail(bus, true, true); + goto fail; + } + + return 0; + +fail: + brcmf_sdbrcm_pktfree2(bus, pkt); + return -EINVAL; +} + +/* Return true if there may be more frames to read */ +static uint +brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) +{ + u16 len, check; /* Extracted hardware header fields */ + u8 chan, seq, doff; /* Extracted software header fields */ + u8 fcbits; /* Extracted fcbits from software header */ + struct sk_buff *pkt; /* Packet for event or data frames */ u16 pad; /* Number of pad bytes to read */ + u16 rdlen; /* Total number of bytes to read */ + u8 rxseq; /* Next sequence number to expect */ uint rxleft = 0; /* Remaining number of frames allowed */ int sdret; /* Return code from calls */ + u8 txmax; /* Maximum tx sequence offered */ + u8 *rxbuf; int ifidx = 0; uint rxcount = 0; /* Total frames read */ - struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; - u8 head_read = 0; brcmf_dbg(TRACE, "Enter\n"); /* Not finished unless we encounter no more frames indication */ - bus->rxpending = true; + *finished = false; - for (rd->seq_num = bus->rx_seq, rxleft = maxframes; + for (rxseq = bus->rx_seq, rxleft = maxframes; !bus->rxskip && rxleft && bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN; - rd->seq_num++, rxleft--) { + rxseq++, rxleft--) { /* Handle glomming separately */ if (bus->glomd || !skb_queue_empty(&bus->glom)) { u8 cnt; brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", bus->glomd, skb_peek(&bus->glom)); - cnt = brcmf_sdbrcm_rxglom(bus, rd->seq_num); + cnt = brcmf_sdbrcm_rxglom(bus, rxseq); brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); - rd->seq_num += cnt - 1; + rxseq += cnt - 1; rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; continue; } - rd->len_left = rd->len; - /* read header first for unknow frame length */ - if (!rd->len) { - sdret = brcmf_sdcard_recv_buf(bus->sdiodev, - bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, - bus->rxhdr, - BRCMF_FIRSTREAD); - bus->sdcnt.f2rxhdrs++; - if (sdret < 0) { - brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", - sdret); - bus->sdcnt.rx_hdrfail++; - brcmf_sdbrcm_rxfail(bus, true, true); + /* Try doing single read if we can */ + if (bus->nextlen) { + u16 nextlen = bus->nextlen; + bus->nextlen = 0; + + rdlen = len = nextlen << 4; + brcmf_pad(bus, &pad, &rdlen); + + /* + * After the frame is received we have to + * distinguish whether it is data + * or non-data frame. + */ + brcmf_alloc_pkt_and_read(bus, rdlen, &pkt, &rxbuf); + if (pkt == NULL) { + /* Give up on data, request rtx of events */ + brcmf_dbg(ERROR, "(nextlen): brcmf_alloc_pkt_and_read failed: len %d rdlen %d expected rxseq %d\n", + len, rdlen, rxseq); + continue; + } + + if (brcmf_check_rxbuf(bus, pkt, rxbuf, rxseq, nextlen, + &len) < 0) continue; + + /* Extract software header fields */ + chan = SDPCM_PACKET_CHANNEL( + &bus->rxhdr[SDPCM_FRAMETAG_LEN]); + seq = SDPCM_PACKET_SEQUENCE( + &bus->rxhdr[SDPCM_FRAMETAG_LEN]); + doff = SDPCM_DOFFSET_VALUE( + &bus->rxhdr[SDPCM_FRAMETAG_LEN]); + txmax = SDPCM_WINDOW_VALUE( + &bus->rxhdr[SDPCM_FRAMETAG_LEN]); + + bus->nextlen = + bus->rxhdr[SDPCM_FRAMETAG_LEN + + SDPCM_NEXTLEN_OFFSET]; + if ((bus->nextlen << 4) > MAX_RX_DATASZ) { + brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", + bus->nextlen, seq); + bus->nextlen = 0; } - brcmf_dbg_hex_dump(BRCMF_BYTES_ON() || BRCMF_HDRS_ON(), + bus->sdcnt.rx_readahead_cnt++; + + /* Handle Flow Control */ + fcbits = SDPCM_FCMASK_VALUE( + &bus->rxhdr[SDPCM_FRAMETAG_LEN]); + + if (bus->flowcontrol != fcbits) { + if (~bus->flowcontrol & fcbits) + bus->sdcnt.fc_xoff++; + + if (bus->flowcontrol & ~fcbits) + bus->sdcnt.fc_xon++; + + bus->sdcnt.fc_rcvd++; + bus->flowcontrol = fcbits; + } + + /* Check and update sequence number */ + if (rxseq != seq) { + brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n", + seq, rxseq); + bus->sdcnt.rx_badseq++; + rxseq = seq; + } + + /* Check window for sanity */ + if ((u8) (txmax - bus->tx_seq) > 0x40) { + brcmf_dbg(ERROR, "got unlikely tx max %d with tx_seq %d\n", + txmax, bus->tx_seq); + txmax = bus->tx_seq + 2; + } + bus->tx_max = txmax; + + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), + rxbuf, len, "Rx Data:\n"); + brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && + BRCMF_DATA_ON()) && + BRCMF_HDRS_ON(), bus->rxhdr, SDPCM_HDRLEN, "RxHdr:\n"); - if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd)) { - if (!bus->rxpending) - break; - else - continue; + if (chan == SDPCM_CONTROL_CHANNEL) { + brcmf_dbg(ERROR, "(nextlen): readahead on control packet %d?\n", + seq); + /* Force retry w/normal header read */ + bus->nextlen = 0; + brcmf_sdbrcm_rxfail(bus, false, true); + brcmf_sdbrcm_pktfree2(bus, pkt); + continue; } - if (rd->channel == SDPCM_CONTROL_CHANNEL) { - brcmf_sdbrcm_read_control(bus, bus->rxhdr, - rd->len, - rd->dat_offset); - /* prepare the descriptor for the next read */ - rd->len = rd->len_nxtfrm << 4; - rd->len_nxtfrm = 0; - /* treat all packet as event if we don't know */ - rd->channel = SDPCM_EVENT_CHANNEL; + /* Validate data offset */ + if ((doff < SDPCM_HDRLEN) || (doff > len)) { + brcmf_dbg(ERROR, "(nextlen): bad data offset %d: HW len %d min %d\n", + doff, len, SDPCM_HDRLEN); + brcmf_sdbrcm_rxfail(bus, false, false); + brcmf_sdbrcm_pktfree2(bus, pkt); continue; } - rd->len_left = rd->len > BRCMF_FIRSTREAD ? - rd->len - BRCMF_FIRSTREAD : 0; - head_read = BRCMF_FIRSTREAD; + + /* All done with this one -- now deliver the packet */ + goto deliver; + } + + /* Read frame header (hardware and software) */ + sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, + SDIO_FUNC_2, F2SYNC, bus->rxhdr, + BRCMF_FIRSTREAD); + bus->sdcnt.f2rxhdrs++; + + if (sdret < 0) { + brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret); + bus->sdcnt.rx_hdrfail++; + brcmf_sdbrcm_rxfail(bus, true, true); + continue; + } + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() || BRCMF_HDRS_ON(), + bus->rxhdr, SDPCM_HDRLEN, "RxHdr:\n"); + + + /* Extract hardware header fields */ + len = get_unaligned_le16(bus->rxhdr); + check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); + + /* All zeros means no more frames */ + if (!(len | check)) { + *finished = true; + break; } - brcmf_pad(bus, &pad, &rd->len_left); + /* Validate check bytes */ + if ((u16) ~(len ^ check)) { + brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n", + len, check); + bus->sdcnt.rx_badhdr++; + brcmf_sdbrcm_rxfail(bus, false, false); + continue; + } - pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read + - BRCMF_SDALIGN); + /* Validate frame length */ + if (len < SDPCM_HDRLEN) { + brcmf_dbg(ERROR, "HW hdr length invalid: %d\n", len); + continue; + } + + /* Extract software header fields */ + chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); + seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); + doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); + txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); + + /* Validate data offset */ + if ((doff < SDPCM_HDRLEN) || (doff > len)) { + brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n", + doff, len, SDPCM_HDRLEN, seq); + bus->sdcnt.rx_badhdr++; + brcmf_sdbrcm_rxfail(bus, false, false); + continue; + } + + /* Save the readahead length if there is one */ + bus->nextlen = + bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; + if ((bus->nextlen << 4) > MAX_RX_DATASZ) { + brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", + bus->nextlen, seq); + bus->nextlen = 0; + } + + /* Handle Flow Control */ + fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); + + if (bus->flowcontrol != fcbits) { + if (~bus->flowcontrol & fcbits) + bus->sdcnt.fc_xoff++; + + if (bus->flowcontrol & ~fcbits) + bus->sdcnt.fc_xon++; + + bus->sdcnt.fc_rcvd++; + bus->flowcontrol = fcbits; + } + + /* Check and update sequence number */ + if (rxseq != seq) { + brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq); + bus->sdcnt.rx_badseq++; + rxseq = seq; + } + + /* Check window for sanity */ + if ((u8) (txmax - bus->tx_seq) > 0x40) { + brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", + txmax, bus->tx_seq); + txmax = bus->tx_seq + 2; + } + bus->tx_max = txmax; + + /* Call a separate function for control frames */ + if (chan == SDPCM_CONTROL_CHANNEL) { + brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff); + continue; + } + + /* precondition: chan is either SDPCM_DATA_CHANNEL, + SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or + SDPCM_GLOM_CHANNEL */ + + /* Length to read */ + rdlen = (len > BRCMF_FIRSTREAD) ? (len - BRCMF_FIRSTREAD) : 0; + + /* May pad read to blocksize for efficiency */ + if (bus->roundup && bus->blocksize && + (rdlen > bus->blocksize)) { + pad = bus->blocksize - (rdlen % bus->blocksize); + if ((pad <= bus->roundup) && (pad < bus->blocksize) && + ((rdlen + pad + BRCMF_FIRSTREAD) < MAX_RX_DATASZ)) + rdlen += pad; + } else if (rdlen % BRCMF_SDALIGN) { + rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); + } + + /* Satisfy length-alignment requirements */ + if (rdlen & (ALIGNMENT - 1)) + rdlen = roundup(rdlen, ALIGNMENT); + + if ((rdlen + BRCMF_FIRSTREAD) > MAX_RX_DATASZ) { + /* Too long -- skip this frame */ + brcmf_dbg(ERROR, "too long: len %d rdlen %d\n", + len, rdlen); + bus->sdiodev->bus_if->dstats.rx_errors++; + bus->sdcnt.rx_toolong++; + brcmf_sdbrcm_rxfail(bus, false, false); + continue; + } + + pkt = brcmu_pkt_buf_get_skb(rdlen + + BRCMF_FIRSTREAD + BRCMF_SDALIGN); if (!pkt) { /* Give up on data, request rtx of events */ - brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed\n"); + brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: rdlen %d chan %d\n", + rdlen, chan); bus->sdiodev->bus_if->dstats.rx_dropped++; - brcmf_sdbrcm_rxfail(bus, false, - RETRYCHAN(rd->channel)); + brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan)); continue; } - skb_pull(pkt, head_read); - pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); + /* Leave room for what we already read, and align remainder */ + skb_pull(pkt, BRCMF_FIRSTREAD); + pkt_align(pkt, rdlen, BRCMF_SDALIGN); + + /* Read the remaining frame data */ sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, pkt); bus->sdcnt.f2rxdata++; if (sdret < 0) { - brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n", - rd->len, rd->channel, sdret); + brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen, + ((chan == SDPCM_EVENT_CHANNEL) ? "event" + : ((chan == SDPCM_DATA_CHANNEL) ? "data" + : "test")), sdret); brcmu_pkt_buf_free_skb(pkt); bus->sdiodev->bus_if->dstats.rx_errors++; - brcmf_sdbrcm_rxfail(bus, true, - RETRYCHAN(rd->channel)); + brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan)); continue; } - if (head_read) { - skb_push(pkt, head_read); - memcpy(pkt->data, bus->rxhdr, head_read); - head_read = 0; - } else { - memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); - rd_new.seq_num = rd->seq_num; - if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new)) { - rd->len = 0; - brcmu_pkt_buf_free_skb(pkt); - } - bus->sdcnt.rx_readahead_cnt++; - if (rd->len != roundup(rd_new.len, 16)) { - brcmf_dbg(ERROR, "frame length mismatch:read %d, should be %d\n", - rd->len, - roundup(rd_new.len, 16) >> 4); - rd->len = 0; - brcmf_sdbrcm_rxfail(bus, true, true); - brcmu_pkt_buf_free_skb(pkt); - continue; - } - rd->len_nxtfrm = rd_new.len_nxtfrm; - rd->channel = rd_new.channel; - rd->dat_offset = rd_new.dat_offset; - - brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && - BRCMF_DATA_ON()) && - BRCMF_HDRS_ON(), - bus->rxhdr, SDPCM_HDRLEN, - "RxHdr:\n"); - - if (rd_new.channel == SDPCM_CONTROL_CHANNEL) { - brcmf_dbg(ERROR, "readahead on control packet %d?\n", - rd_new.seq_num); - /* Force retry w/normal header read */ - rd->len = 0; - brcmf_sdbrcm_rxfail(bus, false, true); - brcmu_pkt_buf_free_skb(pkt); - continue; - } - } + /* Copy the already-read portion */ + skb_push(pkt, BRCMF_FIRSTREAD); + memcpy(pkt->data, bus->rxhdr, BRCMF_FIRSTREAD); brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), - pkt->data, rd->len, "Rx Data:\n"); + pkt->data, len, "Rx Data:\n"); +deliver: /* Save superframe descriptor and allocate packet frame */ - if (rd->channel == SDPCM_GLOM_CHANNEL) { + if (chan == SDPCM_GLOM_CHANNEL) { if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", - rd->len); + len); brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), - pkt->data, rd->len, + pkt->data, len, "Glom Data:\n"); - __skb_trim(pkt, rd->len); + __skb_trim(pkt, len); skb_pull(pkt, SDPCM_HDRLEN); bus->glomd = pkt; } else { @@ -1755,23 +1996,12 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) "descriptor!\n", __func__); brcmf_sdbrcm_rxfail(bus, false, false); } - /* prepare the descriptor for the next read */ - rd->len = rd->len_nxtfrm << 4; - rd->len_nxtfrm = 0; - /* treat all packet as event if we don't know */ - rd->channel = SDPCM_EVENT_CHANNEL; continue; } /* Fill in packet len and prio, deliver upward */ - __skb_trim(pkt, rd->len); - skb_pull(pkt, rd->dat_offset); - - /* prepare the descriptor for the next read */ - rd->len = rd->len_nxtfrm << 4; - rd->len_nxtfrm = 0; - /* treat all packet as event if we don't know */ - rd->channel = SDPCM_EVENT_CHANNEL; + __skb_trim(pkt, len); + skb_pull(pkt, doff); if (pkt->len == 0) { brcmu_pkt_buf_free_skb(pkt); @@ -1789,17 +2019,17 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt); down(&bus->sdsem); } - rxcount = maxframes - rxleft; /* Message if we hit the limit */ if (!rxleft) - brcmf_dbg(DATA, "hit rx limit of %d frames\n", maxframes); + brcmf_dbg(DATA, "hit rx limit of %d frames\n", + maxframes); else brcmf_dbg(DATA, "processed %d frames\n", rxcount); /* Back off rxseq if awaiting rtx, update rx_seq */ if (bus->rxskip) - rd->seq_num--; - bus->rx_seq = rd->seq_num; + rxseq--; + bus->rx_seq = rxseq; return rxcount; } @@ -1997,7 +2227,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) if (ret != 0) break; if (intstatus & bus->hostintmask) - atomic_set(&bus->ipend, 1); + bus->ipend = true; } } @@ -2029,8 +2259,16 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) bus->watchdog_tsk = NULL; } + if (bus->dpc_tsk && bus->dpc_tsk != current) { + send_sig(SIGTERM, bus->dpc_tsk, 1); + kthread_stop(bus->dpc_tsk); + bus->dpc_tsk = NULL; + } + down(&bus->sdsem); + bus_wake(bus); + /* Enable clock for device interrupts */ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); @@ -2089,7 +2327,7 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) unsigned long flags; spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); - if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) { + if (!bus->sdiodev->irq_en && !bus->ipend) { enable_irq(bus->sdiodev->irq); bus->sdiodev->irq_en = true; } @@ -2101,69 +2339,21 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) } #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ -static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) -{ - struct list_head *new_hd; - unsigned long flags; - - if (in_interrupt()) - new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC); - else - new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL); - if (new_hd == NULL) - return; - - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - list_add_tail(new_hd, &bus->dpc_tsklst); - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); -} - -static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) +static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) { - u8 idx; - u32 addr; - unsigned long val; - int n, ret; - - idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); - addr = bus->ci->c_inf[idx].base + - offsetof(struct sdpcmd_regs, intstatus); - - ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, false); - bus->sdcnt.f1regdata++; - if (ret != 0) - val = 0; - - val &= bus->hostintmask; - atomic_set(&bus->fcstate, !!(val & I_HMB_FC_STATE)); - - /* Clear interrupts */ - if (val) { - ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, true); - bus->sdcnt.f1regdata++; - } - - if (ret) { - atomic_set(&bus->intstatus, 0); - } else if (val) { - for_each_set_bit(n, &val, 32) - set_bit(n, (unsigned long *)&bus->intstatus.counter); - } - - return ret; -} - -static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) -{ - u32 newstatus = 0; - unsigned long intstatus; + u32 intstatus, newstatus = 0; uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ uint txlimit = bus->txbound; /* Tx frames to send before resched */ uint framecnt = 0; /* Temporary counter of tx/rx frames */ - int err = 0, n; + bool rxdone = true; /* Flag for no more read data */ + bool resched = false; /* Flag indicating resched wanted */ + int err; brcmf_dbg(TRACE, "Enter\n"); + /* Start with leftover status bits */ + intstatus = bus->intstatus; + down(&bus->sdsem); /* If waiting for HTAVAIL, check status */ @@ -2209,22 +2399,39 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; } bus->clkstate = CLK_AVAIL; + } else { + goto clkwait; } } + bus_wake(bus); + /* Make sure backplane clock is on */ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); + if (bus->clkstate == CLK_PENDING) + goto clkwait; /* Pending interrupt indicates new device status */ - if (atomic_read(&bus->ipend) > 0) { - atomic_set(&bus->ipend, 0); - sdio_claim_host(bus->sdiodev->func[1]); - err = brcmf_sdio_intr_rstatus(bus); - sdio_release_host(bus->sdiodev->func[1]); + if (bus->ipend) { + bus->ipend = false; + err = r_sdreg32(bus, &newstatus, + offsetof(struct sdpcmd_regs, intstatus)); + bus->sdcnt.f1regdata++; + if (err != 0) + newstatus = 0; + newstatus &= bus->hostintmask; + bus->fcstate = !!(newstatus & I_HMB_FC_STATE); + if (newstatus) { + err = w_sdreg32(bus, newstatus, + offsetof(struct sdpcmd_regs, + intstatus)); + bus->sdcnt.f1regdata++; + } } - /* Start with leftover status bits */ - intstatus = atomic_xchg(&bus->intstatus, 0); + /* Merge new bits with previous */ + intstatus |= newstatus; + bus->intstatus = 0; /* Handle flow-control change: read new state in case our ack * crossed another change interrupt. If change still set, assume @@ -2238,8 +2445,8 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) err = r_sdreg32(bus, &newstatus, offsetof(struct sdpcmd_regs, intstatus)); bus->sdcnt.f1regdata += 2; - atomic_set(&bus->fcstate, - !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE))); + bus->fcstate = + !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); intstatus |= (newstatus & bus->hostintmask); } @@ -2276,34 +2483,32 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) intstatus &= ~I_HMB_FRAME_IND; /* On frame indication, read available frames */ - if (PKT_AVAILABLE() && bus->clkstate == CLK_AVAIL) { - framecnt = brcmf_sdio_readframes(bus, rxlimit); - if (!bus->rxpending) + if (PKT_AVAILABLE()) { + framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone); + if (rxdone || bus->rxskip) intstatus &= ~I_HMB_FRAME_IND; rxlimit -= min(framecnt, rxlimit); } /* Keep still-pending events for next scheduling */ - if (intstatus) { - for_each_set_bit(n, &intstatus, 32) - set_bit(n, (unsigned long *)&bus->intstatus.counter); - } + bus->intstatus = intstatus; +clkwait: brcmf_sdbrcm_clrintr(bus); if (data_ok(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { - int i; + int ret, i; - err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, + ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf, (u32) bus->ctrl_frame_len); - if (err < 0) { + if (ret < 0) { /* On failure, abort the command and terminate the frame */ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", - err); + ret); bus->sdcnt.tx_sderrs++; brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); @@ -2325,34 +2530,42 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) break; } - } else { - bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; } + if (ret == 0) + bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; + + brcmf_dbg(INFO, "Return_dpc value is : %d\n", ret); bus->ctrl_frame_stat = false; brcmf_sdbrcm_wait_event_wakeup(bus); } /* Send queued frames (limit 1 if rx may still be pending) */ - else if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && + else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && data_ok(bus)) { - framecnt = bus->rxpending ? min(txlimit, bus->txminmax) : - txlimit; + framecnt = rxdone ? txlimit : min(txlimit, bus->txminmax); framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt); txlimit -= framecnt; } + /* Resched if events or tx frames are pending, + else await next interrupt */ + /* On failed register access, all bets are off: + no resched or interrupts */ if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) { brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n"); bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; - atomic_set(&bus->intstatus, 0); - } else if (atomic_read(&bus->intstatus) || - atomic_read(&bus->ipend) > 0 || - (!atomic_read(&bus->fcstate) && - brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && - data_ok(bus)) || PKT_AVAILABLE()) { - brcmf_sdbrcm_adddpctsk(bus); + bus->intstatus = 0; + } else if (bus->clkstate == CLK_PENDING) { + brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n"); + resched = true; + } else if (bus->intstatus || bus->ipend || + (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) + && data_ok(bus)) || PKT_AVAILABLE()) { + resched = true; } + bus->dpc_sched = resched; + /* If we're done for now, turn off clock request. */ if ((bus->clkstate != CLK_PENDING) && bus->idletime == BRCMF_IDLE_IMMEDIATE) { @@ -2361,6 +2574,65 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) } up(&bus->sdsem); + + return resched; +} + +static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) +{ + struct list_head *new_hd; + unsigned long flags; + + if (in_interrupt()) + new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC); + else + new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL); + if (new_hd == NULL) + return; + + spin_lock_irqsave(&bus->dpc_tl_lock, flags); + list_add_tail(new_hd, &bus->dpc_tsklst); + spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); +} + +static int brcmf_sdbrcm_dpc_thread(void *data) +{ + struct brcmf_sdio *bus = (struct brcmf_sdio *) data; + struct list_head *cur_hd, *tmp_hd; + unsigned long flags; + + allow_signal(SIGTERM); + /* Run until signal received */ + while (1) { + if (kthread_should_stop()) + break; + + if (list_empty(&bus->dpc_tsklst)) + if (wait_for_completion_interruptible(&bus->dpc_wait)) + break; + + spin_lock_irqsave(&bus->dpc_tl_lock, flags); + list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) { + spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); + + if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) { + /* after stopping the bus, exit thread */ + brcmf_sdbrcm_bus_stop(bus->sdiodev->dev); + bus->dpc_tsk = NULL; + spin_lock_irqsave(&bus->dpc_tl_lock, flags); + break; + } + + if (brcmf_sdbrcm_dpc(bus)) + brcmf_sdbrcm_adddpctsk(bus); + + spin_lock_irqsave(&bus->dpc_tl_lock, flags); + list_del(cur_hd); + kfree(cur_hd); + } + spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); + } + return 0; } static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) @@ -2370,7 +2642,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; - unsigned long flags; brcmf_dbg(TRACE, "Enter\n"); @@ -2409,15 +2680,13 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) if (pktq_plen(&bus->txq, prec) > qcount[prec]) qcount[prec] = pktq_plen(&bus->txq, prec); #endif - - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - if (list_empty(&bus->dpc_tsklst)) { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); - - brcmf_sdbrcm_adddpctsk(bus); - queue_work(bus->brcmf_wq, &bus->datawork); - } else { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); + /* Schedule DPC if needed to send queued packet(s) */ + if (!bus->dpc_sched) { + bus->dpc_sched = true; + if (bus->dpc_tsk) { + brcmf_sdbrcm_adddpctsk(bus); + complete(&bus->dpc_wait); + } } return ret; @@ -2438,8 +2707,6 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, else dsize = size; - sdio_claim_host(bus->sdiodev->func[1]); - /* Set the backplane window to include the start address */ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); if (bcmerror) { @@ -2481,8 +2748,6 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", bus->sdiodev->sbwad); - sdio_release_host(bus->sdiodev->func[1]); - return bcmerror; } @@ -2617,7 +2882,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; - unsigned long flags; brcmf_dbg(TRACE, "Enter\n"); @@ -2654,6 +2918,8 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) /* Need to lock here to protect txseq and SDIO tx calls */ down(&bus->sdsem); + bus_wake(bus); + /* Make sure backplane clock is on */ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); @@ -2701,15 +2967,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) } while (ret < 0 && retries++ < TXRETRIES); } - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && - list_empty(&bus->dpc_tsklst)) { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); - + if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) { bus->activity = false; brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); - } else { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); } up(&bus->sdsem); @@ -3514,20 +3774,23 @@ void brcmf_sdbrcm_isr(void *arg) } /* Count the interrupt call */ bus->sdcnt.intrcount++; - if (in_interrupt()) - atomic_set(&bus->ipend, 1); - else - if (brcmf_sdio_intr_rstatus(bus)) { - brcmf_dbg(ERROR, "failed backplane access\n"); - bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; - } + bus->ipend = true; + + /* Shouldn't get this interrupt if we're sleeping? */ + if (bus->sleeping) { + brcmf_dbg(ERROR, "INTERRUPT WHILE SLEEPING??\n"); + return; + } /* Disable additional interrupts (is this needed now)? */ if (!bus->intr) brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); - brcmf_sdbrcm_adddpctsk(bus); - queue_work(bus->brcmf_wq, &bus->datawork); + bus->dpc_sched = true; + if (bus->dpc_tsk) { + brcmf_sdbrcm_adddpctsk(bus); + complete(&bus->dpc_wait); + } } static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) @@ -3535,10 +3798,13 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) #ifdef DEBUG struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); #endif /* DEBUG */ - unsigned long flags; brcmf_dbg(TIMER, "Enter\n"); + /* Ignore the timer if simulating bus down */ + if (bus->sleeping) + return false; + down(&bus->sdsem); /* Poll period: check device if appropriate. */ @@ -3552,30 +3818,27 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) if (!bus->intr || (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - if (list_empty(&bus->dpc_tsklst)) { + if (!bus->dpc_sched) { u8 devpend; - spin_unlock_irqrestore(&bus->dpc_tl_lock, - flags); devpend = brcmf_sdio_regrb(bus->sdiodev, SDIO_CCCR_INTx, NULL); intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2); - } else { - spin_unlock_irqrestore(&bus->dpc_tl_lock, - flags); } /* If there is something, make like the ISR and schedule the DPC */ if (intstatus) { bus->sdcnt.pollcnt++; - atomic_set(&bus->ipend, 1); + bus->ipend = true; - brcmf_sdbrcm_adddpctsk(bus); - queue_work(bus->brcmf_wq, &bus->datawork); + bus->dpc_sched = true; + if (bus->dpc_tsk) { + brcmf_sdbrcm_adddpctsk(bus); + complete(&bus->dpc_wait); + } } } @@ -3613,7 +3876,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) up(&bus->sdsem); - return (atomic_read(&bus->ipend) > 0); + return bus->ipend; } static bool brcmf_sdbrcm_chipmatch(u16 chipid) @@ -3629,26 +3892,6 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid) return false; } -static void brcmf_sdio_dataworker(struct work_struct *work) -{ - struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, - datawork); - struct list_head *cur_hd, *tmp_hd; - unsigned long flags; - - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); - - brcmf_sdbrcm_dpc(bus); - - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - list_del(cur_hd); - kfree(cur_hd); - } - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); -} - static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) { brcmf_dbg(TRACE, "Enter\n"); @@ -3781,6 +4024,7 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) SDIO_FUNC_ENABLE_1, NULL); bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; + bus->sleeping = false; bus->rxflow = false; /* Done with backplane-dependent accesses, can drop clock... */ @@ -3861,9 +4105,6 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) /* De-register interrupt handler */ brcmf_sdio_intr_unregister(bus->sdiodev); - cancel_work_sync(&bus->datawork); - destroy_workqueue(bus->brcmf_wq); - if (bus->sdiodev->bus_if->drvr) { brcmf_detach(bus->sdiodev->dev); brcmf_sdbrcm_release_dongle(bus); @@ -3903,6 +4144,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) bus->rxbound = BRCMF_RXBOUND; bus->txminmax = BRCMF_TXMINMAX; bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; + bus->usebufpool = false; /* Use bufpool if allocated, + else use locally malloced rxbuf */ /* attempt to attach to the dongle */ if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { @@ -3914,13 +4157,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) init_waitqueue_head(&bus->ctrl_wait); init_waitqueue_head(&bus->dcmd_resp_wait); - bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq"); - if (bus->brcmf_wq == NULL) { - brcmf_dbg(ERROR, "insufficient memory to create txworkqueue\n"); - goto fail; - } - INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); - /* Set up the watchdog timer */ init_timer(&bus->timer); bus->timer.data = (unsigned long)bus; @@ -3938,8 +4174,15 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) bus->watchdog_tsk = NULL; } /* Initialize DPC thread */ + init_completion(&bus->dpc_wait); INIT_LIST_HEAD(&bus->dpc_tsklst); spin_lock_init(&bus->dpc_tl_lock); + bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread, + bus, "brcmf_dpc"); + if (IS_ERR(bus->dpc_tsk)) { + pr_warn("brcmf_dpc thread failed to start\n"); + bus->dpc_tsk = NULL; + } /* Assign bus interface call back */ bus->sdiodev->bus_if->brcmf_bus_stop = brcmf_sdbrcm_bus_stop; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 0d30afd8c672..29bf78d264e0 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h @@ -174,8 +174,6 @@ extern void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data, int *ret); extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data, int *ret); -extern int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, - void *data, bool write); /* Buffer transfer to/from device (client) core via cmd53. * fn: function number diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a2b4b1e71017..c6d5aeb27a02 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -81,12 +81,10 @@ enum usbdev_suspend_state { }; struct brcmf_usb_image { - struct list_head list; - s8 *fwname; - u8 *image; - int image_len; + void *data; + u32 len; }; -static struct list_head fw_image_list; +static struct brcmf_usb_image g_image = { NULL, 0 }; struct intr_transfer_buf { u32 notification; @@ -134,6 +132,8 @@ struct brcmf_usbdev_info { wait_queue_head_t ctrl_wait; ulong ctl_op; + bool rxctl_deferrespok; + struct urb *bulk_urb; /* used for FW download */ struct urb *intr_urb; /* URB for interrupt endpoint */ int intr_size; /* Size of interrupt message */ @@ -160,17 +160,40 @@ static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev) return brcmf_usb_get_buspub(dev)->devinfo; } -static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo) +static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo, + uint *condition, bool *pending) { - return wait_event_timeout(devinfo->ioctl_resp_wait, - devinfo->ctl_completed, - msecs_to_jiffies(IOCTL_RESP_TIMEOUT)); + DECLARE_WAITQUEUE(wait, current); + int timeout = IOCTL_RESP_TIMEOUT; + + /* Convert timeout in millsecond to jiffies */ + timeout = msecs_to_jiffies(timeout); + /* Wait until control frame is available */ + add_wait_queue(&devinfo->ioctl_resp_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + smp_mb(); + while (!(*condition) && (!signal_pending(current) && timeout)) { + timeout = schedule_timeout(timeout); + /* Wait until control frame is available */ + smp_mb(); + } + + if (signal_pending(current)) + *pending = true; + + set_current_state(TASK_RUNNING); + remove_wait_queue(&devinfo->ioctl_resp_wait, &wait); + + return timeout; } -static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo) +static int brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo) { if (waitqueue_active(&devinfo->ioctl_resp_wait)) - wake_up(&devinfo->ioctl_resp_wait); + wake_up_interruptible(&devinfo->ioctl_resp_wait); + + return 0; } static void @@ -276,9 +299,17 @@ brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len) devinfo->ctl_read.wLength = cpu_to_le16p(&size); devinfo->ctl_urb->transfer_buffer_length = size; - devinfo->ctl_read.bRequestType = USB_DIR_IN - | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - devinfo->ctl_read.bRequest = 1; + if (devinfo->rxctl_deferrespok) { + /* BMAC model */ + devinfo->ctl_read.bRequestType = USB_DIR_IN + | USB_TYPE_VENDOR | USB_RECIP_INTERFACE; + devinfo->ctl_read.bRequest = DL_DEFER_RESP_OK; + } else { + /* full dongle model */ + devinfo->ctl_read.bRequestType = USB_DIR_IN + | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + devinfo->ctl_read.bRequest = 1; + } usb_fill_control_urb(devinfo->ctl_urb, devinfo->usbdev, @@ -299,6 +330,7 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len) { int err = 0; int timeout = 0; + bool pending; struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { @@ -313,10 +345,11 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len) err = brcmf_usb_send_ctl(devinfo, buf, len); if (err) { brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); - clear_bit(0, &devinfo->ctl_op); return err; } - timeout = brcmf_usb_ioctl_resp_wait(devinfo); + + timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed, + &pending); clear_bit(0, &devinfo->ctl_op); if (!timeout) { brcmf_dbg(ERROR, "Txctl wait timed out\n"); @@ -329,6 +362,7 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len) { int err = 0; int timeout = 0; + bool pending; struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { @@ -338,14 +372,14 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len) if (test_and_set_bit(0, &devinfo->ctl_op)) return -EIO; - devinfo->ctl_completed = false; err = brcmf_usb_recv_ctl(devinfo, buf, len); if (err) { brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); - clear_bit(0, &devinfo->ctl_op); return err; } - timeout = brcmf_usb_ioctl_resp_wait(devinfo); + devinfo->ctl_completed = false; + timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed, + &pending); err = devinfo->ctl_urb_status; clear_bit(0, &devinfo->ctl_op); if (!timeout) { @@ -465,8 +499,6 @@ static void brcmf_usb_tx_complete(struct urb *urb) else devinfo->bus_pub.bus->dstats.tx_errors++; - brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0); - brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount); @@ -1120,6 +1152,10 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo) { brcmf_dbg(TRACE, "devinfo %p\n", devinfo); + /* store the image globally */ + g_image.data = devinfo->image; + g_image.len = devinfo->image_len; + /* free the URBS */ brcmf_usb_free_q(&devinfo->rx_freeq, false); brcmf_usb_free_q(&devinfo->tx_freeq, false); @@ -1171,9 +1207,17 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) { s8 *fwname; const struct firmware *fw; - struct brcmf_usb_image *fw_image; int err; + devinfo->image = g_image.data; + devinfo->image_len = g_image.len; + + /* + * if we have an image we can leave here. + */ + if (devinfo->image) + return 0; + switch (devinfo->bus_pub.devid) { case 43143: fwname = BRCMF_USB_43143_FW_NAME; @@ -1191,14 +1235,6 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) break; } - list_for_each_entry(fw_image, &fw_image_list, list) { - if (fw_image->fwname == fwname) { - devinfo->image = fw_image->image; - devinfo->image_len = fw_image->image_len; - return 0; - } - } - /* fw image not yet loaded. Load it now and add to list */ err = request_firmware(&fw, fwname, devinfo->dev); if (!fw) { brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname); @@ -1209,24 +1245,14 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) return -EINVAL; } - fw_image = kzalloc(sizeof(*fw_image), GFP_ATOMIC); - if (!fw_image) - return -ENOMEM; - INIT_LIST_HEAD(&fw_image->list); - list_add_tail(&fw_image->list, &fw_image_list); - fw_image->fwname = fwname; - fw_image->image = vmalloc(fw->size); - if (!fw_image->image) + devinfo->image = vmalloc(fw->size); /* plus nvram */ + if (!devinfo->image) return -ENOMEM; - memcpy(fw_image->image, fw->data, fw->size); - fw_image->image_len = fw->size; + memcpy(devinfo->image, fw->data, fw->size); + devinfo->image_len = fw->size; release_firmware(fw); - - devinfo->image = fw_image->image; - devinfo->image_len = fw_image->image_len; - return 0; } @@ -1278,6 +1304,8 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo, brcmf_dbg(ERROR, "usb_alloc_urb (ctl) failed\n"); goto error; } + devinfo->rxctl_deferrespok = 0; + devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC); if (!devinfo->bulk_urb) { brcmf_dbg(ERROR, "usb_alloc_urb (bulk) failed\n"); @@ -1312,8 +1340,10 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo, struct device *dev = devinfo->dev; bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ); - if (!bus_pub) - return -ENODEV; + if (!bus_pub) { + ret = -ENODEV; + goto fail; + } bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); if (!bus) { @@ -1566,25 +1596,15 @@ static struct usb_driver brcmf_usbdrvr = { .disable_hub_initiated_lpm = 1, }; -static void brcmf_release_fw(struct list_head *q) -{ - struct brcmf_usb_image *fw_image, *next; - - list_for_each_entry_safe(fw_image, next, q, list) { - vfree(fw_image->image); - list_del_init(&fw_image->list); - } -} - - void brcmf_usb_exit(void) { usb_deregister(&brcmf_usbdrvr); - brcmf_release_fw(&fw_image_list); + vfree(g_image.data); + g_image.data = NULL; + g_image.len = 0; } void brcmf_usb_init(void) { - INIT_LIST_HEAD(&fw_image_list); usb_register(&brcmf_usbdrvr); } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index c1abaa6db59e..65cf8f92cb3e 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -36,58 +36,6 @@ #include "dhd.h" #include "wl_cfg80211.h" -#define BRCMF_SCAN_IE_LEN_MAX 2048 -#define BRCMF_PNO_VERSION 2 -#define BRCMF_PNO_TIME 30 -#define BRCMF_PNO_REPEAT 4 -#define BRCMF_PNO_FREQ_EXPO_MAX 3 -#define BRCMF_PNO_MAX_PFN_COUNT 16 -#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 -#define BRCMF_PNO_HIDDEN_BIT 2 -#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF -#define BRCMF_PNO_SCAN_COMPLETE 1 -#define BRCMF_PNO_SCAN_INCOMPLETE 0 - -#define TLV_LEN_OFF 1 /* length offset */ -#define TLV_HDR_LEN 2 /* header length */ -#define TLV_BODY_OFF 2 /* body offset */ -#define TLV_OUI_LEN 3 /* oui id length */ -#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ -#define WPA_OUI_TYPE 1 -#define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */ -#define WME_OUI_TYPE 2 - -#define VS_IE_FIXED_HDR_LEN 6 -#define WPA_IE_VERSION_LEN 2 -#define WPA_IE_MIN_OUI_LEN 4 -#define WPA_IE_SUITE_COUNT_LEN 2 - -#define WPA_CIPHER_NONE 0 /* None */ -#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ -#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ -#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ -#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ - -#define RSN_AKM_NONE 0 /* None (IBSS) */ -#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ -#define RSN_AKM_PSK 2 /* Pre-shared Key */ -#define RSN_CAP_LEN 2 /* Length of RSN capabilities */ -#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C - -#define VNDR_IE_CMD_LEN 4 /* length of the set command - * string :"add", "del" (+ NUL) - */ -#define VNDR_IE_COUNT_OFFSET 4 -#define VNDR_IE_PKTFLAG_OFFSET 8 -#define VNDR_IE_VSIE_OFFSET 12 -#define VNDR_IE_HDR_SIZE 12 -#define VNDR_IE_BEACON_FLAG 0x1 -#define VNDR_IE_PRBRSP_FLAG 0x2 -#define MAX_VNDR_IE_NUMBER 5 - -#define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */ -#define DOT11_BCN_PRB_FIXED_LEN 12 /* beacon/probe fixed length */ - #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) @@ -95,12 +43,33 @@ static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; static u32 brcmf_dbg_level = WL_DBG_ERR; +static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data) +{ + dev->driver_data = data; +} + +static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev) +{ + void *data = NULL; + + if (dev) + data = dev->driver_data; + return data; +} + +static +struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev) +{ + struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev); + return ci->cfg_priv; +} + static bool check_sys_up(struct wiphy *wiphy) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - if (!test_bit(WL_STATUS_READY, &cfg->status)) { + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { WL_INFO("device is not ready : status (%d)\n", - (int)cfg->status); + (int)cfg_priv->status); return false; } return true; @@ -288,25 +257,6 @@ struct brcmf_tlv { u8 data[1]; }; -/* Vendor specific ie. id = 221, oui and type defines exact ie */ -struct brcmf_vs_tlv { - u8 id; - u8 len; - u8 oui[3]; - u8 oui_type; -}; - -struct parsed_vndr_ie_info { - u8 *ie_ptr; - u32 ie_len; /* total length including id & length field */ - struct brcmf_vs_tlv vndrie; -}; - -struct parsed_vndr_ies { - u32 count; - struct parsed_vndr_ie_info ie_info[MAX_VNDR_IE_NUMBER]; -}; - /* Quarter dBm units to mW * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 * Table is offset so the last entry is largest mW value that fits in @@ -404,44 +354,6 @@ brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par) return err; } -static s32 -brcmf_dev_iovar_setbuf_bsscfg(struct net_device *ndev, s8 *name, - void *param, s32 paramlen, - void *buf, s32 buflen, s32 bssidx) -{ - s32 err = -ENOMEM; - u32 len; - - len = brcmf_c_mkiovar_bsscfg(name, param, paramlen, - buf, buflen, bssidx); - BUG_ON(!len); - if (len > 0) - err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len); - if (err) - WL_ERR("error (%d)\n", err); - - return err; -} - -static s32 -brcmf_dev_iovar_getbuf_bsscfg(struct net_device *ndev, s8 *name, - void *param, s32 paramlen, - void *buf, s32 buflen, s32 bssidx) -{ - s32 err = -ENOMEM; - u32 len; - - len = brcmf_c_mkiovar_bsscfg(name, param, paramlen, - buf, buflen, bssidx); - BUG_ON(!len); - if (len > 0) - err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, buf, len); - if (err) - WL_ERR("error (%d)\n", err); - - return err; -} - static void convert_key_from_CPU(struct brcmf_wsec_key *key, struct brcmf_wsec_key_le *key_le) { @@ -456,22 +368,16 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key, memcpy(key_le->ea, key->ea, sizeof(key->ea)); } -static int -send_key_to_dongle(struct brcmf_cfg80211_info *cfg, s32 bssidx, - struct net_device *ndev, struct brcmf_wsec_key *key) +static int send_key_to_dongle(struct net_device *ndev, + struct brcmf_wsec_key *key) { int err; struct brcmf_wsec_key_le key_le; convert_key_from_CPU(key, &key_le); - - err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, - sizeof(key_le), - cfg->extra_buf, - WL_EXTRA_BUF_MAX, bssidx); - + err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le)); if (err) - WL_ERR("wsec_key error (%d)\n", err); + WL_ERR("WLC_SET_KEY error (%d)\n", err); return err; } @@ -480,12 +386,14 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct wireless_dev *wdev; s32 infra = 0; - s32 ap = 0; s32 err = 0; - WL_TRACE("Enter, ndev=%p, type=%d\n", ndev, type); + WL_TRACE("Enter\n"); + if (!check_sys_up(wiphy)) + return -EIO; switch (type) { case NL80211_IFTYPE_MONITOR: @@ -494,44 +402,29 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, type); return -EOPNOTSUPP; case NL80211_IFTYPE_ADHOC: - cfg->conf->mode = WL_MODE_IBSS; + cfg_priv->conf->mode = WL_MODE_IBSS; infra = 0; break; case NL80211_IFTYPE_STATION: - cfg->conf->mode = WL_MODE_BSS; + cfg_priv->conf->mode = WL_MODE_BSS; infra = 1; break; - case NL80211_IFTYPE_AP: - cfg->conf->mode = WL_MODE_AP; - ap = 1; - break; default: err = -EINVAL; goto done; } - if (ap) { - set_bit(WL_STATUS_AP_CREATING, &cfg->status); - if (!cfg->ap_info) - cfg->ap_info = kzalloc(sizeof(*cfg->ap_info), - GFP_KERNEL); - if (!cfg->ap_info) { - err = -ENOMEM; - goto done; - } - WL_INFO("IF Type = AP\n"); + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); + if (err) { + WL_ERR("WLC_SET_INFRA error (%d)\n", err); + err = -EAGAIN; } else { - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); - if (err) { - WL_ERR("WLC_SET_INFRA error (%d)\n", err); - err = -EAGAIN; - goto done; - } - WL_INFO("IF Type = %s\n", - (cfg->conf->mode == WL_MODE_IBSS) ? - "Adhoc" : "Infra"); + wdev = ndev->ieee80211_ptr; + wdev->iftype = type; } - ndev->ieee80211_ptr->iftype = type; + + WL_INFO("IF Type = %s\n", + (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra"); done: WL_TRACE("Exit\n"); @@ -582,55 +475,12 @@ brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval) return err; } -static s32 -brcmf_dev_intvar_set_bsscfg(struct net_device *ndev, s8 *name, u32 val, - s32 bssidx) -{ - s8 buf[BRCMF_DCMD_SMLEN]; - __le32 val_le; - - val_le = cpu_to_le32(val); - - return brcmf_dev_iovar_setbuf_bsscfg(ndev, name, &val_le, - sizeof(val_le), buf, sizeof(buf), - bssidx); -} - -static s32 -brcmf_dev_intvar_get_bsscfg(struct net_device *ndev, s8 *name, s32 *val, - s32 bssidx) -{ - s8 buf[BRCMF_DCMD_SMLEN]; - s32 err; - __le32 val_le; - - memset(buf, 0, sizeof(buf)); - err = brcmf_dev_iovar_getbuf_bsscfg(ndev, name, val, sizeof(*val), buf, - sizeof(buf), bssidx); - if (err == 0) { - memcpy(&val_le, buf, sizeof(val_le)); - *val = le32_to_cpu(val_le); - } - return err; -} - - -/* - * For now brcmf_find_bssidx will return 0. Once p2p gets implemented this - * should return the ndev matching bssidx. - */ -static s32 -brcmf_find_bssidx(struct brcmf_cfg80211_info *cfg, struct net_device *ndev) -{ - return 0; -} - static void brcmf_set_mpc(struct net_device *ndev, int mpc) { s32 err = 0; - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); - if (test_bit(WL_STATUS_READY, &cfg->status)) { + if (test_bit(WL_STATUS_READY, &cfg_priv->status)) { err = brcmf_dev_intvar_set(ndev, "mpc", mpc); if (err) { WL_ERR("fail to set mpc\n"); @@ -651,10 +501,8 @@ static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le, params_le->active_time = cpu_to_le32(-1); params_le->passive_time = cpu_to_le32(-1); params_le->home_time = cpu_to_le32(-1); - if (ssid && ssid->SSID_len) { - params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len); - memcpy(¶ms_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len); - } + if (ssid && ssid->SSID_len) + memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); } static s32 @@ -716,10 +564,10 @@ brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, return err; } -static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); - struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); + struct net_device *ndev = cfg_to_ndev(cfg_priv); struct brcmf_ssid ssid; __le32 passive_scan; s32 err = 0; @@ -729,19 +577,19 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg) iscan->state = WL_ISCAN_STATE_SCANING; - passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); - err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_SET_PASSIVE_SCAN, + passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); + err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan)); if (err) { WL_ERR("error (%d)\n", err); return err; } brcmf_set_mpc(ndev, 0); - cfg->iscan_kickstart = true; + cfg_priv->iscan_kickstart = true; err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START); if (err) { brcmf_set_mpc(ndev, 1); - cfg->iscan_kickstart = false; + cfg_priv->iscan_kickstart = false; return err; } mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); @@ -754,27 +602,27 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid) { - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct cfg80211_ssid *ssids; - struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; + struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int; __le32 passive_scan; bool iscan_req; bool spec_scan; s32 err = 0; u32 SSID_len; - if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { - WL_ERR("Scanning already : status (%lu)\n", cfg->status); + if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { + WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status); return -EAGAIN; } - if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) { + if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) { WL_ERR("Scanning being aborted : status (%lu)\n", - cfg->status); + cfg_priv->status); return -EAGAIN; } - if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) { + if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { WL_ERR("Connecting : status (%lu)\n", - cfg->status); + cfg_priv->status); return -EAGAIN; } @@ -783,7 +631,7 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, if (request) { /* scan bss */ ssids = request->ssids; - if (cfg->iscan_on && (!ssids || !ssids->ssid_len)) + if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len)) iscan_req = true; } else { /* scan in ibss */ @@ -791,10 +639,10 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, ssids = this_ssid; } - cfg->scan_request = request; - set_bit(WL_STATUS_SCANNING, &cfg->status); + cfg_priv->scan_request = request; + set_bit(WL_STATUS_SCANNING, &cfg_priv->status); if (iscan_req) { - err = brcmf_do_iscan(cfg); + err = brcmf_do_iscan(cfg_priv); if (!err) return err; else @@ -813,7 +661,7 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, WL_SCAN("Broadcast scan\n"); } - passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); + passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan)); if (err) { @@ -838,8 +686,8 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, return 0; scan_out: - clear_bit(WL_STATUS_SCANNING, &cfg->status); - cfg->scan_request = NULL; + clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); + cfg_priv->scan_request = NULL; return err; } @@ -850,11 +698,11 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, u32 n_channels; s32 i; s32 offset; - u16 chanspec; + __le16 chanspec; u16 channel; struct ieee80211_channel *req_channel; char *ptr; - struct brcmf_ssid_le ssid_le; + struct brcmf_ssid ssid; memcpy(params_le->bssid, ether_bcast, ETH_ALEN); params_le->bss_type = DOT11_BSSTYPE_ANY; @@ -897,10 +745,13 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, chanspec |= WL_CHANSPEC_CTL_SB_UPPER; } - chanspec |= (channel & WL_CHANSPEC_CHAN_MASK); + params_le->channel_list[i] = + (channel & WL_CHANSPEC_CHAN_MASK) | + chanspec; WL_SCAN("Chan : %d, Channel spec: %x\n", - channel, chanspec); - params_le->channel_list[i] = cpu_to_le16(chanspec); + channel, params_le->channel_list[i]); + params_le->channel_list[i] = + cpu_to_le16(params_le->channel_list[i]); } } else { WL_SCAN("Scanning all channels\n"); @@ -913,18 +764,17 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, offset = roundup(offset, sizeof(u32)); ptr = (char *)params_le + offset; for (i = 0; i < n_ssids; i++) { - memset(&ssid_le, 0, sizeof(ssid_le)); - ssid_le.SSID_len = - cpu_to_le32(request->ssids[i].ssid_len); - memcpy(ssid_le.SSID, request->ssids[i].ssid, - request->ssids[i].ssid_len); - if (!ssid_le.SSID_len) + memset(&ssid, 0, sizeof(ssid)); + ssid.SSID_len = cpu_to_le32(request->ssids[i].ssid_len); + memcpy(ssid.SSID, request->ssids[i].ssid, + request->ssids[i].ssid_len); + if (!ssid.SSID_len) WL_SCAN("%d: Broadcast scan\n", i); else WL_SCAN("%d: scan for %s size =%d\n", i, - ssid_le.SSID, ssid_le.SSID_len); - memcpy(ptr, &ssid_le, sizeof(ssid_le)); - ptr += sizeof(ssid_le); + ssid.SSID, ssid.SSID_len); + memcpy(ptr, &ssid, sizeof(ssid)); + ptr += sizeof(ssid); } } else { WL_SCAN("Broadcast scan %p\n", request->ssids); @@ -944,7 +794,7 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, } static s32 -brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, +brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, bool aborted, bool fw_abort) { @@ -956,11 +806,11 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, /* clear scan request, because the FW abort can cause a second call */ /* to this functon and might cause a double cfg80211_scan_done */ - scan_request = cfg->scan_request; - cfg->scan_request = NULL; + scan_request = cfg_priv->scan_request; + cfg_priv->scan_request = NULL; - if (timer_pending(&cfg->escan_timeout)) - del_timer_sync(&cfg->escan_timeout); + if (timer_pending(&cfg_priv->escan_timeout)) + del_timer_sync(&cfg_priv->escan_timeout); if (fw_abort) { /* Do a scan abort to stop the driver's scan engine */ @@ -982,23 +832,13 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, if (err) WL_ERR("Scan abort failed\n"); } - /* - * e-scan can be initiated by scheduled scan - * which takes precedence. - */ - if (cfg->sched_escan) { - WL_SCAN("scheduled scan completed\n"); - cfg->sched_escan = false; - if (!aborted) - cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); - brcmf_set_mpc(ndev, 1); - } else if (scan_request) { + if (scan_request) { WL_SCAN("ESCAN Completed scan: %s\n", aborted ? "Aborted" : "Done"); cfg80211_scan_done(scan_request, aborted); brcmf_set_mpc(ndev, 1); } - if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { + if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { WL_ERR("Scan complete while device not scanning\n"); return -EPERM; } @@ -1007,7 +847,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, } static s32 -brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, +brcmf_run_escan(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, struct cfg80211_scan_request *request, u16 action) { s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + @@ -1037,7 +877,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, params->sync_id = cpu_to_le16(0x1234); err = brcmf_dev_iovar_setbuf(ndev, "escan", params, params_size, - cfg->escan_ioctl_buf, BRCMF_DCMD_MEDLEN); + cfg_priv->escan_ioctl_buf, BRCMF_DCMD_MEDLEN); if (err) { if (err == -EBUSY) WL_INFO("system busy : escan canceled\n"); @@ -1051,7 +891,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, } static s32 -brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, +brcmf_do_escan(struct brcmf_cfg80211_priv *cfg_priv, struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request) { s32 err; @@ -1059,10 +899,10 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, struct brcmf_scan_results *results; WL_SCAN("Enter\n"); - cfg->escan_info.ndev = ndev; - cfg->escan_info.wiphy = wiphy; - cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING; - passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); + cfg_priv->escan_info.ndev = ndev; + cfg_priv->escan_info.wiphy = wiphy; + cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_SCANNING; + passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan)); if (err) { @@ -1070,12 +910,12 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, return err; } brcmf_set_mpc(ndev, 0); - results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; + results = (struct brcmf_scan_results *)cfg_priv->escan_info.escan_buf; results->version = 0; results->count = 0; results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE; - err = brcmf_run_escan(cfg, ndev, request, WL_ESCAN_ACTION_START); + err = brcmf_run_escan(cfg_priv, ndev, request, WL_ESCAN_ACTION_START); if (err) brcmf_set_mpc(ndev, 1); return err; @@ -1086,9 +926,9 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid) { - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct cfg80211_ssid *ssids; - struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; + struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int; __le32 passive_scan; bool escan_req; bool spec_scan; @@ -1097,23 +937,23 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, WL_SCAN("START ESCAN\n"); - if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { - WL_ERR("Scanning already : status (%lu)\n", cfg->status); + if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { + WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status); return -EAGAIN; } - if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) { + if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) { WL_ERR("Scanning being aborted : status (%lu)\n", - cfg->status); + cfg_priv->status); return -EAGAIN; } - if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) { + if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { WL_ERR("Connecting : status (%lu)\n", - cfg->status); + cfg_priv->status); return -EAGAIN; } /* Arm scan timeout timer */ - mod_timer(&cfg->escan_timeout, jiffies + + mod_timer(&cfg_priv->escan_timeout, jiffies + WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); escan_req = false; @@ -1127,10 +967,10 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, ssids = this_ssid; } - cfg->scan_request = request; - set_bit(WL_STATUS_SCANNING, &cfg->status); + cfg_priv->scan_request = request; + set_bit(WL_STATUS_SCANNING, &cfg_priv->status); if (escan_req) { - err = brcmf_do_escan(cfg, wiphy, ndev, request); + err = brcmf_do_escan(cfg_priv, wiphy, ndev, request); if (!err) return err; else @@ -1149,7 +989,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, } else WL_SCAN("Broadcast scan\n"); - passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); + passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan)); if (err) { @@ -1174,10 +1014,10 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, return 0; scan_out: - clear_bit(WL_STATUS_SCANNING, &cfg->status); - if (timer_pending(&cfg->escan_timeout)) - del_timer_sync(&cfg->escan_timeout); - cfg->scan_request = NULL; + clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); + if (timer_pending(&cfg_priv->escan_timeout)) + del_timer_sync(&cfg_priv->escan_timeout); + cfg_priv->scan_request = NULL; return err; } @@ -1186,7 +1026,7 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { struct net_device *ndev = request->wdev->netdev; - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); s32 err = 0; WL_TRACE("Enter\n"); @@ -1194,9 +1034,9 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, if (!check_sys_up(wiphy)) return -EIO; - if (cfg->iscan_on) + if (cfg_priv->iscan_on) err = brcmf_cfg80211_iscan(wiphy, ndev, request, NULL); - else if (cfg->escan_on) + else if (cfg_priv->escan_on) err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL); if (err) @@ -1243,8 +1083,8 @@ static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l) static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_to_ndev(cfg_priv); s32 err = 0; WL_TRACE("Enter\n"); @@ -1252,30 +1092,30 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return -EIO; if (changed & WIPHY_PARAM_RTS_THRESHOLD && - (cfg->conf->rts_threshold != wiphy->rts_threshold)) { - cfg->conf->rts_threshold = wiphy->rts_threshold; - err = brcmf_set_rts(ndev, cfg->conf->rts_threshold); + (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) { + cfg_priv->conf->rts_threshold = wiphy->rts_threshold; + err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold); if (!err) goto done; } if (changed & WIPHY_PARAM_FRAG_THRESHOLD && - (cfg->conf->frag_threshold != wiphy->frag_threshold)) { - cfg->conf->frag_threshold = wiphy->frag_threshold; - err = brcmf_set_frag(ndev, cfg->conf->frag_threshold); + (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) { + cfg_priv->conf->frag_threshold = wiphy->frag_threshold; + err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold); if (!err) goto done; } if (changed & WIPHY_PARAM_RETRY_LONG - && (cfg->conf->retry_long != wiphy->retry_long)) { - cfg->conf->retry_long = wiphy->retry_long; - err = brcmf_set_retry(ndev, cfg->conf->retry_long, true); + && (cfg_priv->conf->retry_long != wiphy->retry_long)) { + cfg_priv->conf->retry_long = wiphy->retry_long; + err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true); if (!err) goto done; } if (changed & WIPHY_PARAM_RETRY_SHORT - && (cfg->conf->retry_short != wiphy->retry_short)) { - cfg->conf->retry_short = wiphy->retry_short; - err = brcmf_set_retry(ndev, cfg->conf->retry_short, false); + && (cfg_priv->conf->retry_short != wiphy->retry_short)) { + cfg_priv->conf->retry_short = wiphy->retry_short; + err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false); if (!err) goto done; } @@ -1285,6 +1125,61 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return err; } +static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item) +{ + switch (item) { + case WL_PROF_SEC: + return &cfg_priv->profile->sec; + case WL_PROF_BSSID: + return &cfg_priv->profile->bssid; + case WL_PROF_SSID: + return &cfg_priv->profile->ssid; + } + WL_ERR("invalid item (%d)\n", item); + return NULL; +} + +static s32 +brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv, + const struct brcmf_event_msg *e, void *data, s32 item) +{ + s32 err = 0; + struct brcmf_ssid *ssid; + + switch (item) { + case WL_PROF_SSID: + ssid = (struct brcmf_ssid *) data; + memset(cfg_priv->profile->ssid.SSID, 0, + sizeof(cfg_priv->profile->ssid.SSID)); + memcpy(cfg_priv->profile->ssid.SSID, + ssid->SSID, ssid->SSID_len); + cfg_priv->profile->ssid.SSID_len = ssid->SSID_len; + break; + case WL_PROF_BSSID: + if (data) + memcpy(cfg_priv->profile->bssid, data, ETH_ALEN); + else + memset(cfg_priv->profile->bssid, 0, ETH_ALEN); + break; + case WL_PROF_SEC: + memcpy(&cfg_priv->profile->sec, data, + sizeof(cfg_priv->profile->sec)); + break; + case WL_PROF_BEACONINT: + cfg_priv->profile->beacon_interval = *(u16 *)data; + break; + case WL_PROF_DTIMPERIOD: + cfg_priv->profile->dtim_period = *(u8 *)data; + break; + default: + WL_ERR("unsupported item (%d)\n", item); + err = -EOPNOTSUPP; + break; + } + + return err; +} + static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) { memset(prof, 0, sizeof(*prof)); @@ -1317,20 +1212,20 @@ static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, } } -static void brcmf_link_down(struct brcmf_cfg80211_info *cfg) +static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv) { struct net_device *ndev = NULL; s32 err = 0; WL_TRACE("Enter\n"); - if (cfg->link_up) { - ndev = cfg_to_ndev(cfg); + if (cfg_priv->link_up) { + ndev = cfg_to_ndev(cfg_priv); WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0); if (err) WL_ERR("WLC_DISASSOC failed (%d)\n", err); - cfg->link_up = false; + cfg_priv->link_up = false; } WL_TRACE("Exit\n"); } @@ -1339,13 +1234,13 @@ static s32 brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct brcmf_join_params join_params; size_t join_params_size = 0; s32 err = 0; s32 wsec = 0; s32 bcnprd; + struct brcmf_ssid ssid; WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) @@ -1358,7 +1253,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, return -EOPNOTSUPP; } - set_bit(WL_STATUS_CONNECTING, &cfg->status); + set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); if (params->bssid) WL_CONN("BSSID: %pM\n", params->bssid); @@ -1421,38 +1316,40 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, memset(&join_params, 0, sizeof(struct brcmf_join_params)); /* SSID */ - profile->ssid.SSID_len = min_t(u32, params->ssid_len, 32); - memcpy(profile->ssid.SSID, params->ssid, profile->ssid.SSID_len); - memcpy(join_params.ssid_le.SSID, params->ssid, profile->ssid.SSID_len); - join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); + ssid.SSID_len = min_t(u32, params->ssid_len, 32); + memcpy(ssid.SSID, params->ssid, ssid.SSID_len); + memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len); + join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); join_params_size = sizeof(join_params.ssid_le); + brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); /* BSSID */ if (params->bssid) { memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN); join_params_size = sizeof(join_params.ssid_le) + BRCMF_ASSOC_PARAMS_FIXED_SIZE; - memcpy(profile->bssid, params->bssid, ETH_ALEN); } else { memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); - memset(profile->bssid, 0, ETH_ALEN); } + brcmf_update_prof(cfg_priv, NULL, + &join_params.params_le.bssid, WL_PROF_BSSID); + /* Channel */ if (params->channel) { u32 target_channel; - cfg->channel = + cfg_priv->channel = ieee80211_frequency_to_channel( params->channel->center_freq); if (params->channel_fixed) { /* adding chanspec */ - brcmf_ch_to_chanspec(cfg->channel, + brcmf_ch_to_chanspec(cfg_priv->channel, &join_params, &join_params_size); } /* set channel for starter */ - target_channel = cfg->channel; + target_channel = cfg_priv->channel; err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL, &target_channel); if (err) { @@ -1460,9 +1357,9 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, goto done; } } else - cfg->channel = 0; + cfg_priv->channel = 0; - cfg->ibss_starter = false; + cfg_priv->ibss_starter = false; err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, @@ -1474,7 +1371,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, done: if (err) - clear_bit(WL_STATUS_CONNECTING, &cfg->status); + clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); WL_TRACE("Exit\n"); return err; } @@ -1482,14 +1379,14 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); s32 err = 0; WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) return -EIO; - brcmf_link_down(cfg); + brcmf_link_down(cfg_priv); WL_TRACE("Exit\n"); @@ -1499,8 +1396,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) static s32 brcmf_set_wpa_version(struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1517,7 +1413,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, WL_ERR("set wpa_auth failed (%d)\n", err); return err; } - sec = &profile->sec; + sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); sec->wpa_versions = sme->crypto.wpa_versions; return err; } @@ -1525,8 +1421,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, static s32 brcmf_set_auth_type(struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1557,7 +1452,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, WL_ERR("set auth failed (%d)\n", err); return err; } - sec = &profile->sec; + sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); sec->auth_type = sme->auth_type; return err; } @@ -1566,8 +1461,7 @@ static s32 brcmf_set_set_cipher(struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; s32 pval = 0; s32 gval = 0; @@ -1623,7 +1517,7 @@ brcmf_set_set_cipher(struct net_device *ndev, return err; } - sec = &profile->sec; + sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; sec->cipher_group = sme->crypto.cipher_group; @@ -1633,8 +1527,7 @@ brcmf_set_set_cipher(struct net_device *ndev, static s32 brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1680,76 +1573,74 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) return err; } } - sec = &profile->sec; + sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); sec->wpa_auth = sme->crypto.akm_suites[0]; return err; } static s32 -brcmf_set_sharedkey(struct net_device *ndev, - struct cfg80211_connect_params *sme) +brcmf_set_wep_sharedkey(struct net_device *ndev, + struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; struct brcmf_wsec_key key; s32 val; s32 err = 0; - s32 bssidx; WL_CONN("key len (%d)\n", sme->key_len); if (sme->key_len == 0) return 0; - sec = &profile->sec; + sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n", sec->wpa_versions, sec->cipher_pairwise); if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) return 0; - if (!(sec->cipher_pairwise & - (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104))) - return 0; - - memset(&key, 0, sizeof(key)); - key.len = (u32) sme->key_len; - key.index = (u32) sme->key_idx; - if (key.len > sizeof(key.data)) { - WL_ERR("Too long key length (%u)\n", key.len); - return -EINVAL; - } - memcpy(key.data, sme->key, key.len); - key.flags = BRCMF_PRIMARY_KEY; - switch (sec->cipher_pairwise) { - case WLAN_CIPHER_SUITE_WEP40: - key.algo = CRYPTO_ALGO_WEP1; - break; - case WLAN_CIPHER_SUITE_WEP104: - key.algo = CRYPTO_ALGO_WEP128; - break; - default: - WL_ERR("Invalid algorithm (%d)\n", - sme->crypto.ciphers_pairwise[0]); - return -EINVAL; - } - /* Set the new key/index */ - WL_CONN("key length (%d) key index (%d) algo (%d)\n", - key.len, key.index, key.algo); - WL_CONN("key \"%s\"\n", key.data); - bssidx = brcmf_find_bssidx(cfg, ndev); - err = send_key_to_dongle(cfg, bssidx, ndev, &key); - if (err) - return err; - - if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { - WL_CONN("set auth_type to shared key\n"); - val = WL_AUTH_SHARED_KEY; /* shared key */ - err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", val, bssidx); + if (sec->cipher_pairwise & + (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)) { + memset(&key, 0, sizeof(key)); + key.len = (u32) sme->key_len; + key.index = (u32) sme->key_idx; + if (key.len > sizeof(key.data)) { + WL_ERR("Too long key length (%u)\n", key.len); + return -EINVAL; + } + memcpy(key.data, sme->key, key.len); + key.flags = BRCMF_PRIMARY_KEY; + switch (sec->cipher_pairwise) { + case WLAN_CIPHER_SUITE_WEP40: + key.algo = CRYPTO_ALGO_WEP1; + break; + case WLAN_CIPHER_SUITE_WEP104: + key.algo = CRYPTO_ALGO_WEP128; + break; + default: + WL_ERR("Invalid algorithm (%d)\n", + sme->crypto.ciphers_pairwise[0]); + return -EINVAL; + } + /* Set the new key/index */ + WL_CONN("key length (%d) key index (%d) algo (%d)\n", + key.len, key.index, key.algo); + WL_CONN("key \"%s\"\n", key.data); + err = send_key_to_dongle(ndev, &key); if (err) - WL_ERR("set auth failed (%d)\n", err); + return err; + + if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { + WL_CONN("set auth_type to shared key\n"); + val = 1; /* shared key */ + err = brcmf_dev_intvar_set(ndev, "auth", val); + if (err) { + WL_ERR("set auth failed (%d)\n", err); + return err; + } + } } return err; } @@ -1758,8 +1649,7 @@ static s32 brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct ieee80211_channel *chan = sme->channel; struct brcmf_join_params join_params; size_t join_params_size; @@ -1776,15 +1666,15 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, return -EOPNOTSUPP; } - set_bit(WL_STATUS_CONNECTING, &cfg->status); + set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); if (chan) { - cfg->channel = + cfg_priv->channel = ieee80211_frequency_to_channel(chan->center_freq); WL_CONN("channel (%d), center_req (%d)\n", - cfg->channel, chan->center_freq); + cfg_priv->channel, chan->center_freq); } else - cfg->channel = 0; + cfg_priv->channel = 0; WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len); @@ -1812,20 +1702,20 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - err = brcmf_set_sharedkey(ndev, sme); + err = brcmf_set_wep_sharedkey(ndev, sme); if (err) { - WL_ERR("brcmf_set_sharedkey failed (%d)\n", err); + WL_ERR("brcmf_set_wep_sharedkey failed (%d)\n", err); goto done; } memset(&join_params, 0, sizeof(join_params)); join_params_size = sizeof(join_params.ssid_le); - profile->ssid.SSID_len = min_t(u32, - sizeof(ssid.SSID), (u32)sme->ssid_len); - memcpy(&join_params.ssid_le.SSID, sme->ssid, profile->ssid.SSID_len); - memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len); - join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); + ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), (u32)sme->ssid_len); + memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len); + memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len); + join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); + brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); @@ -1833,7 +1723,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, WL_CONN("ssid \"%s\", len (%d)\n", ssid.SSID, ssid.SSID_len); - brcmf_ch_to_chanspec(cfg->channel, + brcmf_ch_to_chanspec(cfg_priv->channel, &join_params, &join_params_size); err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, &join_params, join_params_size); @@ -1842,7 +1732,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, done: if (err) - clear_bit(WL_STATUS_CONNECTING, &cfg->status); + clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); WL_TRACE("Exit\n"); return err; } @@ -1851,8 +1741,7 @@ static s32 brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct brcmf_scb_val_le scbval; s32 err = 0; @@ -1860,16 +1749,16 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, if (!check_sys_up(wiphy)) return -EIO; - clear_bit(WL_STATUS_CONNECTED, &cfg->status); + clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status); - memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); + memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN); scbval.val = cpu_to_le32(reason_code); err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval, sizeof(struct brcmf_scb_val_le)); if (err) WL_ERR("error (%d)\n", err); - cfg->link_up = false; + cfg_priv->link_up = false; WL_TRACE("Exit\n"); return err; @@ -1880,8 +1769,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, s32 mbm) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_to_ndev(cfg_priv); u16 txpwrmw; s32 err = 0; s32 disable = 0; @@ -1917,7 +1806,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, (s32) (brcmf_mw_to_qdbm(txpwrmw))); if (err) WL_ERR("qtxpower error (%d)\n", err); - cfg->conf->tx_power = dbm; + cfg_priv->conf->tx_power = dbm; done: WL_TRACE("Exit\n"); @@ -1926,8 +1815,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_to_ndev(cfg_priv); s32 txpwrdbm; u8 result; s32 err = 0; @@ -1954,19 +1843,16 @@ static s32 brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool unicast, bool multicast) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); u32 index; u32 wsec; s32 err = 0; - s32 bssidx; WL_TRACE("Enter\n"); WL_CONN("key index (%d)\n", key_idx); if (!check_sys_up(wiphy)) return -EIO; - bssidx = brcmf_find_bssidx(cfg, ndev); - err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); if (err) { WL_ERR("WLC_GET_WSEC error (%d)\n", err); goto done; @@ -1989,11 +1875,9 @@ static s32 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, const u8 *mac_addr, struct key_params *params) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_wsec_key key; struct brcmf_wsec_key_le key_le; s32 err = 0; - s32 bssidx; memset(&key, 0, sizeof(key)); key.index = (u32) key_idx; @@ -2002,13 +1886,12 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, if (!is_multicast_ether_addr(mac_addr)) memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); key.len = (u32) params->key_len; - bssidx = brcmf_find_bssidx(cfg, ndev); /* check for key index change */ if (key.len == 0) { /* key delete */ - err = send_key_to_dongle(cfg, bssidx, ndev, &key); + err = send_key_to_dongle(ndev, &key); if (err) - WL_ERR("key delete error (%d)\n", err); + return err; } else { if (key.len > sizeof(key.data)) { WL_ERR("Invalid key length (%d)\n", key.len); @@ -2064,12 +1947,12 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, convert_key_from_CPU(&key, &key_le); brcmf_netdev_wait_pend8021x(ndev); - err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, - sizeof(key_le), - cfg->extra_buf, - WL_EXTRA_BUF_MAX, bssidx); - if (err) - WL_ERR("wsec_key error (%d)\n", err); + err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, + sizeof(key_le)); + if (err) { + WL_ERR("WLC_SET_KEY error (%d)\n", err); + return err; + } } return err; } @@ -2079,13 +1962,11 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_wsec_key key; s32 val; s32 wsec; s32 err = 0; u8 keybuf[8]; - s32 bssidx; WL_TRACE("Enter\n"); WL_CONN("key index (%d)\n", key_idx); @@ -2112,33 +1993,25 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: key.algo = CRYPTO_ALGO_WEP1; - val = WEP_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); break; case WLAN_CIPHER_SUITE_WEP104: key.algo = CRYPTO_ALGO_WEP128; - val = WEP_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); break; case WLAN_CIPHER_SUITE_TKIP: - if (cfg->conf->mode != WL_MODE_AP) { - WL_CONN("Swapping key\n"); - memcpy(keybuf, &key.data[24], sizeof(keybuf)); - memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); - memcpy(&key.data[16], keybuf, sizeof(keybuf)); - } + memcpy(keybuf, &key.data[24], sizeof(keybuf)); + memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); + memcpy(&key.data[16], keybuf, sizeof(keybuf)); key.algo = CRYPTO_ALGO_TKIP; - val = TKIP_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); break; case WLAN_CIPHER_SUITE_AES_CMAC: key.algo = CRYPTO_ALGO_AES_CCM; - val = AES_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); break; case WLAN_CIPHER_SUITE_CCMP: key.algo = CRYPTO_ALGO_AES_CCM; - val = AES_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_CCMP\n"); break; default: @@ -2147,23 +2020,28 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, goto done; } - bssidx = brcmf_find_bssidx(cfg, ndev); - err = send_key_to_dongle(cfg, bssidx, ndev, &key); + err = send_key_to_dongle(ndev, &key); /* Set the new key/index */ if (err) goto done; - err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); + val = WEP_ENABLED; + err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); if (err) { WL_ERR("get wsec error (%d)\n", err); goto done; } + wsec &= ~(WEP_ENABLED); wsec |= val; - err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx); + err = brcmf_dev_intvar_set(ndev, "wsec", wsec); if (err) { WL_ERR("set wsec error (%d)\n", err); goto done; } + val = 1; /* assume shared key. otherwise 0 */ + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); + if (err) + WL_ERR("WLC_SET_AUTH error (%d)\n", err); done: WL_TRACE("Exit\n"); return err; @@ -2173,10 +2051,10 @@ static s32 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool pairwise, const u8 *mac_addr) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_wsec_key key; s32 err = 0; - s32 bssidx; + s32 val; + s32 wsec; WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) @@ -2191,8 +2069,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, WL_CONN("key index (%d)\n", key_idx); /* Set the new key/index */ - bssidx = brcmf_find_bssidx(cfg, ndev); - err = send_key_to_dongle(cfg, bssidx, ndev, &key); + err = send_key_to_dongle(ndev, &key); if (err) { if (err == -EINVAL) { if (key.index >= DOT11_MAX_DEFAULT_KEYS) @@ -2201,8 +2078,35 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, } /* Ignore this error, may happen during DISASSOC */ err = -EAGAIN; + goto done; + } + + val = 0; + err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); + if (err) { + WL_ERR("get wsec error (%d)\n", err); + /* Ignore this error, may happen during DISASSOC */ + err = -EAGAIN; + goto done; + } + wsec &= ~(WEP_ENABLED); + wsec |= val; + err = brcmf_dev_intvar_set(ndev, "wsec", wsec); + if (err) { + WL_ERR("set wsec error (%d)\n", err); + /* Ignore this error, may happen during DISASSOC */ + err = -EAGAIN; + goto done; } + val = 0; /* assume open key. otherwise 1 */ + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); + if (err) { + WL_ERR("WLC_SET_AUTH error (%d)\n", err); + /* Ignore this error, may happen during DISASSOC */ + err = -EAGAIN; + } +done: WL_TRACE("Exit\n"); return err; } @@ -2213,12 +2117,10 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, void (*callback) (void *cookie, struct key_params * params)) { struct key_params params; - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct brcmf_cfg80211_security *sec; s32 wsec; s32 err = 0; - s32 bssidx; WL_TRACE("Enter\n"); WL_CONN("key index (%d)\n", key_idx); @@ -2227,17 +2129,16 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, memset(¶ms, 0, sizeof(params)); - bssidx = brcmf_find_bssidx(cfg, ndev); - err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); if (err) { WL_ERR("WLC_GET_WSEC error (%d)\n", err); /* Ignore this error, may happen during DISASSOC */ err = -EAGAIN; goto done; } - switch (wsec & ~SES_OW_ENABLED) { + switch (wsec) { case WEP_ENABLED: - sec = &profile->sec; + sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { params.cipher = WLAN_CIPHER_SUITE_WEP40; WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); @@ -2277,73 +2178,53 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, static s32 brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, - u8 *mac, struct station_info *sinfo) + u8 *mac, struct station_info *sinfo) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_cfg80211_profile *profile = cfg->profile; + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct brcmf_scb_val_le scb_val; int rssi; s32 rate; s32 err = 0; - u8 *bssid = profile->bssid; - struct brcmf_sta_info_le *sta_info_le; + u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID); - WL_TRACE("Enter, MAC %pM\n", mac); + WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) return -EIO; - if (cfg->conf->mode == WL_MODE_AP) { - err = brcmf_dev_iovar_getbuf(ndev, "sta_info", mac, ETH_ALEN, - cfg->dcmd_buf, - WL_DCMD_LEN_MAX); - if (err < 0) { - WL_ERR("GET STA INFO failed, %d\n", err); - goto done; - } - sta_info_le = (struct brcmf_sta_info_le *)cfg->dcmd_buf; + if (memcmp(mac, bssid, ETH_ALEN)) { + WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X" + "wl_bssid-%X:%X:%X:%X:%X:%X\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + bssid[0], bssid[1], bssid[2], bssid[3], + bssid[4], bssid[5]); + err = -ENOENT; + goto done; + } - sinfo->filled = STATION_INFO_INACTIVE_TIME; - sinfo->inactive_time = le32_to_cpu(sta_info_le->idle) * 1000; - if (le32_to_cpu(sta_info_le->flags) & BRCMF_STA_ASSOC) { - sinfo->filled |= STATION_INFO_CONNECTED_TIME; - sinfo->connected_time = le32_to_cpu(sta_info_le->in); - } - WL_TRACE("STA idle time : %d ms, connected time :%d sec\n", - sinfo->inactive_time, sinfo->connected_time); - } else if (cfg->conf->mode == WL_MODE_BSS) { - if (memcmp(mac, bssid, ETH_ALEN)) { - WL_ERR("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", - mac, bssid); - err = -ENOENT; - goto done; - } - /* Report the current tx rate */ - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate); + /* Report the current tx rate */ + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate); + if (err) { + WL_ERR("Could not get rate (%d)\n", err); + } else { + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.legacy = rate * 5; + WL_CONN("Rate %d Mbps\n", rate / 2); + } + + if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { + memset(&scb_val, 0, sizeof(scb_val)); + err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, + sizeof(struct brcmf_scb_val_le)); if (err) { - WL_ERR("Could not get rate (%d)\n", err); - goto done; + WL_ERR("Could not get rssi (%d)\n", err); } else { - sinfo->filled |= STATION_INFO_TX_BITRATE; - sinfo->txrate.legacy = rate * 5; - WL_CONN("Rate %d Mbps\n", rate / 2); + rssi = le32_to_cpu(scb_val.val); + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = rssi; + WL_CONN("RSSI %d dBm\n", rssi); } + } - if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) { - memset(&scb_val, 0, sizeof(scb_val)); - err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, - sizeof(scb_val)); - if (err) { - WL_ERR("Could not get rssi (%d)\n", err); - goto done; - } else { - rssi = le32_to_cpu(scb_val.val); - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = rssi; - WL_CONN("RSSI %d dBm\n", rssi); - } - } - } else - err = -EPERM; done: WL_TRACE("Exit\n"); return err; @@ -2355,7 +2236,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, { s32 pm; s32 err = 0; - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); WL_TRACE("Enter\n"); @@ -2363,13 +2244,14 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, * Powersave enable/disable request is coming from the * cfg80211 even before the interface is up. In that * scenario, driver will be storing the power save - * preference in cfg struct to apply this to + * preference in cfg_priv struct to apply this to * FW later while initializing the dongle */ - cfg->pwr_save = enabled; - if (!test_bit(WL_STATUS_READY, &cfg->status)) { + cfg_priv->pwr_save = enabled; + if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { - WL_INFO("Device is not ready, storing the value in cfg_info struct\n"); + WL_INFO("Device is not ready," + "storing the value in cfg_priv struct\n"); goto done; } @@ -2447,10 +2329,10 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, return err; } -static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, +static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv, struct brcmf_bss_info_le *bi) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); struct ieee80211_channel *notify_channel; struct cfg80211_bss *bss; struct ieee80211_supported_band *band; @@ -2514,14 +2396,14 @@ next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss) le32_to_cpu(bss->length)); } -static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv) { struct brcmf_scan_results *bss_list; struct brcmf_bss_info_le *bi = NULL; /* must be initialized */ s32 err = 0; int i; - bss_list = cfg->bss_list; + bss_list = cfg_priv->bss_list; if (bss_list->version != BRCMF_BSS_INFO_VERSION) { WL_ERR("Version %d != WL_BSS_INFO_VERSION\n", bss_list->version); @@ -2530,17 +2412,17 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg) WL_SCAN("scanned AP count (%d)\n", bss_list->count); for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) { bi = next_bss_le(bss_list, bi); - err = brcmf_inform_single_bss(cfg, bi); + err = brcmf_inform_single_bss(cfg_priv, bi); if (err) break; } return err; } -static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, +static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const u8 *bssid) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); struct ieee80211_channel *notify_channel; struct brcmf_bss_info_le *bi = NULL; struct ieee80211_supported_band *band; @@ -2615,9 +2497,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, return err; } -static bool brcmf_is_ibssmode(struct brcmf_cfg80211_info *cfg) +static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv) { - return cfg->conf->mode == WL_MODE_IBSS; + return cfg_priv->conf->mode == WL_MODE_IBSS; } /* @@ -2634,62 +2516,22 @@ static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) totlen = buflen; /* find tagged parameter */ - while (totlen >= TLV_HDR_LEN) { + while (totlen >= 2) { int len = elt->len; /* validate remaining totlen */ - if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN))) + if ((elt->id == key) && (totlen >= (len + 2))) return elt; - elt = (struct brcmf_tlv *) ((u8 *) elt + (len + TLV_HDR_LEN)); - totlen -= (len + TLV_HDR_LEN); - } - - return NULL; -} - -/* Is any of the tlvs the expected entry? If - * not update the tlvs buffer pointer/length. - */ -static bool -brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, - u8 *oui, u32 oui_len, u8 type) -{ - /* If the contents match the OUI and the type */ - if (ie[TLV_LEN_OFF] >= oui_len + 1 && - !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) && - type == ie[TLV_BODY_OFF + oui_len]) { - return true; + elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2)); + totlen -= (len + 2); } - if (tlvs == NULL) - return false; - /* point to the next ie */ - ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN; - /* calculate the length of the rest of the buffer */ - *tlvs_len -= (int)(ie - *tlvs); - /* update the pointer to the start of the buffer */ - *tlvs = ie; - - return false; -} - -struct brcmf_vs_tlv * -brcmf_find_wpaie(u8 *parse, u32 len) -{ - struct brcmf_tlv *ie; - - while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_WPA))) { - if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len, - WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE)) - return (struct brcmf_vs_tlv *)ie; - } return NULL; } -static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_bss_info_le *bi; struct brcmf_ssid *ssid; struct brcmf_tlv *tim; @@ -2700,21 +2542,21 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) s32 err = 0; WL_TRACE("Enter\n"); - if (brcmf_is_ibssmode(cfg)) + if (brcmf_is_ibssmode(cfg_priv)) return err; - ssid = &profile->ssid; + ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID); - *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); - err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_GET_BSS_INFO, - cfg->extra_buf, WL_EXTRA_BUF_MAX); + *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); + err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO, + cfg_priv->extra_buf, WL_EXTRA_BUF_MAX); if (err) { WL_ERR("Could not get bss info %d\n", err); goto update_bss_info_out; } - bi = (struct brcmf_bss_info_le *)(cfg->extra_buf + 4); - err = brcmf_inform_single_bss(cfg, bi); + bi = (struct brcmf_bss_info_le *)(cfg_priv->extra_buf + 4); + err = brcmf_inform_single_bss(cfg_priv, bi); if (err) goto update_bss_info_out; @@ -2732,7 +2574,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) * so we speficially query dtim information to dongle. */ u32 var; - err = brcmf_dev_intvar_get(cfg_to_ndev(cfg), + err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv), "dtim_assoc", &var); if (err) { WL_ERR("wl dtim_assoc failed (%d)\n", err); @@ -2741,22 +2583,20 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) dtim_period = (u8)var; } - profile->beacon_interval = beacon_interval; - profile->dtim_period = dtim_period; + brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT); + brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD); update_bss_info_out: WL_TRACE("Exit"); return err; } -static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) +static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); - struct escan_info *escan = &cfg->escan_info; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); struct brcmf_ssid ssid; - set_bit(WL_STATUS_SCAN_ABORTING, &cfg->status); - if (cfg->iscan_on) { + if (cfg_priv->iscan_on) { iscan->state = WL_ISCAN_STATE_IDLE; if (iscan->timer_on) { @@ -2769,40 +2609,27 @@ static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) /* Abort iscan running in FW */ memset(&ssid, 0, sizeof(ssid)); brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT); - - if (cfg->scan_request) { - /* Indidate scan abort to cfg80211 layer */ - WL_INFO("Terminating scan in progress\n"); - cfg80211_scan_done(cfg->scan_request, true); - cfg->scan_request = NULL; - } } - if (cfg->escan_on && cfg->scan_request) { - escan->escan_state = WL_ESCAN_STATE_IDLE; - brcmf_notify_escan_complete(cfg, escan->ndev, true, true); - } - clear_bit(WL_STATUS_SCANNING, &cfg->status); - clear_bit(WL_STATUS_SCAN_ABORTING, &cfg->status); } static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, bool aborted) { - struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan); - struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); + struct net_device *ndev = cfg_to_ndev(cfg_priv); - if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { + if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { WL_ERR("Scan complete while device not scanning\n"); return; } - if (cfg->scan_request) { + if (cfg_priv->scan_request) { WL_SCAN("ISCAN Completed scan: %s\n", aborted ? "Aborted" : "Done"); - cfg80211_scan_done(cfg->scan_request, aborted); + cfg80211_scan_done(cfg_priv->scan_request, aborted); brcmf_set_mpc(ndev, 1); - cfg->scan_request = NULL; + cfg_priv->scan_request = NULL; } - cfg->iscan_kickstart = false; + cfg_priv->iscan_kickstart = false; } static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan) @@ -2855,21 +2682,21 @@ brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, return err; } -static s32 brcmf_iscan_done(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; s32 err = 0; iscan->state = WL_ISCAN_STATE_IDLE; - brcmf_inform_bss(cfg); + brcmf_inform_bss(cfg_priv); brcmf_notify_iscan_complete(iscan, false); return err; } -static s32 brcmf_iscan_pending(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; s32 err = 0; /* Reschedule the timer */ @@ -2879,12 +2706,12 @@ static s32 brcmf_iscan_pending(struct brcmf_cfg80211_info *cfg) return err; } -static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; s32 err = 0; - brcmf_inform_bss(cfg); + brcmf_inform_bss(cfg_priv); brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE); /* Reschedule the timer */ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); @@ -2893,9 +2720,9 @@ static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_info *cfg) return err; } -static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; s32 err = 0; iscan->state = WL_ISCAN_STATE_IDLE; @@ -2909,7 +2736,7 @@ static void brcmf_cfg80211_iscan_handler(struct work_struct *work) struct brcmf_cfg80211_iscan_ctrl *iscan = container_of(work, struct brcmf_cfg80211_iscan_ctrl, work); - struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan); + struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); struct brcmf_cfg80211_iscan_eloop *el = &iscan->el; u32 status = BRCMF_SCAN_RESULTS_PARTIAL; @@ -2918,12 +2745,12 @@ static void brcmf_cfg80211_iscan_handler(struct work_struct *work) iscan->timer_on = 0; } - if (brcmf_get_iscan_results(iscan, &status, &cfg->bss_list)) { + if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) { status = BRCMF_SCAN_RESULTS_ABORTED; WL_ERR("Abort iscan\n"); } - el->handler[status](cfg); + el->handler[status](cfg_priv); } static void brcmf_iscan_timer(unsigned long data) @@ -2938,11 +2765,11 @@ static void brcmf_iscan_timer(unsigned long data) } } -static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); - if (cfg->iscan_on) { + if (cfg_priv->iscan_on) { iscan->state = WL_ISCAN_STATE_IDLE; INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler); } @@ -2960,21 +2787,21 @@ static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el) el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted; } -static s32 brcmf_init_iscan(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); int err = 0; - if (cfg->iscan_on) { - iscan->ndev = cfg_to_ndev(cfg); + if (cfg_priv->iscan_on) { + iscan->ndev = cfg_to_ndev(cfg_priv); brcmf_init_iscan_eloop(&iscan->el); iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS; init_timer(&iscan->timer); iscan->timer.data = (unsigned long) iscan; iscan->timer.function = brcmf_iscan_timer; - err = brcmf_invoke_iscan(cfg); + err = brcmf_invoke_iscan(cfg_priv); if (!err) - iscan->data = cfg; + iscan->data = cfg_priv; } return err; @@ -2982,23 +2809,23 @@ static s32 brcmf_init_iscan(struct brcmf_cfg80211_info *cfg) static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work) { - struct brcmf_cfg80211_info *cfg = - container_of(work, struct brcmf_cfg80211_info, + struct brcmf_cfg80211_priv *cfg_priv = + container_of(work, struct brcmf_cfg80211_priv, escan_timeout_work); - brcmf_notify_escan_complete(cfg, - cfg->escan_info.ndev, true, true); + brcmf_notify_escan_complete(cfg_priv, + cfg_priv->escan_info.ndev, true, true); } static void brcmf_escan_timeout(unsigned long data) { - struct brcmf_cfg80211_info *cfg = - (struct brcmf_cfg80211_info *)data; + struct brcmf_cfg80211_priv *cfg_priv = + (struct brcmf_cfg80211_priv *)data; - if (cfg->scan_request) { + if (cfg_priv->scan_request) { WL_ERR("timer expired\n"); - if (cfg->escan_on) - schedule_work(&cfg->escan_timeout_work); + if (cfg_priv->escan_on) + schedule_work(&cfg_priv->escan_timeout_work); } } @@ -3013,13 +2840,10 @@ brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss, !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) { if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) { - s16 bss_rssi = le16_to_cpu(bss->RSSI); - s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI); - /* preserve max RSSI if the measurements are * both on-channel or both off-channel */ - if (bss_info_rssi > bss_rssi) + if (bss_info_le->RSSI > bss->RSSI) bss->RSSI = bss_info_le->RSSI; } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) && (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) { @@ -3035,7 +2859,7 @@ brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss, } static s32 -brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, +brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -3047,15 +2871,14 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, u32 bi_length; struct brcmf_scan_results *list; u32 i; - bool aborted; status = be32_to_cpu(e->status); - if (!ndev || !cfg->escan_on || - !test_bit(WL_STATUS_SCANNING, &cfg->status)) { + if (!ndev || !cfg_priv->escan_on || + !test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n", - ndev, cfg->escan_on, - !test_bit(WL_STATUS_SCANNING, &cfg->status)); + ndev, cfg_priv->escan_on, + !test_bit(WL_STATUS_SCANNING, &cfg_priv->status)); return -EPERM; } @@ -3066,7 +2889,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, WL_ERR("Invalid escan result (NULL pointer)\n"); goto exit; } - if (!cfg->scan_request) { + if (!cfg_priv->scan_request) { WL_SCAN("result without cfg80211 request\n"); goto exit; } @@ -3086,7 +2909,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, goto exit; } - if (!(cfg_to_wiphy(cfg)->interface_modes & + if (!(cfg_to_wiphy(cfg_priv)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) { if (le16_to_cpu(bss_info_le->capability) & WLAN_CAPABILITY_IBSS) { @@ -3096,7 +2919,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, } list = (struct brcmf_scan_results *) - cfg->escan_info.escan_buf; + cfg_priv->escan_info.escan_buf; if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) { WL_ERR("Buffer is too small: ignoring\n"); goto exit; @@ -3109,20 +2932,27 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, if (brcmf_compare_update_same_bss(bss, bss_info_le)) goto exit; } - memcpy(&(cfg->escan_info.escan_buf[list->buflen]), + memcpy(&(cfg_priv->escan_info.escan_buf[list->buflen]), bss_info_le, bi_length); list->version = le32_to_cpu(bss_info_le->version); list->buflen += bi_length; list->count++; } else { - cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE; - if (cfg->scan_request) { - cfg->bss_list = (struct brcmf_scan_results *) - cfg->escan_info.escan_buf; - brcmf_inform_bss(cfg); - aborted = status != BRCMF_E_STATUS_SUCCESS; - brcmf_notify_escan_complete(cfg, ndev, aborted, - false); + cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE; + if (cfg_priv->scan_request) { + cfg_priv->bss_list = (struct brcmf_scan_results *) + cfg_priv->escan_info.escan_buf; + brcmf_inform_bss(cfg_priv); + if (status == BRCMF_E_STATUS_SUCCESS) { + WL_SCAN("ESCAN Completed\n"); + brcmf_notify_escan_complete(cfg_priv, ndev, + false, false); + } else { + WL_ERR("ESCAN Aborted, Event 0x%x\n", status); + brcmf_notify_escan_complete(cfg_priv, ndev, + true, false); + } + brcmf_set_mpc(ndev, 1); } else WL_ERR("Unexpected scan result 0x%x\n", status); } @@ -3130,18 +2960,18 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, return err; } -static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg) +static void brcmf_init_escan(struct brcmf_cfg80211_priv *cfg_priv) { - if (cfg->escan_on) { - cfg->el.handler[BRCMF_E_ESCAN_RESULT] = + if (cfg_priv->escan_on) { + cfg_priv->el.handler[BRCMF_E_ESCAN_RESULT] = brcmf_cfg80211_escan_handler; - cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE; + cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE; /* Init scan_timeout timer */ - init_timer(&cfg->escan_timeout); - cfg->escan_timeout.data = (unsigned long) cfg; - cfg->escan_timeout.function = brcmf_escan_timeout; - INIT_WORK(&cfg->escan_timeout_work, + init_timer(&cfg_priv->escan_timeout); + cfg_priv->escan_timeout.data = (unsigned long) cfg_priv; + cfg_priv->escan_timeout.function = brcmf_escan_timeout; + INIT_WORK(&cfg_priv->escan_timeout_work, brcmf_cfg80211_escan_timeout_worker); } } @@ -3158,7 +2988,7 @@ static __always_inline void brcmf_delay(u32 ms) static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); /* * Check for WL_STATUS_READY before any function call which @@ -3167,7 +2997,7 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) */ WL_TRACE("Enter\n"); - if (test_bit(WL_STATUS_READY, &cfg->status)) + if (test_bit(WL_STATUS_READY, &cfg_priv->status)) brcmf_invoke_iscan(wiphy_to_cfg(wiphy)); WL_TRACE("Exit\n"); @@ -3177,8 +3007,8 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_to_ndev(cfg_priv); WL_TRACE("Enter\n"); @@ -3192,12 +3022,12 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, * While going to suspend if associated with AP disassociate * from AP to save power while system is in suspended state */ - if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) || - test_bit(WL_STATUS_CONNECTING, &cfg->status)) && - test_bit(WL_STATUS_READY, &cfg->status)) { + if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || + test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && + test_bit(WL_STATUS_READY, &cfg_priv->status)) { WL_INFO("Disassociating from AP" " while entering suspend state\n"); - brcmf_link_down(cfg); + brcmf_link_down(cfg_priv); /* * Make sure WPA_Supplicant receives all the event @@ -3207,13 +3037,21 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, brcmf_delay(500); } - if (test_bit(WL_STATUS_READY, &cfg->status)) - brcmf_abort_scanning(cfg); - else - clear_bit(WL_STATUS_SCANNING, &cfg->status); + set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); + if (test_bit(WL_STATUS_READY, &cfg_priv->status)) + brcmf_term_iscan(cfg_priv); + + if (cfg_priv->scan_request) { + /* Indidate scan abort to cfg80211 layer */ + WL_INFO("Terminating scan in progress\n"); + cfg80211_scan_done(cfg_priv->scan_request, true); + cfg_priv->scan_request = NULL; + } + clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); + clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); /* Turn off watchdog timer */ - if (test_bit(WL_STATUS_READY, &cfg->status)) + if (test_bit(WL_STATUS_READY, &cfg_priv->status)) brcmf_set_mpc(ndev, 1); WL_TRACE("Exit\n"); @@ -3224,14 +3062,14 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, static __used s32 brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len) { - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); u32 buflen; - buflen = brcmf_c_mkiovar(name, buf, len, cfg->dcmd_buf, + buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf, WL_DCMD_LEN_MAX); BUG_ON(!buflen); - return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg->dcmd_buf, + return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf, buflen); } @@ -3239,20 +3077,20 @@ static s32 brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf, s32 buf_len) { - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); u32 len; s32 err = 0; - len = brcmf_c_mkiovar(name, NULL, 0, cfg->dcmd_buf, + len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf, WL_DCMD_LEN_MAX); BUG_ON(!len); - err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg->dcmd_buf, + err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf, WL_DCMD_LEN_MAX); if (err) { WL_ERR("error (%d)\n", err); return err; } - memcpy(buf, cfg->dcmd_buf, buf_len); + memcpy(buf, cfg_priv->dcmd_buf, buf_len); return err; } @@ -3285,8 +3123,8 @@ static s32 brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct pmkid_list *pmkids = &cfg->pmk_list->pmkids; + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids; s32 err = 0; int i; int pmkid_len; @@ -3314,7 +3152,7 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, for (i = 0; i < WLAN_PMKID_LEN; i++) WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]); - err = brcmf_update_pmklist(ndev, cfg->pmk_list, err); + err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); WL_TRACE("Exit\n"); return err; @@ -3324,7 +3162,7 @@ static s32 brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct pmkid_list pmkid; s32 err = 0; int i, pmkid_len; @@ -3341,30 +3179,30 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, for (i = 0; i < WLAN_PMKID_LEN; i++) WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]); - pmkid_len = le32_to_cpu(cfg->pmk_list->pmkids.npmkid); + pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid); for (i = 0; i < pmkid_len; i++) if (!memcmp - (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID, + (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, ETH_ALEN)) break; if ((pmkid_len > 0) && (i < pmkid_len)) { - memset(&cfg->pmk_list->pmkids.pmkid[i], 0, + memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0, sizeof(struct pmkid)); for (; i < (pmkid_len - 1); i++) { - memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, - &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID, + memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, + &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID, ETH_ALEN); - memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, - &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID, + memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID, + &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID, WLAN_PMKID_LEN); } - cfg->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1); + cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1); } else err = -EINVAL; - err = brcmf_update_pmklist(ndev, cfg->pmk_list, err); + err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); WL_TRACE("Exit\n"); return err; @@ -3374,978 +3212,39 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, static s32 brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); s32 err = 0; WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) return -EIO; - memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list)); - err = brcmf_update_pmklist(ndev, cfg->pmk_list, err); + memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list)); + err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); WL_TRACE("Exit\n"); return err; } -/* - * PFN result doesn't have all the info which are - * required by the supplicant - * (For e.g IEs) Do a target Escan so that sched scan results are reported - * via wl_inform_single_bss in the required format. Escan does require the - * scan request in the form of cfg80211_scan_request. For timebeing, create - * cfg80211_scan_request one out of the received PNO event. - */ -static s32 -brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg, - struct net_device *ndev, - const struct brcmf_event_msg *e, void *data) -{ - struct brcmf_pno_net_info_le *netinfo, *netinfo_start; - struct cfg80211_scan_request *request = NULL; - struct cfg80211_ssid *ssid = NULL; - struct ieee80211_channel *channel = NULL; - struct wiphy *wiphy = cfg_to_wiphy(cfg); - int err = 0; - int channel_req = 0; - int band = 0; - struct brcmf_pno_scanresults_le *pfn_result; - u32 result_count; - u32 status; - - WL_SCAN("Enter\n"); +#ifdef CONFIG_NL80211_TESTMODE +static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) +{ + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_priv->wdev->netdev; + struct brcmf_dcmd *dcmd = data; + struct sk_buff *reply; + int ret; - if (e->event_type == cpu_to_be32(BRCMF_E_PFN_NET_LOST)) { - WL_SCAN("PFN NET LOST event. Do Nothing\n"); - return 0; + ret = brcmf_netlink_dcmd(ndev, dcmd); + if (ret == 0) { + reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd)); + nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd); + ret = cfg80211_testmode_reply(reply); } - - pfn_result = (struct brcmf_pno_scanresults_le *)data; - result_count = le32_to_cpu(pfn_result->count); - status = le32_to_cpu(pfn_result->status); - - /* - * PFN event is limited to fit 512 bytes so we may get - * multiple NET_FOUND events. For now place a warning here. - */ - WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE); - WL_SCAN("PFN NET FOUND event. count: %d\n", result_count); - if (result_count > 0) { - int i; - - request = kzalloc(sizeof(*request), GFP_KERNEL); - ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL); - channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL); - if (!request || !ssid || !channel) { - err = -ENOMEM; - goto out_err; - } - - request->wiphy = wiphy; - data += sizeof(struct brcmf_pno_scanresults_le); - netinfo_start = (struct brcmf_pno_net_info_le *)data; - - for (i = 0; i < result_count; i++) { - netinfo = &netinfo_start[i]; - if (!netinfo) { - WL_ERR("Invalid netinfo ptr. index: %d\n", i); - err = -EINVAL; - goto out_err; - } - - WL_SCAN("SSID:%s Channel:%d\n", - netinfo->SSID, netinfo->channel); - memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len); - ssid[i].ssid_len = netinfo->SSID_len; - request->n_ssids++; - - channel_req = netinfo->channel; - if (channel_req <= CH_MAX_2G_CHANNEL) - band = NL80211_BAND_2GHZ; - else - band = NL80211_BAND_5GHZ; - channel[i].center_freq = - ieee80211_channel_to_frequency(channel_req, - band); - channel[i].band = band; - channel[i].flags |= IEEE80211_CHAN_NO_HT40; - request->channels[i] = &channel[i]; - request->n_channels++; - } - - /* assign parsed ssid array */ - if (request->n_ssids) - request->ssids = &ssid[0]; - - if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { - /* Abort any on-going scan */ - brcmf_abort_scanning(cfg); - } - - set_bit(WL_STATUS_SCANNING, &cfg->status); - err = brcmf_do_escan(cfg, wiphy, ndev, request); - if (err) { - clear_bit(WL_STATUS_SCANNING, &cfg->status); - goto out_err; - } - cfg->sched_escan = true; - cfg->scan_request = request; - } else { - WL_ERR("FALSE PNO Event. (pfn_count == 0)\n"); - goto out_err; - } - - kfree(ssid); - kfree(channel); - kfree(request); - return 0; - -out_err: - kfree(ssid); - kfree(channel); - kfree(request); - cfg80211_sched_scan_stopped(wiphy); - return err; -} - -#ifndef CONFIG_BRCMISCAN -static int brcmf_dev_pno_clean(struct net_device *ndev) -{ - char iovbuf[128]; - int ret; - - /* Disable pfn */ - ret = brcmf_dev_intvar_set(ndev, "pfn", 0); - if (ret == 0) { - /* clear pfn */ - ret = brcmf_dev_iovar_setbuf(ndev, "pfnclear", NULL, 0, - iovbuf, sizeof(iovbuf)); - } - if (ret < 0) - WL_ERR("failed code %d\n", ret); - - return ret; -} - -static int brcmf_dev_pno_config(struct net_device *ndev) -{ - struct brcmf_pno_param_le pfn_param; - char iovbuf[128]; - - memset(&pfn_param, 0, sizeof(pfn_param)); - pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); - - /* set extra pno params */ - pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); - pfn_param.repeat = BRCMF_PNO_REPEAT; - pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; - - /* set up pno scan fr */ - pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); - - return brcmf_dev_iovar_setbuf(ndev, "pfn_set", - &pfn_param, sizeof(pfn_param), - iovbuf, sizeof(iovbuf)); -} - -static int -brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, - struct net_device *ndev, - struct cfg80211_sched_scan_request *request) -{ - char iovbuf[128]; - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); - struct brcmf_pno_net_param_le pfn; - int i; - int ret = 0; - - WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n", - request->n_match_sets, request->n_ssids); - if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { - WL_ERR("Scanning already : status (%lu)\n", cfg->status); - return -EAGAIN; - } - - if (!request || !request->n_ssids || !request->n_match_sets) { - WL_ERR("Invalid sched scan req!! n_ssids:%d\n", - request->n_ssids); - return -EINVAL; - } - - if (request->n_ssids > 0) { - for (i = 0; i < request->n_ssids; i++) { - /* Active scan req for ssids */ - WL_SCAN(">>> Active scan req for ssid (%s)\n", - request->ssids[i].ssid); - - /* - * match_set ssids is a supert set of n_ssid list, - * so we need not add these set seperately. - */ - } - } - - if (request->n_match_sets > 0) { - /* clean up everything */ - ret = brcmf_dev_pno_clean(ndev); - if (ret < 0) { - WL_ERR("failed error=%d\n", ret); - return ret; - } - - /* configure pno */ - ret = brcmf_dev_pno_config(ndev); - if (ret < 0) { - WL_ERR("PNO setup failed!! ret=%d\n", ret); - return -EINVAL; - } - - /* configure each match set */ - for (i = 0; i < request->n_match_sets; i++) { - struct cfg80211_ssid *ssid; - u32 ssid_len; - - ssid = &request->match_sets[i].ssid; - ssid_len = ssid->ssid_len; - - if (!ssid_len) { - WL_ERR("skip broadcast ssid\n"); - continue; - } - pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN); - pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY); - pfn.wsec = cpu_to_le32(0); - pfn.infra = cpu_to_le32(1); - pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); - pfn.ssid.SSID_len = cpu_to_le32(ssid_len); - memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len); - ret = brcmf_dev_iovar_setbuf(ndev, "pfn_add", - &pfn, sizeof(pfn), - iovbuf, sizeof(iovbuf)); - WL_SCAN(">>> PNO filter %s for ssid (%s)\n", - ret == 0 ? "set" : "failed", - ssid->ssid); - } - /* Enable the PNO */ - if (brcmf_dev_intvar_set(ndev, "pfn", 1) < 0) { - WL_ERR("PNO enable failed!! ret=%d\n", ret); - return -EINVAL; - } - } else { - return -EINVAL; - } - - return 0; -} - -static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, - struct net_device *ndev) -{ - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - - WL_SCAN("enter\n"); - brcmf_dev_pno_clean(ndev); - if (cfg->sched_escan) - brcmf_notify_escan_complete(cfg, ndev, true, true); - return 0; -} -#endif /* CONFIG_BRCMISCAN */ - -#ifdef CONFIG_NL80211_TESTMODE -static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) -{ - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg->wdev->netdev; - struct brcmf_dcmd *dcmd = data; - struct sk_buff *reply; - int ret; - - ret = brcmf_netlink_dcmd(ndev, dcmd); - if (ret == 0) { - reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd)); - nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd); - ret = cfg80211_testmode_reply(reply); - } - return ret; -} -#endif - -static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx) -{ - s32 err; - - /* set auth */ - err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", 0, bssidx); - if (err < 0) { - WL_ERR("auth error %d\n", err); - return err; - } - /* set wsec */ - err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", 0, bssidx); - if (err < 0) { - WL_ERR("wsec error %d\n", err); - return err; - } - /* set upper-layer auth */ - err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", - WPA_AUTH_NONE, bssidx); - if (err < 0) { - WL_ERR("wpa_auth error %d\n", err); - return err; - } - - return 0; -} - -static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie) -{ - if (is_rsn_ie) - return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0); - - return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0); -} - -static s32 -brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, - bool is_rsn_ie, s32 bssidx) -{ - u32 auth = 0; /* d11 open authentication */ - u16 count; - s32 err = 0; - s32 len = 0; - u32 i; - u32 wsec; - u32 pval = 0; - u32 gval = 0; - u32 wpa_auth = 0; - u32 offset; - u8 *data; - u16 rsn_cap; - u32 wme_bss_disable; - - WL_TRACE("Enter\n"); - if (wpa_ie == NULL) - goto exit; - - len = wpa_ie->len + TLV_HDR_LEN; - data = (u8 *)wpa_ie; - offset = 0; - if (!is_rsn_ie) - offset += VS_IE_FIXED_HDR_LEN; - offset += WPA_IE_VERSION_LEN; - - /* check for multicast cipher suite */ - if (offset + WPA_IE_MIN_OUI_LEN > len) { - err = -EINVAL; - WL_ERR("no multicast cipher suite\n"); - goto exit; - } - - if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { - err = -EINVAL; - WL_ERR("ivalid OUI\n"); - goto exit; - } - offset += TLV_OUI_LEN; - - /* pick up multicast cipher */ - switch (data[offset]) { - case WPA_CIPHER_NONE: - gval = 0; - break; - case WPA_CIPHER_WEP_40: - case WPA_CIPHER_WEP_104: - gval = WEP_ENABLED; - break; - case WPA_CIPHER_TKIP: - gval = TKIP_ENABLED; - break; - case WPA_CIPHER_AES_CCM: - gval = AES_ENABLED; - break; - default: - err = -EINVAL; - WL_ERR("Invalid multi cast cipher info\n"); - goto exit; - } - - offset++; - /* walk thru unicast cipher list and pick up what we recognize */ - count = data[offset] + (data[offset + 1] << 8); - offset += WPA_IE_SUITE_COUNT_LEN; - /* Check for unicast suite(s) */ - if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) { - err = -EINVAL; - WL_ERR("no unicast cipher suite\n"); - goto exit; - } - for (i = 0; i < count; i++) { - if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { - err = -EINVAL; - WL_ERR("ivalid OUI\n"); - goto exit; - } - offset += TLV_OUI_LEN; - switch (data[offset]) { - case WPA_CIPHER_NONE: - break; - case WPA_CIPHER_WEP_40: - case WPA_CIPHER_WEP_104: - pval |= WEP_ENABLED; - break; - case WPA_CIPHER_TKIP: - pval |= TKIP_ENABLED; - break; - case WPA_CIPHER_AES_CCM: - pval |= AES_ENABLED; - break; - default: - WL_ERR("Ivalid unicast security info\n"); - } - offset++; - } - /* walk thru auth management suite list and pick up what we recognize */ - count = data[offset] + (data[offset + 1] << 8); - offset += WPA_IE_SUITE_COUNT_LEN; - /* Check for auth key management suite(s) */ - if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) { - err = -EINVAL; - WL_ERR("no auth key mgmt suite\n"); - goto exit; - } - for (i = 0; i < count; i++) { - if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { - err = -EINVAL; - WL_ERR("ivalid OUI\n"); - goto exit; - } - offset += TLV_OUI_LEN; - switch (data[offset]) { - case RSN_AKM_NONE: - WL_TRACE("RSN_AKM_NONE\n"); - wpa_auth |= WPA_AUTH_NONE; - break; - case RSN_AKM_UNSPECIFIED: - WL_TRACE("RSN_AKM_UNSPECIFIED\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : - (wpa_auth |= WPA_AUTH_UNSPECIFIED); - break; - case RSN_AKM_PSK: - WL_TRACE("RSN_AKM_PSK\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : - (wpa_auth |= WPA_AUTH_PSK); - break; - default: - WL_ERR("Ivalid key mgmt info\n"); - } - offset++; - } - - if (is_rsn_ie) { - wme_bss_disable = 1; - if ((offset + RSN_CAP_LEN) <= len) { - rsn_cap = data[offset] + (data[offset + 1] << 8); - if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK) - wme_bss_disable = 0; - } - /* set wme_bss_disable to sync RSN Capabilities */ - err = brcmf_dev_intvar_set_bsscfg(ndev, "wme_bss_disable", - wme_bss_disable, bssidx); - if (err < 0) { - WL_ERR("wme_bss_disable error %d\n", err); - goto exit; - } - } - /* FOR WPS , set SES_OW_ENABLED */ - wsec = (pval | gval | SES_OW_ENABLED); - - /* set auth */ - err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", auth, bssidx); - if (err < 0) { - WL_ERR("auth error %d\n", err); - goto exit; - } - /* set wsec */ - err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx); - if (err < 0) { - WL_ERR("wsec error %d\n", err); - goto exit; - } - /* set upper-layer auth */ - err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", wpa_auth, bssidx); - if (err < 0) { - WL_ERR("wpa_auth error %d\n", err); - goto exit; - } - -exit: - return err; -} - -static s32 -brcmf_parse_vndr_ies(u8 *vndr_ie_buf, u32 vndr_ie_len, - struct parsed_vndr_ies *vndr_ies) -{ - s32 err = 0; - struct brcmf_vs_tlv *vndrie; - struct brcmf_tlv *ie; - struct parsed_vndr_ie_info *parsed_info; - s32 remaining_len; - - remaining_len = (s32)vndr_ie_len; - memset(vndr_ies, 0, sizeof(*vndr_ies)); - - ie = (struct brcmf_tlv *)vndr_ie_buf; - while (ie) { - if (ie->id != WLAN_EID_VENDOR_SPECIFIC) - goto next; - vndrie = (struct brcmf_vs_tlv *)ie; - /* len should be bigger than OUI length + one */ - if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) { - WL_ERR("invalid vndr ie. length is too small %d\n", - vndrie->len); - goto next; - } - /* if wpa or wme ie, do not add ie */ - if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) && - ((vndrie->oui_type == WPA_OUI_TYPE) || - (vndrie->oui_type == WME_OUI_TYPE))) { - WL_TRACE("Found WPA/WME oui. Do not add it\n"); - goto next; - } - - parsed_info = &vndr_ies->ie_info[vndr_ies->count]; - - /* save vndr ie information */ - parsed_info->ie_ptr = (char *)vndrie; - parsed_info->ie_len = vndrie->len + TLV_HDR_LEN; - memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie)); - - vndr_ies->count++; - - WL_TRACE("** OUI %02x %02x %02x, type 0x%02x\n", - parsed_info->vndrie.oui[0], - parsed_info->vndrie.oui[1], - parsed_info->vndrie.oui[2], - parsed_info->vndrie.oui_type); - - if (vndr_ies->count >= MAX_VNDR_IE_NUMBER) - break; -next: - remaining_len -= ie->len; - if (remaining_len <= 2) - ie = NULL; - else - ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len); - } - return err; -} - -static u32 -brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) -{ - - __le32 iecount_le; - __le32 pktflag_le; - - strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1); - iebuf[VNDR_IE_CMD_LEN - 1] = '\0'; - - iecount_le = cpu_to_le32(1); - memcpy(&iebuf[VNDR_IE_COUNT_OFFSET], &iecount_le, sizeof(iecount_le)); - - pktflag_le = cpu_to_le32(pktflag); - memcpy(&iebuf[VNDR_IE_PKTFLAG_OFFSET], &pktflag_le, sizeof(pktflag_le)); - - memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len); - - return ie_len + VNDR_IE_HDR_SIZE; -} - -s32 -brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, - struct net_device *ndev, s32 bssidx, s32 pktflag, - u8 *vndr_ie_buf, u32 vndr_ie_len) -{ - s32 err = 0; - u8 *iovar_ie_buf; - u8 *curr_ie_buf; - u8 *mgmt_ie_buf = NULL; - u32 mgmt_ie_buf_len = 0; - u32 *mgmt_ie_len = 0; - u32 del_add_ie_buf_len = 0; - u32 total_ie_buf_len = 0; - u32 parsed_ie_buf_len = 0; - struct parsed_vndr_ies old_vndr_ies; - struct parsed_vndr_ies new_vndr_ies; - struct parsed_vndr_ie_info *vndrie_info; - s32 i; - u8 *ptr; - u32 remained_buf_len; - - WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag); - iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); - if (!iovar_ie_buf) - return -ENOMEM; - curr_ie_buf = iovar_ie_buf; - if (test_bit(WL_STATUS_AP_CREATING, &cfg->status) || - test_bit(WL_STATUS_AP_CREATED, &cfg->status)) { - switch (pktflag) { - case VNDR_IE_PRBRSP_FLAG: - mgmt_ie_buf = cfg->ap_info->probe_res_ie; - mgmt_ie_len = &cfg->ap_info->probe_res_ie_len; - mgmt_ie_buf_len = - sizeof(cfg->ap_info->probe_res_ie); - break; - case VNDR_IE_BEACON_FLAG: - mgmt_ie_buf = cfg->ap_info->beacon_ie; - mgmt_ie_len = &cfg->ap_info->beacon_ie_len; - mgmt_ie_buf_len = sizeof(cfg->ap_info->beacon_ie); - break; - default: - err = -EPERM; - WL_ERR("not suitable type\n"); - goto exit; - } - bssidx = 0; - } else { - err = -EPERM; - WL_ERR("not suitable type\n"); - goto exit; - } - - if (vndr_ie_len > mgmt_ie_buf_len) { - err = -ENOMEM; - WL_ERR("extra IE size too big\n"); - goto exit; - } - - /* parse and save new vndr_ie in curr_ie_buff before comparing it */ - if (vndr_ie_buf && vndr_ie_len && curr_ie_buf) { - ptr = curr_ie_buf; - brcmf_parse_vndr_ies(vndr_ie_buf, vndr_ie_len, &new_vndr_ies); - for (i = 0; i < new_vndr_ies.count; i++) { - vndrie_info = &new_vndr_ies.ie_info[i]; - memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr, - vndrie_info->ie_len); - parsed_ie_buf_len += vndrie_info->ie_len; - } - } - - if (mgmt_ie_buf != NULL) { - if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) && - (memcmp(mgmt_ie_buf, curr_ie_buf, - parsed_ie_buf_len) == 0)) { - WL_TRACE("Previous mgmt IE is equals to current IE"); - goto exit; - } - - /* parse old vndr_ie */ - brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies); - - /* make a command to delete old ie */ - for (i = 0; i < old_vndr_ies.count; i++) { - vndrie_info = &old_vndr_ies.ie_info[i]; - - WL_TRACE("DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n", - vndrie_info->vndrie.id, - vndrie_info->vndrie.len, - vndrie_info->vndrie.oui[0], - vndrie_info->vndrie.oui[1], - vndrie_info->vndrie.oui[2]); - - del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag, - vndrie_info->ie_ptr, - vndrie_info->ie_len, - "del"); - curr_ie_buf += del_add_ie_buf_len; - total_ie_buf_len += del_add_ie_buf_len; - } - } - - *mgmt_ie_len = 0; - /* Add if there is any extra IE */ - if (mgmt_ie_buf && parsed_ie_buf_len) { - ptr = mgmt_ie_buf; - - remained_buf_len = mgmt_ie_buf_len; - - /* make a command to add new ie */ - for (i = 0; i < new_vndr_ies.count; i++) { - vndrie_info = &new_vndr_ies.ie_info[i]; - - WL_TRACE("ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n", - vndrie_info->vndrie.id, - vndrie_info->vndrie.len, - vndrie_info->vndrie.oui[0], - vndrie_info->vndrie.oui[1], - vndrie_info->vndrie.oui[2]); - - del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag, - vndrie_info->ie_ptr, - vndrie_info->ie_len, - "add"); - /* verify remained buf size before copy data */ - remained_buf_len -= vndrie_info->ie_len; - if (remained_buf_len < 0) { - WL_ERR("no space in mgmt_ie_buf: len left %d", - remained_buf_len); - break; - } - - /* save the parsed IE in wl struct */ - memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr, - vndrie_info->ie_len); - *mgmt_ie_len += vndrie_info->ie_len; - - curr_ie_buf += del_add_ie_buf_len; - total_ie_buf_len += del_add_ie_buf_len; - } - } - if (total_ie_buf_len) { - err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "vndr_ie", - iovar_ie_buf, - total_ie_buf_len, - cfg->extra_buf, - WL_EXTRA_BUF_MAX, bssidx); - if (err) - WL_ERR("vndr ie set error : %d\n", err); - } - -exit: - kfree(iovar_ie_buf); - return err; -} - -static s32 -brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_ap_settings *settings) -{ - s32 ie_offset; - struct brcmf_tlv *ssid_ie; - struct brcmf_ssid_le ssid_le; - s32 ioctl_value; - s32 err = -EPERM; - struct brcmf_tlv *rsn_ie; - struct brcmf_vs_tlv *wpa_ie; - struct brcmf_join_params join_params; - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - s32 bssidx = 0; - - WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n", - settings->channel_type, settings->beacon_interval, - settings->dtim_period); - WL_TRACE("ssid=%s(%d), auth_type=%d, inactivity_timeout=%d\n", - settings->ssid, settings->ssid_len, settings->auth_type, - settings->inactivity_timeout); - - if (!test_bit(WL_STATUS_AP_CREATING, &cfg->status)) { - WL_ERR("Not in AP creation mode\n"); - return -EPERM; - } - - memset(&ssid_le, 0, sizeof(ssid_le)); - if (settings->ssid == NULL || settings->ssid_len == 0) { - ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; - ssid_ie = brcmf_parse_tlvs( - (u8 *)&settings->beacon.head[ie_offset], - settings->beacon.head_len - ie_offset, - WLAN_EID_SSID); - if (!ssid_ie) - return -EINVAL; - - memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len); - ssid_le.SSID_len = cpu_to_le32(ssid_ie->len); - WL_TRACE("SSID is (%s) in Head\n", ssid_le.SSID); - } else { - memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len); - ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len); - } - - brcmf_set_mpc(ndev, 0); - ioctl_value = 1; - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_DOWN, &ioctl_value); - if (err < 0) { - WL_ERR("BRCMF_C_DOWN error %d\n", err); - goto exit; - } - ioctl_value = 1; - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &ioctl_value); - if (err < 0) { - WL_ERR("SET INFRA error %d\n", err); - goto exit; - } - ioctl_value = 1; - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value); - if (err < 0) { - WL_ERR("setting AP mode failed %d\n", err); - goto exit; - } - - /* find the RSN_IE */ - rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail, - settings->beacon.tail_len, WLAN_EID_RSN); - - /* find the WPA_IE */ - wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail, - settings->beacon.tail_len); - - kfree(cfg->ap_info->rsn_ie); - cfg->ap_info->rsn_ie = NULL; - kfree(cfg->ap_info->wpa_ie); - cfg->ap_info->wpa_ie = NULL; - - if ((wpa_ie != NULL || rsn_ie != NULL)) { - WL_TRACE("WPA(2) IE is found\n"); - if (wpa_ie != NULL) { - /* WPA IE */ - err = brcmf_configure_wpaie(ndev, wpa_ie, false, - bssidx); - if (err < 0) - goto exit; - cfg->ap_info->wpa_ie = kmemdup(wpa_ie, - wpa_ie->len + - TLV_HDR_LEN, - GFP_KERNEL); - } else { - /* RSN IE */ - err = brcmf_configure_wpaie(ndev, - (struct brcmf_vs_tlv *)rsn_ie, true, bssidx); - if (err < 0) - goto exit; - cfg->ap_info->rsn_ie = kmemdup(rsn_ie, - rsn_ie->len + - TLV_HDR_LEN, - GFP_KERNEL); - } - cfg->ap_info->security_mode = true; - } else { - WL_TRACE("No WPA(2) IEs found\n"); - brcmf_configure_opensecurity(ndev, bssidx); - cfg->ap_info->security_mode = false; - } - /* Set Beacon IEs to FW */ - err = brcmf_set_management_ie(cfg, ndev, bssidx, - VNDR_IE_BEACON_FLAG, - (u8 *)settings->beacon.tail, - settings->beacon.tail_len); - if (err) - WL_ERR("Set Beacon IE Failed\n"); - else - WL_TRACE("Applied Vndr IEs for Beacon\n"); - - /* Set Probe Response IEs to FW */ - err = brcmf_set_management_ie(cfg, ndev, bssidx, - VNDR_IE_PRBRSP_FLAG, - (u8 *)settings->beacon.proberesp_ies, - settings->beacon.proberesp_ies_len); - if (err) - WL_ERR("Set Probe Resp IE Failed\n"); - else - WL_TRACE("Applied Vndr IEs for Probe Resp\n"); - - if (settings->beacon_interval) { - ioctl_value = settings->beacon_interval; - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_BCNPRD, - &ioctl_value); - if (err < 0) { - WL_ERR("Beacon Interval Set Error, %d\n", err); - goto exit; - } - } - if (settings->dtim_period) { - ioctl_value = settings->dtim_period; - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_DTIMPRD, - &ioctl_value); - if (err < 0) { - WL_ERR("DTIM Interval Set Error, %d\n", err); - goto exit; - } - } - ioctl_value = 1; - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value); - if (err < 0) { - WL_ERR("BRCMF_C_UP error (%d)\n", err); - goto exit; - } - - memset(&join_params, 0, sizeof(join_params)); - /* join parameters starts with ssid */ - memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le)); - /* create softap */ - err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, &join_params, - sizeof(join_params)); - if (err < 0) { - WL_ERR("SET SSID error (%d)\n", err); - goto exit; - } - clear_bit(WL_STATUS_AP_CREATING, &cfg->status); - set_bit(WL_STATUS_AP_CREATED, &cfg->status); - -exit: - if (err) - brcmf_set_mpc(ndev, 1); - return err; -} - -static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) -{ - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - s32 ioctl_value; - s32 err = -EPERM; - - WL_TRACE("Enter\n"); - - if (cfg->conf->mode == WL_MODE_AP) { - /* Due to most likely deauths outstanding we sleep */ - /* first to make sure they get processed by fw. */ - msleep(400); - ioctl_value = 0; - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value); - if (err < 0) { - WL_ERR("setting AP mode failed %d\n", err); - goto exit; - } - ioctl_value = 0; - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value); - if (err < 0) { - WL_ERR("BRCMF_C_UP error %d\n", err); - goto exit; - } - brcmf_set_mpc(ndev, 1); - clear_bit(WL_STATUS_AP_CREATING, &cfg->status); - clear_bit(WL_STATUS_AP_CREATED, &cfg->status); - } -exit: - return err; -} - -static int -brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, - u8 *mac) -{ - struct brcmf_scb_val_le scbval; - s32 err; - - if (!mac) - return -EFAULT; - - WL_TRACE("Enter %pM\n", mac); - - if (!check_sys_up(wiphy)) - return -EIO; - - memcpy(&scbval.ea, mac, ETH_ALEN); - scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); - err = brcmf_exec_dcmd(ndev, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, - &scbval, sizeof(scbval)); - if (err) - WL_ERR("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err); - - WL_TRACE("Exit\n"); - return err; -} + return ret; +} +#endif static struct cfg80211_ops wl_cfg80211_ops = { .change_virtual_intf = brcmf_cfg80211_change_iface, @@ -4370,14 +3269,6 @@ static struct cfg80211_ops wl_cfg80211_ops = { .set_pmksa = brcmf_cfg80211_set_pmksa, .del_pmksa = brcmf_cfg80211_del_pmksa, .flush_pmksa = brcmf_cfg80211_flush_pmksa, - .start_ap = brcmf_cfg80211_start_ap, - .stop_ap = brcmf_cfg80211_stop_ap, - .del_station = brcmf_cfg80211_del_station, -#ifndef CONFIG_BRCMISCAN - /* scheduled scan need e-scan, which is mutual exclusive with i-scan */ - .sched_scan_start = brcmf_cfg80211_sched_scan_start, - .sched_scan_stop = brcmf_cfg80211_sched_scan_stop, -#endif #ifdef CONFIG_NL80211_TESTMODE .testmode_cmd = brcmf_cfg80211_testmode #endif @@ -4399,18 +3290,8 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode) return err; } -static void brcmf_wiphy_pno_params(struct wiphy *wiphy) -{ -#ifndef CONFIG_BRCMFISCAN - /* scheduled scan settings */ - wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; - wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; - wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; - wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; -#endif -} - -static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) +static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, + struct device *ndev) { struct wireless_dev *wdev; s32 err = 0; @@ -4419,8 +3300,9 @@ static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) if (!wdev) return ERR_PTR(-ENOMEM); - wdev->wiphy = wiphy_new(&wl_cfg80211_ops, - sizeof(struct brcmf_cfg80211_info)); + wdev->wiphy = + wiphy_new(&wl_cfg80211_ops, + sizeof(struct brcmf_cfg80211_priv) + sizeof_iface); if (!wdev->wiphy) { WL_ERR("Could not allocate wiphy device\n"); err = -ENOMEM; @@ -4429,9 +3311,8 @@ static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) set_wiphy_dev(wdev->wiphy, ndev); wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; - wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP); + wdev->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set * it as 11a by default. @@ -4447,7 +3328,6 @@ static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) * save mode * by default */ - brcmf_wiphy_pno_params(wdev->wiphy); err = wiphy_register(wdev->wiphy); if (err < 0) { WL_ERR("Could not register wiphy device (%d)\n", err); @@ -4464,9 +3344,9 @@ static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) return ERR_PTR(err); } -static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg) +static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv) { - struct wireless_dev *wdev = cfg->wdev; + struct wireless_dev *wdev = cfg_priv->wdev; if (!wdev) { WL_ERR("wdev is invalid\n"); @@ -4475,10 +3355,10 @@ static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg) wiphy_unregister(wdev->wiphy); wiphy_free(wdev->wiphy); kfree(wdev); - cfg->wdev = NULL; + cfg_priv->wdev = NULL; } -static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, +static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv, const struct brcmf_event_msg *e) { u32 event = be32_to_cpu(e->event_type); @@ -4486,14 +3366,14 @@ static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) { WL_CONN("Processing set ssid\n"); - cfg->link_up = true; + cfg_priv->link_up = true; return true; } return false; } -static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg, +static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv, const struct brcmf_event_msg *e) { u32 event = be32_to_cpu(e->event_type); @@ -4506,7 +3386,7 @@ static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg, return false; } -static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg, +static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv, const struct brcmf_event_msg *e) { u32 event = be32_to_cpu(e->event_type); @@ -4527,9 +3407,9 @@ static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg, return false; } -static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg) +static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); + struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); kfree(conn_info->req_ie); conn_info->req_ie = NULL; @@ -4539,30 +3419,30 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg) conn_info->resp_ie_len = 0; } -static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) { - struct net_device *ndev = cfg_to_ndev(cfg); + struct net_device *ndev = cfg_to_ndev(cfg_priv); struct brcmf_cfg80211_assoc_ielen_le *assoc_info; - struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); + struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); u32 req_len; u32 resp_len; s32 err = 0; - brcmf_clear_assoc_ies(cfg); + brcmf_clear_assoc_ies(cfg_priv); - err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg->extra_buf, + err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf, WL_ASSOC_INFO_MAX); if (err) { WL_ERR("could not get assoc info (%d)\n", err); return err; } assoc_info = - (struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf; + (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf; req_len = le32_to_cpu(assoc_info->req_len); resp_len = le32_to_cpu(assoc_info->resp_len); if (req_len) { err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies", - cfg->extra_buf, + cfg_priv->extra_buf, WL_ASSOC_INFO_MAX); if (err) { WL_ERR("could not get assoc req (%d)\n", err); @@ -4570,7 +3450,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) } conn_info->req_ie_len = req_len; conn_info->req_ie = - kmemdup(cfg->extra_buf, conn_info->req_ie_len, + kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len, GFP_KERNEL); } else { conn_info->req_ie_len = 0; @@ -4578,7 +3458,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) } if (resp_len) { err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies", - cfg->extra_buf, + cfg_priv->extra_buf, WL_ASSOC_INFO_MAX); if (err) { WL_ERR("could not get assoc resp (%d)\n", err); @@ -4586,7 +3466,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) } conn_info->resp_ie_len = resp_len; conn_info->resp_ie = - kmemdup(cfg->extra_buf, conn_info->resp_ie_len, + kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len, GFP_KERNEL); } else { conn_info->resp_ie_len = 0; @@ -4599,13 +3479,12 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) } static s32 -brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, +brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e) { - struct brcmf_cfg80211_profile *profile = cfg->profile; - struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); + struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); struct brcmf_channel_info_le channel_le; struct ieee80211_channel *notify_channel; struct ieee80211_supported_band *band; @@ -4615,9 +3494,9 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, WL_TRACE("Enter\n"); - brcmf_get_assoc_ies(cfg); - memcpy(profile->bssid, e->addr, ETH_ALEN); - brcmf_update_bss_info(cfg); + brcmf_get_assoc_ies(cfg_priv); + brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID); + brcmf_update_bss_info(cfg_priv); brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, sizeof(channel_le)); @@ -4633,35 +3512,37 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, freq = ieee80211_channel_to_frequency(target_channel, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); - cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid, + cfg80211_roamed(ndev, notify_channel, + (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID), conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); WL_CONN("Report roaming result\n"); - set_bit(WL_STATUS_CONNECTED, &cfg->status); + set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); WL_TRACE("Exit\n"); return err; } static s32 -brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, +brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e, bool completed) { - struct brcmf_cfg80211_profile *profile = cfg->profile; - struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); + struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); s32 err = 0; WL_TRACE("Enter\n"); - if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg->status)) { + if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { if (completed) { - brcmf_get_assoc_ies(cfg); - memcpy(profile->bssid, e->addr, ETH_ALEN); - brcmf_update_bss_info(cfg); + brcmf_get_assoc_ies(cfg_priv); + brcmf_update_prof(cfg_priv, NULL, &e->addr, + WL_PROF_BSSID); + brcmf_update_bss_info(cfg_priv); } cfg80211_connect_result(ndev, - (u8 *)profile->bssid, + (u8 *)brcmf_read_prof(cfg_priv, + WL_PROF_BSSID), conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, @@ -4670,7 +3551,7 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL); if (completed) - set_bit(WL_STATUS_CONNECTED, &cfg->status); + set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); WL_CONN("Report connect result - connection %s\n", completed ? "succeeded" : "failed"); } @@ -4679,93 +3560,52 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, } static s32 -brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, - struct net_device *ndev, - const struct brcmf_event_msg *e, void *data) -{ - s32 err = 0; - u32 event = be32_to_cpu(e->event_type); - u32 reason = be32_to_cpu(e->reason); - u32 len = be32_to_cpu(e->datalen); - static int generation; - - struct station_info sinfo; - - WL_CONN("event %d, reason %d\n", event, reason); - memset(&sinfo, 0, sizeof(sinfo)); - - sinfo.filled = 0; - if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) && - reason == BRCMF_E_STATUS_SUCCESS) { - sinfo.filled = STATION_INFO_ASSOC_REQ_IES; - if (!data) { - WL_ERR("No IEs present in ASSOC/REASSOC_IND"); - return -EINVAL; - } - sinfo.assoc_req_ies = data; - sinfo.assoc_req_ies_len = len; - generation++; - sinfo.generation = generation; - cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_ATOMIC); - } else if ((event == BRCMF_E_DISASSOC_IND) || - (event == BRCMF_E_DEAUTH_IND) || - (event == BRCMF_E_DEAUTH)) { - generation++; - sinfo.generation = generation; - cfg80211_del_sta(ndev, e->addr, GFP_ATOMIC); - } - return err; -} - -static s32 -brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg, +brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { - struct brcmf_cfg80211_profile *profile = cfg->profile; s32 err = 0; - if (cfg->conf->mode == WL_MODE_AP) { - err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); - } else if (brcmf_is_linkup(cfg, e)) { + if (brcmf_is_linkup(cfg_priv, e)) { WL_CONN("Linkup\n"); - if (brcmf_is_ibssmode(cfg)) { - memcpy(profile->bssid, e->addr, ETH_ALEN); - wl_inform_ibss(cfg, ndev, e->addr); + if (brcmf_is_ibssmode(cfg_priv)) { + brcmf_update_prof(cfg_priv, NULL, (void *)e->addr, + WL_PROF_BSSID); + wl_inform_ibss(cfg_priv, ndev, e->addr); cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); - clear_bit(WL_STATUS_CONNECTING, &cfg->status); - set_bit(WL_STATUS_CONNECTED, &cfg->status); + clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); + set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); } else - brcmf_bss_connect_done(cfg, ndev, e, true); - } else if (brcmf_is_linkdown(cfg, e)) { + brcmf_bss_connect_done(cfg_priv, ndev, e, true); + } else if (brcmf_is_linkdown(cfg_priv, e)) { WL_CONN("Linkdown\n"); - if (brcmf_is_ibssmode(cfg)) { - clear_bit(WL_STATUS_CONNECTING, &cfg->status); + if (brcmf_is_ibssmode(cfg_priv)) { + clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); if (test_and_clear_bit(WL_STATUS_CONNECTED, - &cfg->status)) - brcmf_link_down(cfg); + &cfg_priv->status)) + brcmf_link_down(cfg_priv); } else { - brcmf_bss_connect_done(cfg, ndev, e, false); + brcmf_bss_connect_done(cfg_priv, ndev, e, false); if (test_and_clear_bit(WL_STATUS_CONNECTED, - &cfg->status)) { + &cfg_priv->status)) { cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); - brcmf_link_down(cfg); + brcmf_link_down(cfg_priv); } } - brcmf_init_prof(cfg->profile); - } else if (brcmf_is_nonetwork(cfg, e)) { - if (brcmf_is_ibssmode(cfg)) - clear_bit(WL_STATUS_CONNECTING, &cfg->status); + brcmf_init_prof(cfg_priv->profile); + } else if (brcmf_is_nonetwork(cfg_priv, e)) { + if (brcmf_is_ibssmode(cfg_priv)) + clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); else - brcmf_bss_connect_done(cfg, ndev, e, false); + brcmf_bss_connect_done(cfg_priv, ndev, e, false); } return err; } static s32 -brcmf_notify_roaming_status(struct brcmf_cfg80211_info *cfg, +brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -4774,17 +3614,17 @@ brcmf_notify_roaming_status(struct brcmf_cfg80211_info *cfg, u32 status = be32_to_cpu(e->status); if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { - if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) - brcmf_bss_roaming_done(cfg, ndev, e); + if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) + brcmf_bss_roaming_done(cfg_priv, ndev, e); else - brcmf_bss_connect_done(cfg, ndev, e, true); + brcmf_bss_connect_done(cfg_priv, ndev, e, true); } return err; } static s32 -brcmf_notify_mic_status(struct brcmf_cfg80211_info *cfg, +brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -4803,7 +3643,7 @@ brcmf_notify_mic_status(struct brcmf_cfg80211_info *cfg, } static s32 -brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, +brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -4816,12 +3656,12 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, WL_TRACE("Enter\n"); - if (cfg->iscan_on && cfg->iscan_kickstart) { + if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) { WL_TRACE("Exit\n"); - return brcmf_wakeup_iscan(cfg_to_iscan(cfg)); + return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv)); } - if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { + if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { WL_ERR("Scan complete while device not scanning\n"); scan_abort = true; err = -EINVAL; @@ -4838,33 +3678,33 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, scan_channel = le32_to_cpu(channel_inform_le.scan_channel); if (scan_channel) WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel); - cfg->bss_list = cfg->scan_results; - bss_list_le = (struct brcmf_scan_results_le *) cfg->bss_list; + cfg_priv->bss_list = cfg_priv->scan_results; + bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list; - memset(cfg->scan_results, 0, len); + memset(cfg_priv->scan_results, 0, len); bss_list_le->buflen = cpu_to_le32(len); err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS, - cfg->scan_results, len); + cfg_priv->scan_results, len); if (err) { WL_ERR("%s Scan_results error (%d)\n", ndev->name, err); err = -EINVAL; scan_abort = true; goto scan_done_out; } - cfg->scan_results->buflen = le32_to_cpu(bss_list_le->buflen); - cfg->scan_results->version = le32_to_cpu(bss_list_le->version); - cfg->scan_results->count = le32_to_cpu(bss_list_le->count); + cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen); + cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version); + cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count); - err = brcmf_inform_bss(cfg); + err = brcmf_inform_bss(cfg_priv); if (err) scan_abort = true; scan_done_out: - if (cfg->scan_request) { + if (cfg_priv->scan_request) { WL_SCAN("calling cfg80211_scan_done\n"); - cfg80211_scan_done(cfg->scan_request, scan_abort); + cfg80211_scan_done(cfg_priv->scan_request, scan_abort); brcmf_set_mpc(ndev, 1); - cfg->scan_request = NULL; + cfg_priv->scan_request = NULL; } WL_TRACE("Exit\n"); @@ -4887,85 +3727,73 @@ static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el) memset(el, 0, sizeof(*el)); el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status; el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status; - el->handler[BRCMF_E_DEAUTH_IND] = brcmf_notify_connect_status; - el->handler[BRCMF_E_DEAUTH] = brcmf_notify_connect_status; - el->handler[BRCMF_E_DISASSOC_IND] = brcmf_notify_connect_status; - el->handler[BRCMF_E_ASSOC_IND] = brcmf_notify_connect_status; - el->handler[BRCMF_E_REASSOC_IND] = brcmf_notify_connect_status; el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status; el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status; el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status; - el->handler[BRCMF_E_PFN_NET_FOUND] = brcmf_notify_sched_scan_results; -} - -static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg) -{ - kfree(cfg->scan_results); - cfg->scan_results = NULL; - kfree(cfg->bss_info); - cfg->bss_info = NULL; - kfree(cfg->conf); - cfg->conf = NULL; - kfree(cfg->profile); - cfg->profile = NULL; - kfree(cfg->scan_req_int); - cfg->scan_req_int = NULL; - kfree(cfg->escan_ioctl_buf); - cfg->escan_ioctl_buf = NULL; - kfree(cfg->dcmd_buf); - cfg->dcmd_buf = NULL; - kfree(cfg->extra_buf); - cfg->extra_buf = NULL; - kfree(cfg->iscan); - cfg->iscan = NULL; - kfree(cfg->pmk_list); - cfg->pmk_list = NULL; - if (cfg->ap_info) { - kfree(cfg->ap_info->wpa_ie); - kfree(cfg->ap_info->rsn_ie); - kfree(cfg->ap_info); - cfg->ap_info = NULL; - } -} - -static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg) -{ - cfg->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); - if (!cfg->scan_results) +} + +static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) +{ + kfree(cfg_priv->scan_results); + cfg_priv->scan_results = NULL; + kfree(cfg_priv->bss_info); + cfg_priv->bss_info = NULL; + kfree(cfg_priv->conf); + cfg_priv->conf = NULL; + kfree(cfg_priv->profile); + cfg_priv->profile = NULL; + kfree(cfg_priv->scan_req_int); + cfg_priv->scan_req_int = NULL; + kfree(cfg_priv->escan_ioctl_buf); + cfg_priv->escan_ioctl_buf = NULL; + kfree(cfg_priv->dcmd_buf); + cfg_priv->dcmd_buf = NULL; + kfree(cfg_priv->extra_buf); + cfg_priv->extra_buf = NULL; + kfree(cfg_priv->iscan); + cfg_priv->iscan = NULL; + kfree(cfg_priv->pmk_list); + cfg_priv->pmk_list = NULL; +} + +static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) +{ + cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); + if (!cfg_priv->scan_results) goto init_priv_mem_out; - cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL); - if (!cfg->conf) + cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL); + if (!cfg_priv->conf) goto init_priv_mem_out; - cfg->profile = kzalloc(sizeof(*cfg->profile), GFP_KERNEL); - if (!cfg->profile) + cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL); + if (!cfg_priv->profile) goto init_priv_mem_out; - cfg->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); - if (!cfg->bss_info) + cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); + if (!cfg_priv->bss_info) goto init_priv_mem_out; - cfg->scan_req_int = kzalloc(sizeof(*cfg->scan_req_int), + cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int), GFP_KERNEL); - if (!cfg->scan_req_int) + if (!cfg_priv->scan_req_int) goto init_priv_mem_out; - cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); - if (!cfg->escan_ioctl_buf) + cfg_priv->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); + if (!cfg_priv->escan_ioctl_buf) goto init_priv_mem_out; - cfg->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL); - if (!cfg->dcmd_buf) + cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL); + if (!cfg_priv->dcmd_buf) goto init_priv_mem_out; - cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); - if (!cfg->extra_buf) + cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); + if (!cfg_priv->extra_buf) goto init_priv_mem_out; - cfg->iscan = kzalloc(sizeof(*cfg->iscan), GFP_KERNEL); - if (!cfg->iscan) + cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL); + if (!cfg_priv->iscan) goto init_priv_mem_out; - cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL); - if (!cfg->pmk_list) + cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL); + if (!cfg_priv->pmk_list) goto init_priv_mem_out; return 0; init_priv_mem_out: - brcmf_deinit_priv_mem(cfg); + brcmf_deinit_priv_mem(cfg_priv); return -ENOMEM; } @@ -4975,17 +3803,17 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg) */ static struct brcmf_cfg80211_event_q *brcmf_deq_event( - struct brcmf_cfg80211_info *cfg) + struct brcmf_cfg80211_priv *cfg_priv) { struct brcmf_cfg80211_event_q *e = NULL; - spin_lock_irq(&cfg->evt_q_lock); - if (!list_empty(&cfg->evt_q_list)) { - e = list_first_entry(&cfg->evt_q_list, + spin_lock_irq(&cfg_priv->evt_q_lock); + if (!list_empty(&cfg_priv->evt_q_list)) { + e = list_first_entry(&cfg_priv->evt_q_list, struct brcmf_cfg80211_event_q, evt_q_list); list_del(&e->evt_q_list); } - spin_unlock_irq(&cfg->evt_q_lock); + spin_unlock_irq(&cfg_priv->evt_q_lock); return e; } @@ -4997,7 +3825,7 @@ static struct brcmf_cfg80211_event_q *brcmf_deq_event( */ static s32 -brcmf_enq_event(struct brcmf_cfg80211_info *cfg, u32 event, +brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, const struct brcmf_event_msg *msg, void *data) { struct brcmf_cfg80211_event_q *e; @@ -5021,9 +3849,9 @@ brcmf_enq_event(struct brcmf_cfg80211_info *cfg, u32 event, if (data) memcpy(&e->edata, data, data_len); - spin_lock_irqsave(&cfg->evt_q_lock, flags); - list_add_tail(&e->evt_q_list, &cfg->evt_q_list); - spin_unlock_irqrestore(&cfg->evt_q_lock, flags); + spin_lock_irqsave(&cfg_priv->evt_q_lock, flags); + list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list); + spin_unlock_irqrestore(&cfg_priv->evt_q_lock, flags); return err; } @@ -5035,12 +3863,12 @@ static void brcmf_put_event(struct brcmf_cfg80211_event_q *e) static void brcmf_cfg80211_event_handler(struct work_struct *work) { - struct brcmf_cfg80211_info *cfg = - container_of(work, struct brcmf_cfg80211_info, + struct brcmf_cfg80211_priv *cfg_priv = + container_of(work, struct brcmf_cfg80211_priv, event_work); struct brcmf_cfg80211_event_q *e; - e = brcmf_deq_event(cfg); + e = brcmf_deq_event(cfg_priv); if (unlikely(!e)) { WL_ERR("event queue empty...\n"); return; @@ -5048,131 +3876,147 @@ static void brcmf_cfg80211_event_handler(struct work_struct *work) do { WL_INFO("event type (%d)\n", e->etype); - if (cfg->el.handler[e->etype]) - cfg->el.handler[e->etype](cfg, - cfg_to_ndev(cfg), + if (cfg_priv->el.handler[e->etype]) + cfg_priv->el.handler[e->etype](cfg_priv, + cfg_to_ndev(cfg_priv), &e->emsg, e->edata); else WL_INFO("Unknown Event (%d): ignoring\n", e->etype); brcmf_put_event(e); - } while ((e = brcmf_deq_event(cfg))); + } while ((e = brcmf_deq_event(cfg_priv))); } -static void brcmf_init_eq(struct brcmf_cfg80211_info *cfg) +static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv) { - spin_lock_init(&cfg->evt_q_lock); - INIT_LIST_HEAD(&cfg->evt_q_list); + spin_lock_init(&cfg_priv->evt_q_lock); + INIT_LIST_HEAD(&cfg_priv->evt_q_list); } -static void brcmf_flush_eq(struct brcmf_cfg80211_info *cfg) +static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv) { struct brcmf_cfg80211_event_q *e; - spin_lock_irq(&cfg->evt_q_lock); - while (!list_empty(&cfg->evt_q_list)) { - e = list_first_entry(&cfg->evt_q_list, + spin_lock_irq(&cfg_priv->evt_q_lock); + while (!list_empty(&cfg_priv->evt_q_list)) { + e = list_first_entry(&cfg_priv->evt_q_list, struct brcmf_cfg80211_event_q, evt_q_list); list_del(&e->evt_q_list); kfree(e); } - spin_unlock_irq(&cfg->evt_q_lock); + spin_unlock_irq(&cfg_priv->evt_q_lock); } -static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) +static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv) { s32 err = 0; - cfg->scan_request = NULL; - cfg->pwr_save = true; + cfg_priv->scan_request = NULL; + cfg_priv->pwr_save = true; #ifdef CONFIG_BRCMISCAN - cfg->iscan_on = true; /* iscan on & off switch. + cfg_priv->iscan_on = true; /* iscan on & off switch. we enable iscan per default */ - cfg->escan_on = false; /* escan on & off switch. + cfg_priv->escan_on = false; /* escan on & off switch. we disable escan per default */ #else - cfg->iscan_on = false; /* iscan on & off switch. + cfg_priv->iscan_on = false; /* iscan on & off switch. we disable iscan per default */ - cfg->escan_on = true; /* escan on & off switch. + cfg_priv->escan_on = true; /* escan on & off switch. we enable escan per default */ #endif - cfg->roam_on = true; /* roam on & off switch. + cfg_priv->roam_on = true; /* roam on & off switch. we enable roam per default */ - cfg->iscan_kickstart = false; - cfg->active_scan = true; /* we do active scan for + cfg_priv->iscan_kickstart = false; + cfg_priv->active_scan = true; /* we do active scan for specific scan per default */ - cfg->dongle_up = false; /* dongle is not up yet */ - brcmf_init_eq(cfg); - err = brcmf_init_priv_mem(cfg); + cfg_priv->dongle_up = false; /* dongle is not up yet */ + brcmf_init_eq(cfg_priv); + err = brcmf_init_priv_mem(cfg_priv); if (err) return err; - INIT_WORK(&cfg->event_work, brcmf_cfg80211_event_handler); - brcmf_init_eloop_handler(&cfg->el); - mutex_init(&cfg->usr_sync); - err = brcmf_init_iscan(cfg); + INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler); + brcmf_init_eloop_handler(&cfg_priv->el); + mutex_init(&cfg_priv->usr_sync); + err = brcmf_init_iscan(cfg_priv); if (err) return err; - brcmf_init_escan(cfg); - brcmf_init_conf(cfg->conf); - brcmf_init_prof(cfg->profile); - brcmf_link_down(cfg); + brcmf_init_escan(cfg_priv); + brcmf_init_conf(cfg_priv->conf); + brcmf_init_prof(cfg_priv->profile); + brcmf_link_down(cfg_priv); return err; } -static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg) +static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv) { - cancel_work_sync(&cfg->event_work); - cfg->dongle_up = false; /* dongle down */ - brcmf_flush_eq(cfg); - brcmf_link_down(cfg); - brcmf_abort_scanning(cfg); - brcmf_deinit_priv_mem(cfg); + cancel_work_sync(&cfg_priv->event_work); + cfg_priv->dongle_up = false; /* dongle down */ + brcmf_flush_eq(cfg_priv); + brcmf_link_down(cfg_priv); + brcmf_term_iscan(cfg_priv); + brcmf_deinit_priv_mem(cfg_priv); } -struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, - struct device *busdev, - struct brcmf_pub *drvr) +struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, + struct device *busdev, + void *data) { struct wireless_dev *wdev; - struct brcmf_cfg80211_info *cfg; + struct brcmf_cfg80211_priv *cfg_priv; + struct brcmf_cfg80211_iface *ci; + struct brcmf_cfg80211_dev *cfg_dev; s32 err = 0; if (!ndev) { WL_ERR("ndev is invalid\n"); return NULL; } + cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL); + if (!cfg_dev) + return NULL; - wdev = brcmf_alloc_wdev(busdev); + wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev); if (IS_ERR(wdev)) { + kfree(cfg_dev); return NULL; } wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); - cfg = wdev_to_cfg(wdev); - cfg->wdev = wdev; - cfg->pub = drvr; + cfg_priv = wdev_to_cfg(wdev); + cfg_priv->wdev = wdev; + cfg_priv->pub = data; + ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci; + ci->cfg_priv = cfg_priv; ndev->ieee80211_ptr = wdev; SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); wdev->netdev = ndev; - err = wl_init_priv(cfg); + err = wl_init_priv(cfg_priv); if (err) { WL_ERR("Failed to init iwm_priv (%d)\n", err); goto cfg80211_attach_out; } + brcmf_set_drvdata(cfg_dev, ci); - return cfg; + return cfg_dev; cfg80211_attach_out: - brcmf_free_wdev(cfg); + brcmf_free_wdev(cfg_priv); + kfree(cfg_dev); return NULL; } -void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) +void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev) { - wl_deinit_priv(cfg); - brcmf_free_wdev(cfg); + struct brcmf_cfg80211_priv *cfg_priv; + + cfg_priv = brcmf_priv_get(cfg_dev); + + wl_deinit_priv(cfg_priv); + brcmf_free_wdev(cfg_priv); + brcmf_set_drvdata(cfg_dev, NULL); + kfree(cfg_dev); } void @@ -5180,10 +4024,10 @@ brcmf_cfg80211_event(struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { u32 event_type = be32_to_cpu(e->event_type); - struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); - if (!brcmf_enq_event(cfg, event_type, e, data)) - schedule_work(&cfg->event_work); + if (!brcmf_enq_event(cfg_priv, event_type, e, data)) + schedule_work(&cfg_priv->event_work); } static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) @@ -5204,9 +4048,6 @@ static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) case NL80211_IFTYPE_STATION: infra = 1; break; - case NL80211_IFTYPE_AP: - infra = 1; - break; default: err = -EINVAL; WL_ERR("invalid type (%d)\n", iftype); @@ -5260,7 +4101,6 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev) setbit(eventmask, BRCMF_E_JOIN_START); setbit(eventmask, BRCMF_E_SCAN_COMPLETE); setbit(eventmask, BRCMF_E_ESCAN_RESULT); - setbit(eventmask, BRCMF_E_PFN_NET_FOUND); brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); @@ -5379,46 +4219,46 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, return err; } -static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg) +static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv) { struct wiphy *wiphy; s32 phy_list; s8 phy; s32 err = 0; - err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCM_GET_PHYLIST, + err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST, &phy_list, sizeof(phy_list)); if (err) { WL_ERR("error (%d)\n", err); return err; } - phy = ((char *)&phy_list)[0]; + phy = ((char *)&phy_list)[1]; WL_INFO("%c phy\n", phy); if (phy == 'n' || phy == 'a') { - wiphy = cfg_to_wiphy(cfg); + wiphy = cfg_to_wiphy(cfg_priv); wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; } return err; } -static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv) { - return wl_update_wiphybands(cfg); + return wl_update_wiphybands(cfg_priv); } -static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) +static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv) { struct net_device *ndev; struct wireless_dev *wdev; s32 power_mode; s32 err = 0; - if (cfg->dongle_up) + if (cfg_priv->dongle_up) return err; - ndev = cfg_to_ndev(cfg); + ndev = cfg_to_ndev(cfg_priv); wdev = ndev->ieee80211_ptr; brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME, @@ -5428,21 +4268,21 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) if (err) goto default_conf_out; - power_mode = cfg->pwr_save ? PM_FAST : PM_OFF; + power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF; err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode); if (err) goto default_conf_out; WL_INFO("power save set to %s\n", (power_mode ? "enabled" : "disabled")); - err = brcmf_dongle_roam(ndev, (cfg->roam_on ? 0 : 1), + err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1), WL_BEACON_TIMEOUT); if (err) goto default_conf_out; err = brcmf_dongle_mode(ndev, wdev->iftype); if (err && err != -EINPROGRESS) goto default_conf_out; - err = brcmf_dongle_probecap(cfg); + err = brcmf_dongle_probecap(cfg_priv); if (err) goto default_conf_out; @@ -5450,31 +4290,31 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) default_conf_out: - cfg->dongle_up = true; + cfg_priv->dongle_up = true; return err; } -static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_info *cfg) +static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv) { char buf[10+IFNAMSIZ]; struct dentry *fd; s32 err = 0; - sprintf(buf, "netdev:%s", cfg_to_ndev(cfg)->name); - cfg->debugfsdir = debugfs_create_dir(buf, - cfg_to_wiphy(cfg)->debugfsdir); + sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name); + cfg_priv->debugfsdir = debugfs_create_dir(buf, + cfg_to_wiphy(cfg_priv)->debugfsdir); - fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg->debugfsdir, - (u16 *)&cfg->profile->beacon_interval); + fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir, + (u16 *)&cfg_priv->profile->beacon_interval); if (!fd) { err = -ENOMEM; goto err_out; } - fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg->debugfsdir, - (u8 *)&cfg->profile->dtim_period); + fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir, + (u8 *)&cfg_priv->profile->dtim_period); if (!fd) { err = -ENOMEM; goto err_out; @@ -5484,40 +4324,40 @@ static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_info *cfg) return err; } -static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_info *cfg) +static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv) { - debugfs_remove_recursive(cfg->debugfsdir); - cfg->debugfsdir = NULL; + debugfs_remove_recursive(cfg_priv->debugfsdir); + cfg_priv->debugfsdir = NULL; } -static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) +static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv) { s32 err = 0; - set_bit(WL_STATUS_READY, &cfg->status); + set_bit(WL_STATUS_READY, &cfg_priv->status); - brcmf_debugfs_add_netdev_params(cfg); + brcmf_debugfs_add_netdev_params(cfg_priv); - err = brcmf_config_dongle(cfg); + err = brcmf_config_dongle(cfg_priv); if (err) return err; - brcmf_invoke_iscan(cfg); + brcmf_invoke_iscan(cfg_priv); return err; } -static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) +static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) { /* * While going down, if associated with AP disassociate * from AP to save power */ - if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) || - test_bit(WL_STATUS_CONNECTING, &cfg->status)) && - test_bit(WL_STATUS_READY, &cfg->status)) { + if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || + test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && + test_bit(WL_STATUS_READY, &cfg_priv->status)) { WL_INFO("Disassociating from AP"); - brcmf_link_down(cfg); + brcmf_link_down(cfg_priv); /* Make sure WPA_Supplicant receives all the event generated due to DISASSOC call to the fw to keep @@ -5526,33 +4366,63 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) brcmf_delay(500); } - brcmf_abort_scanning(cfg); - clear_bit(WL_STATUS_READY, &cfg->status); + set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); + brcmf_term_iscan(cfg_priv); + if (cfg_priv->scan_request) { + cfg80211_scan_done(cfg_priv->scan_request, true); + /* May need to perform this to cover rmmod */ + /* wl_set_mpc(cfg_to_ndev(wl), 1); */ + cfg_priv->scan_request = NULL; + } + clear_bit(WL_STATUS_READY, &cfg_priv->status); + clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); + clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); - brcmf_debugfs_remove_netdev(cfg); + brcmf_debugfs_remove_netdev(cfg_priv); return 0; } -s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) +s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev) { + struct brcmf_cfg80211_priv *cfg_priv; s32 err = 0; - mutex_lock(&cfg->usr_sync); - err = __brcmf_cfg80211_up(cfg); - mutex_unlock(&cfg->usr_sync); + cfg_priv = brcmf_priv_get(cfg_dev); + mutex_lock(&cfg_priv->usr_sync); + err = __brcmf_cfg80211_up(cfg_priv); + mutex_unlock(&cfg_priv->usr_sync); return err; } -s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) +s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev) { + struct brcmf_cfg80211_priv *cfg_priv; s32 err = 0; - mutex_lock(&cfg->usr_sync); - err = __brcmf_cfg80211_down(cfg); - mutex_unlock(&cfg->usr_sync); + cfg_priv = brcmf_priv_get(cfg_dev); + mutex_lock(&cfg_priv->usr_sync); + err = __brcmf_cfg80211_down(cfg_priv); + mutex_unlock(&cfg_priv->usr_sync); return err; } +static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv, + u8 t, u8 l, u8 *v) +{ + struct brcmf_cfg80211_ie *ie = &cfg_priv->ie; + s32 err = 0; + + if (ie->offset + l + 2 > WL_TLV_INFO_MAX) { + WL_ERR("ei crosses buffer boundary\n"); + return -ENOSPC; + } + ie->buf[ie->offset] = t; + ie->buf[ie->offset + 1] = l; + memcpy(&ie->buf[ie->offset + 2], v, l); + ie->offset += l + 2; + + return err; +} diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 71ced174748a..3b2129738d30 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -17,6 +17,12 @@ #ifndef _wl_cfg80211_h_ #define _wl_cfg80211_h_ +struct brcmf_cfg80211_conf; +struct brcmf_cfg80211_iface; +struct brcmf_cfg80211_priv; +struct brcmf_cfg80211_security; +struct brcmf_cfg80211_ibss; + #define WL_DBG_NONE 0 #define WL_DBG_CONN (1 << 5) #define WL_DBG_SCAN (1 << 4) @@ -124,18 +130,13 @@ do { \ #define WL_ESCAN_ACTION_CONTINUE 2 #define WL_ESCAN_ACTION_ABORT 3 -#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ -#define IE_MAX_LEN 512 - /* dongle status */ enum wl_status { WL_STATUS_READY, WL_STATUS_SCANNING, WL_STATUS_SCAN_ABORTING, WL_STATUS_CONNECTING, - WL_STATUS_CONNECTED, - WL_STATUS_AP_CREATING, - WL_STATUS_AP_CREATED + WL_STATUS_CONNECTED }; /* wi-fi mode */ @@ -175,17 +176,23 @@ struct brcmf_cfg80211_conf { struct ieee80211_channel channel; }; -/* forward declaration */ -struct brcmf_cfg80211_info; - /* cfg80211 main event loop */ struct brcmf_cfg80211_event_loop { - s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_info *cfg, + s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e, void *data); }; +/* representing interface of cfg80211 plane */ +struct brcmf_cfg80211_iface { + struct brcmf_cfg80211_priv *cfg_priv; +}; + +struct brcmf_cfg80211_dev { + void *driver_data; /* to store cfg80211 object information */ +}; + /* basic structure of scan request */ struct brcmf_cfg80211_scan_req { struct brcmf_ssid_le ssid_le; @@ -238,7 +245,7 @@ struct brcmf_cfg80211_profile { /* dongle iscan event loop */ struct brcmf_cfg80211_iscan_eloop { s32 (*handler[WL_SCAN_ERSULTS_LAST]) - (struct brcmf_cfg80211_info *cfg); + (struct brcmf_cfg80211_priv *cfg_priv); }; /* dongle iscan controller */ @@ -288,227 +295,97 @@ struct escan_info { struct net_device *ndev; }; -/* Structure to hold WPS, WPA IEs for a AP */ -struct ap_info { - u8 probe_res_ie[IE_MAX_LEN]; - u8 beacon_ie[IE_MAX_LEN]; - u32 probe_res_ie_len; - u32 beacon_ie_len; - u8 *wpa_ie; - u8 *rsn_ie; - bool security_mode; -}; - -/** - * struct brcmf_pno_param_le - PNO scan configuration parameters - * - * @version: PNO parameters version. - * @scan_freq: scan frequency. - * @lost_network_timeout: #sec. to declare discovered network as lost. - * @flags: Bit field to control features of PFN such as sort criteria auto - * enable switch and background scan. - * @rssi_margin: Margin to avoid jitter for choosing a PFN based on RSSI sort - * criteria. - * @bestn: number of best networks in each scan. - * @mscan: number of scans recorded. - * @repeat: minimum number of scan intervals before scan frequency changes - * in adaptive scan. - * @exp: exponent of 2 for maximum scan interval. - * @slow_freq: slow scan period. - */ -struct brcmf_pno_param_le { - __le32 version; - __le32 scan_freq; - __le32 lost_network_timeout; - __le16 flags; - __le16 rssi_margin; - u8 bestn; - u8 mscan; - u8 repeat; - u8 exp; - __le32 slow_freq; -}; - -/** - * struct brcmf_pno_net_param_le - scan parameters per preferred network. - * - * @ssid: ssid name and its length. - * @flags: bit2: hidden. - * @infra: BSS vs IBSS. - * @auth: Open vs Closed. - * @wpa_auth: WPA type. - * @wsec: wsec value. - */ -struct brcmf_pno_net_param_le { - struct brcmf_ssid_le ssid; - __le32 flags; - __le32 infra; - __le32 auth; - __le32 wpa_auth; - __le32 wsec; -}; - -/** - * struct brcmf_pno_net_info_le - information per found network. - * - * @bssid: BSS network identifier. - * @channel: channel number only. - * @SSID_len: length of ssid. - * @SSID: ssid characters. - * @RSSI: receive signal strength (in dBm). - * @timestamp: age in seconds. - */ -struct brcmf_pno_net_info_le { - u8 bssid[ETH_ALEN]; - u8 channel; - u8 SSID_len; - u8 SSID[32]; - __le16 RSSI; - __le16 timestamp; -}; - -/** - * struct brcmf_pno_scanresults_le - result returned in PNO NET FOUND event. - * - * @version: PNO version identifier. - * @status: indicates completion status of PNO scan. - * @count: amount of brcmf_pno_net_info_le entries appended. - */ -struct brcmf_pno_scanresults_le { - __le32 version; - __le32 status; - __le32 count; -}; - -/** - * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface - * - * @wdev: representing wl cfg80211 device. - * @conf: dongle configuration. - * @scan_request: cfg80211 scan request object. - * @el: main event loop. - * @evt_q_list: used for event queue. - * @evt_q_lock: for event queue synchronization. - * @usr_sync: mainly for dongle up/down synchronization. - * @bss_list: bss_list holding scanned ap information. - * @scan_results: results of the last scan. - * @scan_req_int: internal scan request object. - * @bss_info: bss information for cfg80211 layer. - * @ie: information element object for internal purpose. - * @profile: holding dongle profile. - * @iscan: iscan controller information. - * @conn_info: association info. - * @pmk_list: wpa2 pmk list. - * @event_work: event handler work struct. - * @status: current dongle status. - * @pub: common driver information. - * @channel: current channel. - * @iscan_on: iscan on/off switch. - * @iscan_kickstart: indicate iscan already started. - * @active_scan: current scan mode. - * @sched_escan: e-scan for scheduled scan support running. - * @ibss_starter: indicates this sta is ibss starter. - * @link_up: link/connection up flag. - * @pwr_save: indicate whether dongle to support power save mode. - * @dongle_up: indicate whether dongle up or not. - * @roam_on: on/off switch for dongle self-roaming. - * @scan_tried: indicates if first scan attempted. - * @dcmd_buf: dcmd buffer. - * @extra_buf: mainly to grab assoc information. - * @debugfsdir: debugfs folder for this device. - * @escan_on: escan on/off switch. - * @escan_info: escan information. - * @escan_timeout: Timer for catch scan timeout. - * @escan_timeout_work: scan timeout worker. - * @escan_ioctl_buf: dongle command buffer for escan commands. - * @ap_info: host ap information. - * @ci: used to link this structure to netdev private data. - */ -struct brcmf_cfg80211_info { - struct wireless_dev *wdev; - struct brcmf_cfg80211_conf *conf; - struct cfg80211_scan_request *scan_request; - struct brcmf_cfg80211_event_loop el; - struct list_head evt_q_list; - spinlock_t evt_q_lock; - struct mutex usr_sync; - struct brcmf_scan_results *bss_list; +/* dongle private data of cfg80211 interface */ +struct brcmf_cfg80211_priv { + struct wireless_dev *wdev; /* representing wl cfg80211 device */ + struct brcmf_cfg80211_conf *conf; /* dongle configuration */ + struct cfg80211_scan_request *scan_request; /* scan request + object */ + struct brcmf_cfg80211_event_loop el; /* main event loop */ + struct list_head evt_q_list; /* used for event queue */ + spinlock_t evt_q_lock; /* for event queue synchronization */ + struct mutex usr_sync; /* maily for dongle up/down synchronization */ + struct brcmf_scan_results *bss_list; /* bss_list holding scanned + ap information */ struct brcmf_scan_results *scan_results; - struct brcmf_cfg80211_scan_req *scan_req_int; - struct wl_cfg80211_bss_info *bss_info; - struct brcmf_cfg80211_ie ie; - struct brcmf_cfg80211_profile *profile; - struct brcmf_cfg80211_iscan_ctrl *iscan; - struct brcmf_cfg80211_connect_info conn_info; - struct brcmf_cfg80211_pmk_list *pmk_list; - struct work_struct event_work; - unsigned long status; - struct brcmf_pub *pub; - u32 channel; - bool iscan_on; - bool iscan_kickstart; - bool active_scan; - bool sched_escan; - bool ibss_starter; - bool link_up; - bool pwr_save; - bool dongle_up; - bool roam_on; - bool scan_tried; - u8 *dcmd_buf; - u8 *extra_buf; + struct brcmf_cfg80211_scan_req *scan_req_int; /* scan request object + for internal purpose */ + struct wl_cfg80211_bss_info *bss_info; /* bss information for + cfg80211 layer */ + struct brcmf_cfg80211_ie ie; /* information element object for + internal purpose */ + struct brcmf_cfg80211_profile *profile; /* holding dongle profile */ + struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */ + struct brcmf_cfg80211_connect_info conn_info; /* association info */ + struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */ + struct work_struct event_work; /* event handler work struct */ + unsigned long status; /* current dongle status */ + void *pub; + u32 channel; /* current channel */ + bool iscan_on; /* iscan on/off switch */ + bool iscan_kickstart; /* indicate iscan already started */ + bool active_scan; /* current scan mode */ + bool ibss_starter; /* indicates this sta is ibss starter */ + bool link_up; /* link/connection up flag */ + bool pwr_save; /* indicate whether dongle to support + power save mode */ + bool dongle_up; /* indicate whether dongle up or not */ + bool roam_on; /* on/off switch for dongle self-roaming */ + bool scan_tried; /* indicates if first scan attempted */ + u8 *dcmd_buf; /* dcmd buffer */ + u8 *extra_buf; /* maily to grab assoc information */ struct dentry *debugfsdir; - bool escan_on; - struct escan_info escan_info; - struct timer_list escan_timeout; - struct work_struct escan_timeout_work; + bool escan_on; /* escan on/off switch */ + struct escan_info escan_info; /* escan information */ + struct timer_list escan_timeout; /* Timer for catch scan timeout */ + struct work_struct escan_timeout_work; /* scan timeout worker */ u8 *escan_ioctl_buf; - struct ap_info *ap_info; + u8 ci[0] __aligned(NETDEV_ALIGN); }; -static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *w) +static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_priv *w) { return w->wdev->wiphy; } -static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w) +static inline struct brcmf_cfg80211_priv *wiphy_to_cfg(struct wiphy *w) { - return (struct brcmf_cfg80211_info *)(wiphy_priv(w)); + return (struct brcmf_cfg80211_priv *)(wiphy_priv(w)); } -static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd) +static inline struct brcmf_cfg80211_priv *wdev_to_cfg(struct wireless_dev *wd) { - return (struct brcmf_cfg80211_info *)(wdev_priv(wd)); + return (struct brcmf_cfg80211_priv *)(wdev_priv(wd)); } -static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg) +static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_priv *cfg) { return cfg->wdev->netdev; } -static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev) +static inline struct brcmf_cfg80211_priv *ndev_to_cfg(struct net_device *ndev) { return wdev_to_cfg(ndev->ieee80211_ptr); } -#define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data)) +#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data)) #define cfg_to_iscan(w) (w->iscan) static inline struct -brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg) +brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg) { return &cfg->conn_info; } -struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, - struct device *busdev, - struct brcmf_pub *drvr); -void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); +extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, + struct device *busdev, + void *data); +extern void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg); /* event handler from dongle */ -void brcmf_cfg80211_event(struct net_device *ndev, - const struct brcmf_event_msg *e, void *data); -s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg); -s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg); +extern void brcmf_cfg80211_event(struct net_device *ndev, + const struct brcmf_event_msg *e, void *data); +extern s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev); +extern s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev); #endif /* _wl_cfg80211_h_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 64a48f06d68b..7ed7d7577024 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -77,7 +77,7 @@ NL80211_RRF_NO_IBSS) static const struct ieee80211_regdomain brcms_regdom_x2 = { - .n_reg_rules = 6, + .n_reg_rules = 7, .alpha2 = "X2", .reg_rules = { BRCM_2GHZ_2412_2462, diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index a744ea5a9559..718da8d6d658 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -304,10 +304,7 @@ static int brcms_ops_start(struct ieee80211_hw *hw) wl->mute_tx = true; if (!wl->pub->up) - if (!blocked) - err = brcms_up(wl); - else - err = -ERFKILL; + err = brcms_up(wl); else err = -ENODEV; spin_unlock_bh(&wl->lock); diff --git a/trunk/drivers/net/wireless/ipw2x00/libipw_wx.c b/trunk/drivers/net/wireless/ipw2x00/libipw_wx.c index 54aba4744438..1571505b1a38 100644 --- a/trunk/drivers/net/wireless/ipw2x00/libipw_wx.c +++ b/trunk/drivers/net/wireless/ipw2x00/libipw_wx.c @@ -675,7 +675,7 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee, } done: if (ieee->set_security) - ieee->set_security(dev, &sec); + ieee->set_security(ieee->dev, &sec); return ret; } diff --git a/trunk/drivers/net/wireless/iwlegacy/common.c b/trunk/drivers/net/wireless/iwlegacy/common.c index 318ed3c9fe74..eb9987520d61 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.c +++ b/trunk/drivers/net/wireless/iwlegacy/common.c @@ -1586,9 +1586,9 @@ il_fill_probe_req(struct il_priv *il, struct ieee80211_mgmt *frame, return 0; frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - eth_broadcast_addr(frame->da); + memcpy(frame->da, il_bcast_addr, ETH_ALEN); memcpy(frame->sa, ta, ETH_ALEN); - eth_broadcast_addr(frame->bssid); + memcpy(frame->bssid, il_bcast_addr, ETH_ALEN); frame->seq_ctrl = 0; len += 24; diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/scan.c b/trunk/drivers/net/wireless/iwlwifi/dvm/scan.c index bb9f6252d28f..e3467fa86899 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/scan.c @@ -612,9 +612,9 @@ static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, return 0; frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - eth_broadcast_addr(frame->da); + memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); memcpy(frame->sa, ta, ETH_ALEN); - eth_broadcast_addr(frame->bssid); + memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); frame->seq_ctrl = 0; len += 24; diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c b/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c index cd9b6de4273e..fe36a38f3505 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c @@ -128,11 +128,10 @@ int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_addsta_cmd *addsta = + (struct iwl_addsta_cmd *) cmd->payload; - if (!cmd) - return 0; - - return iwl_process_add_sta_resp(priv, (void *)cmd->payload, pkt); + return iwl_process_add_sta_resp(priv, addsta, pkt); } int iwl_send_add_sta(struct iwl_priv *priv, diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/ucode.c b/trunk/drivers/net/wireless/iwlwifi/dvm/ucode.c index 2cb1efbc5ed1..6d8d6dd7943f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/ucode.c @@ -295,7 +295,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) static int iwl_verify_sec_sparse(struct iwl_priv *priv, const struct fw_desc *fw_desc) { - __le32 *image = (__le32 *)fw_desc->data; + __le32 *image = (__le32 *)fw_desc->v_addr; u32 len = fw_desc->len; u32 val; u32 i; @@ -319,7 +319,7 @@ static int iwl_verify_sec_sparse(struct iwl_priv *priv, static void iwl_print_mismatch_sec(struct iwl_priv *priv, const struct fw_desc *fw_desc) { - __le32 *image = (__le32 *)fw_desc->data; + __le32 *image = (__le32 *)fw_desc->v_addr; u32 len = fw_desc->len; u32 val; u32 offs; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c index 198634b75ed0..48d6d44c16d0 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -64,7 +64,6 @@ #include #include #include -#include #include "iwl-drv.h" #include "iwl-debug.h" @@ -165,8 +164,10 @@ struct fw_sec { static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc) { - vfree(desc->data); - desc->data = NULL; + if (desc->v_addr) + dma_free_coherent(drv->trans->dev, desc->len, + desc->v_addr, desc->p_addr); + desc->v_addr = NULL; desc->len = 0; } @@ -185,24 +186,21 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) } static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, - struct fw_sec *sec) + struct fw_sec *sec) { - void *data; - - desc->data = NULL; - - if (!sec || !sec->size) + if (!sec || !sec->size) { + desc->v_addr = NULL; return -EINVAL; + } - data = vmalloc(sec->size); - if (!data) + desc->v_addr = dma_alloc_coherent(drv->trans->dev, sec->size, + &desc->p_addr, GFP_KERNEL); + if (!desc->v_addr) return -ENOMEM; desc->len = sec->size; desc->offset = sec->offset; - memcpy(data, sec->data, desc->len); - desc->data = data; - + memcpy(desc->v_addr, sec->data, sec->size); return 0; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-fw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-fw.h index d1a86b66bc51..2153e4cc5572 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-fw.h @@ -124,7 +124,8 @@ struct iwl_ucode_capabilities { /* one for each uCode image (inst/data, init/runtime/wowlan) */ struct fw_desc { - const void *data; /* vmalloc'ed data */ + dma_addr_t p_addr; /* hardware address */ + void *v_addr; /* software address */ u32 len; /* size in bytes */ u32 offset; /* offset in the device */ }; diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/drv.c b/trunk/drivers/net/wireless/iwlwifi/pcie/drv.c index 2a4675396707..89bfb43f4946 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -263,6 +263,8 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 +#ifndef CONFIG_IWLWIFI_IDI + static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); @@ -305,6 +307,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } +#endif /* CONFIG_IWLWIFI_IDI */ + #ifdef CONFIG_PM_SLEEP static int iwl_pci_suspend(struct device *device) @@ -349,6 +353,15 @@ static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); #endif +#ifdef CONFIG_IWLWIFI_IDI +/* + * Defined externally in iwl-idi.c + */ +int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +void __devexit iwl_pci_remove(struct pci_dev *pdev); + +#endif /* CONFIG_IWLWIFI_IDI */ + static struct pci_driver iwl_pci_driver = { .name = DRV_NAME, .id_table = iwl_hw_card_ids, diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h index 401178f44a3b..71c79943e633 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -311,7 +311,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans); ******************************************************/ void iwl_bg_rx_replenish(struct work_struct *data); void iwl_irq_tasklet(struct iwl_trans *trans); -void iwl_rx_replenish(struct iwl_trans *trans); +void iwlagn_rx_replenish(struct iwl_trans *trans); void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, struct iwl_rx_queue *q); diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c index 17c8e5d82681..498372008810 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -35,6 +35,10 @@ #include "internal.h" #include "iwl-op-mode.h" +#ifdef CONFIG_IWLWIFI_IDI +#include "iwl-amfh.h" +#endif + /****************************************************************************** * * RX path functions @@ -177,15 +181,15 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, } /** - * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr + * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ -static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr) +static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) { return cpu_to_le32((u32)(dma_addr >> 8)); } /** - * iwl_rx_queue_restock - refill RX queue from pre-allocated pool + * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool * * If there are slots in the RX queue that need to be restocked, * and we have free pre-allocated buffers, fill the ranks as much @@ -195,7 +199,7 @@ static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr) * also updates the memory address in the firmware to reference the new * target buffer. */ -static void iwl_rx_queue_restock(struct iwl_trans *trans) +static void iwlagn_rx_queue_restock(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; @@ -203,17 +207,6 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans) struct iwl_rx_mem_buffer *rxb; unsigned long flags; - /* - * If the device isn't enabled - not need to try to add buffers... - * This can happen when we stop the device and still have an interrupt - * pending. We stop the APM before we sync the interrupts / tasklets - * because we have to (see comment there). On the other hand, since - * the APM is stopped, we cannot access the HW (in particular not prph). - * So don't try to restock if the APM has been already stopped. - */ - if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) - return; - spin_lock_irqsave(&rxq->lock, flags); while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { /* The overwritten rxb must be a used one */ @@ -226,7 +219,7 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans) list_del(element); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma); + rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -237,6 +230,7 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans) if (rxq->free_count <= RX_LOW_WATERMARK) schedule_work(&trans_pcie->rx_replenish); + /* If we've added more space for the firmware to place data, tell it. * Increment device's write pointer in multiples of 8. */ if (rxq->write_actual != (rxq->write & ~0x7)) { @@ -247,16 +241,15 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans) } } -/* - * iwl_rx_allocate - allocate a page for each used RBD +/** + * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free * - * A used RBD is an Rx buffer that has been given to the stack. To use it again - * a page must be allocated and the RBD must point to the page. This function - * doesn't change the HW pointer but handles the list of pages that is used by - * iwl_rx_queue_restock. The latter function will update the HW to use the newly - * allocated buffers. + * When moving to rx_free an SKB is allocated for the slot. + * + * Also restock the Rx queue via iwl_rx_queue_restock. + * This is called as a scheduled work item (except for during initialization) */ -static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) +static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; @@ -335,31 +328,23 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) } } -/* - * iwl_rx_replenish - Move all used buffers from rx_used to rx_free - * - * When moving to rx_free an page is allocated for the slot. - * - * Also restock the Rx queue via iwl_rx_queue_restock. - * This is called as a scheduled work item (except for during initialization) - */ -void iwl_rx_replenish(struct iwl_trans *trans) +void iwlagn_rx_replenish(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); unsigned long flags; - iwl_rx_allocate(trans, GFP_KERNEL); + iwlagn_rx_allocate(trans, GFP_KERNEL); spin_lock_irqsave(&trans_pcie->irq_lock, flags); - iwl_rx_queue_restock(trans); + iwlagn_rx_queue_restock(trans); spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); } -static void iwl_rx_replenish_now(struct iwl_trans *trans) +static void iwlagn_rx_replenish_now(struct iwl_trans *trans) { - iwl_rx_allocate(trans, GFP_ATOMIC); + iwlagn_rx_allocate(trans, GFP_ATOMIC); - iwl_rx_queue_restock(trans); + iwlagn_rx_queue_restock(trans); } void iwl_bg_rx_replenish(struct work_struct *data) @@ -367,7 +352,7 @@ void iwl_bg_rx_replenish(struct work_struct *data) struct iwl_trans_pcie *trans_pcie = container_of(data, struct iwl_trans_pcie, rx_replenish); - iwl_rx_replenish(trans_pcie->trans); + iwlagn_rx_replenish(trans_pcie->trans); } static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, @@ -545,7 +530,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) count++; if (count >= 8) { rxq->read = i; - iwl_rx_replenish_now(trans); + iwlagn_rx_replenish_now(trans); count = 0; } } @@ -554,9 +539,9 @@ static void iwl_rx_handle(struct iwl_trans *trans) /* Backtrack one entry */ rxq->read = i; if (fill_rx) - iwl_rx_replenish_now(trans); + iwlagn_rx_replenish_now(trans); else - iwl_rx_queue_restock(trans); + iwlagn_rx_queue_restock(trans); } /** @@ -738,9 +723,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* Disable periodic interrupt; we use it as just a one-shot. */ iwl_write8(trans, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); - +#ifdef CONFIG_IWLWIFI_IDI + iwl_amfh_rx_handler(); +#else iwl_rx_handle(trans); - +#endif /* * Enable periodic interrupt in 8 msec only if we received * real RX interrupt (instead of just periodic int), to catch diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c index 34aee0688e0d..848851177e7e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -216,7 +216,7 @@ static int iwl_rx_init(struct iwl_trans *trans) rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); - iwl_rx_replenish(trans); + iwlagn_rx_replenish(trans); iwl_trans_rx_hw_init(trans, rxq); @@ -855,8 +855,10 @@ static int iwl_nic_init(struct iwl_trans *trans) iwl_op_mode_nic_config(trans->op_mode); +#ifndef CONFIG_IWLWIFI_IDI /* Allocate the RX queue, or reset if it is already allocated */ iwl_rx_init(trans); +#endif /* Allocate or reset and init all Tx and Command queues */ if (iwl_tx_init(trans)) @@ -923,10 +925,13 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans) /* * ucode */ -static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr, - dma_addr_t phy_addr, u32 byte_cnt) +static int iwl_load_section(struct iwl_trans *trans, u8 section_num, + const struct fw_desc *section) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + dma_addr_t phy_addr = section->p_addr; + u32 byte_cnt = section->len; + u32 dst_addr = section->offset; int ret; trans_pcie->ucode_write_complete = false; @@ -940,8 +945,8 @@ static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr, dst_addr); iwl_write_direct32(trans, - FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), - phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); + FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), + phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); iwl_write_direct32(trans, FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), @@ -960,64 +965,33 @@ static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr, FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); + IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", + section_num); ret = wait_event_timeout(trans_pcie->ucode_write_waitq, trans_pcie->ucode_write_complete, 5 * HZ); if (!ret) { - IWL_ERR(trans, "Failed to load firmware chunk!\n"); + IWL_ERR(trans, "Could not load the [%d] uCode section\n", + section_num); return -ETIMEDOUT; } return 0; } -static int iwl_load_section(struct iwl_trans *trans, u8 section_num, - const struct fw_desc *section) -{ - u8 *v_addr; - dma_addr_t p_addr; - u32 offset; - int ret = 0; - - IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", - section_num); - - v_addr = dma_alloc_coherent(trans->dev, PAGE_SIZE, &p_addr, GFP_KERNEL); - if (!v_addr) - return -ENOMEM; - - for (offset = 0; offset < section->len; offset += PAGE_SIZE) { - u32 copy_size; - - copy_size = min_t(u32, PAGE_SIZE, section->len - offset); - - memcpy(v_addr, (u8 *)section->data + offset, copy_size); - ret = iwl_load_firmware_chunk(trans, section->offset + offset, - p_addr, copy_size); - if (ret) { - IWL_ERR(trans, - "Could not load the [%d] uCode section\n", - section_num); - break; - } - } - - dma_free_coherent(trans->dev, PAGE_SIZE, v_addr, p_addr); - return ret; -} - static int iwl_load_given_ucode(struct iwl_trans *trans, const struct fw_img *image) { - int i, ret = 0; + int ret = 0; + int i; - for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) { - if (!image->sec[i].data) - break; + for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) { + if (!image->sec[i].p_addr) + break; - ret = iwl_load_section(trans, i, &image->sec[i]); - if (ret) - return ret; - } + ret = iwl_load_section(trans, i, &image->sec[i]); + if (ret) + return ret; + } /* Remove all resets to allow NIC to operate */ iwl_write32(trans, CSR_RESET, 0); @@ -1210,8 +1184,9 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) */ if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) { iwl_trans_tx_stop(trans); +#ifndef CONFIG_IWLWIFI_IDI iwl_trans_rx_stop(trans); - +#endif /* Power-down device's busmaster DMA clocks */ iwl_write_prph(trans, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); @@ -1467,7 +1442,6 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) return err; err_free_irq: - trans_pcie->irq_requested = false; free_irq(trans_pcie->irq, trans); error: iwl_free_isr_ict(trans); @@ -1482,16 +1456,14 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, bool hw_rfkill; unsigned long flags; - spin_lock_irqsave(&trans_pcie->irq_lock, flags); - iwl_disable_interrupts(trans); - spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); - iwl_apm_stop(trans); spin_lock_irqsave(&trans_pcie->irq_lock, flags); iwl_disable_interrupts(trans); spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); + iwl_write32(trans, CSR_INT, 0xFFFFFFFF); + if (!op_mode_leaving) { /* * Even if we stop the HW, we still want the RF kill @@ -1579,8 +1551,9 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); iwl_trans_pcie_tx_free(trans); +#ifndef CONFIG_IWLWIFI_IDI iwl_trans_pcie_rx_free(trans); - +#endif if (trans_pcie->irq_requested == true) { free_irq(trans_pcie->irq, trans); iwl_free_isr_ict(trans); diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index 429ca3215fdb..9d45b3bb974c 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -2056,7 +2056,7 @@ static int __init init_mac80211_hwsim(void) mac80211_hwsim_free(); return err; } -module_init(init_mac80211_hwsim); + static void __exit exit_mac80211_hwsim(void) { @@ -2067,4 +2067,7 @@ static void __exit exit_mac80211_hwsim(void) mac80211_hwsim_free(); unregister_netdev(hwsim_mon); } + + +module_init(init_mac80211_hwsim); module_exit(exit_mac80211_hwsim); diff --git a/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.c b/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.c index 9402b93b9a36..24e2582b467c 100644 --- a/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -302,7 +302,6 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, new_node->start_win = last_seq + 1; new_node->win_size = win_size; - new_node->flags = 0; new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size, GFP_KERNEL); @@ -458,20 +457,13 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, * If seq_num is less then starting win then ignore and drop the * packet */ - if (tbl->flags & RXREOR_FORCE_NO_DROP) { - dev_dbg(priv->adapter->dev, - "RXREOR_FORCE_NO_DROP when HS is activated\n"); - tbl->flags &= ~RXREOR_FORCE_NO_DROP; - } else { - if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { - if (seq_num >= ((start_win + TWOPOW11) & - (MAX_TID_VALUE - 1)) && - seq_num < start_win) - return -1; - } else if ((seq_num < start_win) || - (seq_num > (start_win + TWOPOW11))) { + if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {/* Wrap */ + if (seq_num >= ((start_win + TWOPOW11) & + (MAX_TID_VALUE - 1)) && (seq_num < start_win)) return -1; - } + } else if ((seq_num < start_win) || + (seq_num > (start_win + TWOPOW11))) { + return -1; } /* @@ -482,7 +474,8 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1); if (((end_win < start_win) && - (seq_num < start_win) && (seq_num > end_win)) || + (seq_num < (TWOPOW11 - (MAX_TID_VALUE - start_win))) && + (seq_num > end_win)) || ((end_win > start_win) && ((seq_num > end_win) || (seq_num < start_win)))) { end_win = seq_num; @@ -644,29 +637,3 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv) INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); mwifiex_reset_11n_rx_seq_num(priv); } - -/* - * This function updates all rx_reorder_tbl's flags. - */ -void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags) -{ - struct mwifiex_private *priv; - struct mwifiex_rx_reorder_tbl *tbl; - unsigned long lock_flags; - int i; - - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (!priv) - continue; - if (list_empty(&priv->rx_reorder_tbl_ptr)) - continue; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags); - list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) - tbl->flags = flags; - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags); - } - - return; -} diff --git a/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.h b/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.h index 4064041ac852..72848591691a 100644 --- a/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -41,10 +41,6 @@ #define BA_SETUP_MAX_PACKET_THRESHOLD 16 #define BA_SETUP_PACKET_OFFSET 16 -enum mwifiex_rxreor_flags { - RXREOR_FORCE_NO_DROP = 1<<0, -}; - static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv) { memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq)); @@ -77,6 +73,5 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct struct mwifiex_rx_reorder_tbl * mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta); void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta); -void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags); #endif /* _MWIFIEX_11N_RXREORDER_H_ */ diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index 2691620393ea..b9f7b3e6912d 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -22,7 +22,7 @@ static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { { - .max = 2, .types = BIT(NL80211_IFTYPE_STATION), + .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, { .max = 1, .types = BIT(NL80211_IFTYPE_AP), @@ -77,7 +77,8 @@ static const struct ieee80211_regdomain mwifiex_world_regdom_custom = { * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE */ -u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type) +static u8 +mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type) { switch (chan_type) { case NL80211_CHAN_NO_HT: @@ -137,188 +138,6 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, return 0; } -/* - * This function forms an skb for management frame. - */ -static int -mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len) -{ - u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - u16 pkt_len; - u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT; - struct timeval tv; - - pkt_len = len + ETH_ALEN; - - skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len)); - memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len)); - - memcpy(skb_push(skb, sizeof(tx_control)), - &tx_control, sizeof(tx_control)); - - memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type)); - - /* Add packet data and address4 */ - memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf, - sizeof(struct ieee80211_hdr_3addr)); - memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN); - memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)), - buf + sizeof(struct ieee80211_hdr_3addr), - len - sizeof(struct ieee80211_hdr_3addr)); - - skb->priority = LOW_PRIO_TID; - do_gettimeofday(&tv); - skb->tstamp = timeval_to_ktime(tv); - - return 0; -} - -/* - * CFG802.11 operation handler to transmit a management frame. - */ -static int -mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - enum nl80211_channel_type channel_type, - bool channel_type_valid, unsigned int wait, - const u8 *buf, size_t len, bool no_cck, - bool dont_wait_for_ack, u64 *cookie) -{ - struct sk_buff *skb; - u16 pkt_len; - const struct ieee80211_mgmt *mgmt; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - - if (!buf || !len) { - wiphy_err(wiphy, "invalid buffer and length\n"); - return -EFAULT; - } - - mgmt = (const struct ieee80211_mgmt *)buf; - if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA && - ieee80211_is_probe_resp(mgmt->frame_control)) { - /* Since we support offload probe resp, we need to skip probe - * resp in AP or GO mode */ - wiphy_dbg(wiphy, - "info: skip to send probe resp in AP or GO mode\n"); - return 0; - } - - pkt_len = len + ETH_ALEN; - skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + - pkt_len + sizeof(pkt_len)); - - if (!skb) { - wiphy_err(wiphy, "allocate skb failed for management frame\n"); - return -ENOMEM; - } - - mwifiex_form_mgmt_frame(skb, buf, len); - mwifiex_queue_tx_pkt(priv, skb); - - *cookie = random32() | 1; - cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_ATOMIC); - - wiphy_dbg(wiphy, "info: management frame transmitted\n"); - return 0; -} - -/* - * CFG802.11 operation handler to register a mgmt frame. - */ -static void -mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy, - struct wireless_dev *wdev, - u16 frame_type, bool reg) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - - if (reg) - priv->mgmt_frame_mask |= BIT(frame_type >> 4); - else - priv->mgmt_frame_mask &= ~BIT(frame_type >> 4); - - mwifiex_send_cmd_async(priv, HostCmd_CMD_MGMT_FRAME_REG, - HostCmd_ACT_GEN_SET, 0, &priv->mgmt_frame_mask); - - wiphy_dbg(wiphy, "info: mgmt frame registered\n"); -} - -/* - * CFG802.11 operation handler to remain on channel. - */ -static int -mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type, - unsigned int duration, u64 *cookie) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - int ret; - - if (!chan || !cookie) { - wiphy_err(wiphy, "Invalid parameter for ROC\n"); - return -EINVAL; - } - - if (priv->roc_cfg.cookie) { - wiphy_dbg(wiphy, "info: ongoing ROC, cookie = 0x%llu\n", - priv->roc_cfg.cookie); - return -EBUSY; - } - - ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan, - &channel_type, duration); - - if (!ret) { - *cookie = random32() | 1; - priv->roc_cfg.cookie = *cookie; - priv->roc_cfg.chan = *chan; - priv->roc_cfg.chan_type = channel_type; - - cfg80211_ready_on_channel(wdev, *cookie, chan, channel_type, - duration, GFP_ATOMIC); - - wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie); - } - - return ret; -} - -/* - * CFG802.11 operation handler to cancel remain on channel. - */ -static int -mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, u64 cookie) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - int ret; - - if (cookie != priv->roc_cfg.cookie) - return -ENOENT; - - ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE, - &priv->roc_cfg.chan, - &priv->roc_cfg.chan_type, 0); - - if (!ret) { - cfg80211_remain_on_channel_expired(wdev, cookie, - &priv->roc_cfg.chan, - priv->roc_cfg.chan_type, - GFP_ATOMIC); - - memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg)); - - wiphy_dbg(wiphy, "info: cancel ROC, cookie = 0x%llx\n", cookie); - } - - return ret; -} - /* * CFG802.11 operation handler to set Tx power. */ @@ -674,76 +493,6 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return 0; } -static int -mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv) -{ - u16 mode = P2P_MODE_DISABLE; - - if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) - mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA); - - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) - return -1; - - return 0; -} - -/* - * This function initializes the functionalities for P2P client. - * The P2P client initialization sequence is: - * disable -> device -> client - */ -static int -mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv) -{ - u16 mode; - - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -1; - - mode = P2P_MODE_DEVICE; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) - return -1; - - mode = P2P_MODE_CLIENT; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) - return -1; - - return 0; -} - -/* - * This function initializes the functionalities for P2P GO. - * The P2P GO initialization sequence is: - * disable -> device -> GO - */ -static int -mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) -{ - u16 mode; - - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -1; - - mode = P2P_MODE_DEVICE; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) - return -1; - - mode = P2P_MODE_GO; - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode)) - return -1; - - if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) - mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_UAP); - - return 0; -} - /* * CFG802.11 operation handler to change interface type. */ @@ -776,16 +525,6 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, switch (type) { case NL80211_IFTYPE_ADHOC: break; - case NL80211_IFTYPE_P2P_CLIENT: - if (mwifiex_cfg80211_init_p2p_client(priv)) - return -EFAULT; - dev->ieee80211_ptr->iftype = type; - return 0; - case NL80211_IFTYPE_P2P_GO: - if (mwifiex_cfg80211_init_p2p_go(priv)) - return -EFAULT; - dev->ieee80211_ptr->iftype = type; - return 0; case NL80211_IFTYPE_UNSPECIFIED: wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); case NL80211_IFTYPE_STATION: /* This shouldn't happen */ @@ -811,18 +550,6 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, return -EOPNOTSUPP; } break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - switch (type) { - case NL80211_IFTYPE_STATION: - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -EFAULT; - dev->ieee80211_ptr->iftype = type; - return 0; - default: - return -EOPNOTSUPP; - } - break; default: wiphy_err(wiphy, "%s: unknown iftype: %d\n", dev->name, dev->ieee80211_ptr->iftype); @@ -961,6 +688,7 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, } /* Supported rates to be advertised to the cfg80211 */ + static struct ieee80211_rate mwifiex_rates[] = { {.bitrate = 10, .hw_value = 2, }, {.bitrate = 20, .hw_value = 4, }, @@ -977,6 +705,7 @@ static struct ieee80211_rate mwifiex_rates[] = { }; /* Channel definitions to be advertised to cfg80211 */ + static struct ieee80211_channel mwifiex_channels_2ghz[] = { {.center_freq = 2412, .hw_value = 1, }, {.center_freq = 2417, .hw_value = 2, }, @@ -1044,6 +773,7 @@ static struct ieee80211_supported_band mwifiex_band_5ghz = { /* Supported crypto cipher suits to be advertised to cfg80211 */ + static const u32 mwifiex_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, @@ -1052,35 +782,6 @@ static const u32 mwifiex_cipher_suites[] = { WLAN_CIPHER_SUITE_AES_CMAC, }; -/* Supported mgmt frame types to be advertised to cfg80211 */ -static const struct ieee80211_txrx_stypes -mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = { - [NL80211_IFTYPE_STATION] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), - }, - [NL80211_IFTYPE_AP] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), - }, - [NL80211_IFTYPE_P2P_CLIENT] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), - }, - [NL80211_IFTYPE_P2P_GO] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), - }, -}; - /* * CFG802.11 operation handler for setting bit rates. * @@ -1173,7 +874,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) { + if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__); return -EINVAL; } @@ -1261,7 +962,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); u8 config_bands = 0; - if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) + if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) return -1; if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) return -1; @@ -1331,12 +1032,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, mwifiex_set_ht_params(priv, bss_cfg, params); - if (params->inactivity_timeout > 0) { - /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ - bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout; - bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; - } - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, HostCmd_ACT_GEN_SET, 0, NULL)) { wiphy_err(wiphy, "Failed to stop the BSS\n"); @@ -1802,18 +1497,11 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, { struct net_device *dev = request->wdev->netdev; struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - int i, offset; + int i; struct ieee80211_channel *chan; - struct ieee_types_header *ie; wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); - if (atomic_read(&priv->wmm.tx_pkts_queued) >= - MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) { - dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n"); - return -EBUSY; - } - priv->scan_request = request; priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), @@ -1827,17 +1515,13 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, priv->user_scan_cfg->ssid_list = request->ssids; if (request->ie && request->ie_len) { - offset = 0; for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) { if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR) continue; priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN; - ie = (struct ieee_types_header *)(request->ie + offset); - memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len); - offset += sizeof(*ie) + ie->len; - - if (offset >= request->ie_len) - break; + memcpy(&priv->vs_ie[i].ie, request->ie, + request->ie_len); + break; } } @@ -1946,7 +1630,7 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, * create a new virtual interface with the given name */ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, - const char *name, + char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params) @@ -2015,41 +1699,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->bss_num = 0; priv->bss_mode = type; - break; - case NL80211_IFTYPE_P2P_CLIENT: - priv = adapter->priv[MWIFIEX_BSS_TYPE_P2P]; - - if (priv->bss_mode) { - wiphy_err(wiphy, "Can't create multiple P2P ifaces"); - return ERR_PTR(-EINVAL); - } - - wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) - return ERR_PTR(-ENOMEM); - - priv->wdev = wdev; - wdev->wiphy = wiphy; - - /* At start-up, wpa_supplicant tries to change the interface - * to NL80211_IFTYPE_STATION if it is not managed mode. - * So, we initialize it to STA mode. - */ - wdev->iftype = NL80211_IFTYPE_STATION; - priv->bss_mode = NL80211_IFTYPE_STATION; - - /* Setting bss_type to P2P tells firmware that this interface - * is receiving P2P peers found during find phase and doing - * action frame handshake. - */ - priv->bss_type = MWIFIEX_BSS_TYPE_P2P; - - priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; - priv->bss_priority = MWIFIEX_BSS_ROLE_STA; - priv->bss_role = MWIFIEX_BSS_ROLE_STA; - priv->bss_started = 0; - priv->bss_num = 0; - break; default: wiphy_err(wiphy, "type not supported\n"); @@ -2158,10 +1807,6 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .leave_ibss = mwifiex_cfg80211_leave_ibss, .add_key = mwifiex_cfg80211_add_key, .del_key = mwifiex_cfg80211_del_key, - .mgmt_tx = mwifiex_cfg80211_mgmt_tx, - .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register, - .remain_on_channel = mwifiex_cfg80211_remain_on_channel, - .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel, .set_default_key = mwifiex_cfg80211_set_default_key, .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, .set_tx_power = mwifiex_cfg80211_set_tx_power, @@ -2198,12 +1843,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) } wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; - wiphy->mgmt_stypes = mwifiex_mgmt_stypes; - wiphy->max_remain_on_channel_duration = 5000; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_AP); wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; @@ -2223,20 +1864,17 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | - WIPHY_FLAG_CUSTOM_REGULATORY | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + WIPHY_FLAG_CUSTOM_REGULATORY; wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2; wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1; wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; - wiphy->features = NL80211_FEATURE_HT_IBSS | - NL80211_FEATURE_INACTIVITY_TIMER; + wiphy->features = NL80211_FEATURE_HT_IBSS; /* Reserve space for mwifiex specific private data for BSS */ wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); diff --git a/trunk/drivers/net/wireless/mwifiex/cmdevt.c b/trunk/drivers/net/wireless/mwifiex/cmdevt.c index 8d465107f52b..225c1a4feeba 100644 --- a/trunk/drivers/net/wireless/mwifiex/cmdevt.c +++ b/trunk/drivers/net/wireless/mwifiex/cmdevt.c @@ -1088,8 +1088,6 @@ mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated) if (activated) { if (priv->adapter->is_hs_configured) { priv->adapter->hs_activated = true; - mwifiex_update_rxreor_flags(priv->adapter, - RXREOR_FORCE_NO_DROP); dev_dbg(priv->adapter->dev, "event: hs_activated\n"); priv->adapter->hs_activate_wait_q_woken = true; wake_up_interruptible( diff --git a/trunk/drivers/net/wireless/mwifiex/decl.h b/trunk/drivers/net/wireless/mwifiex/decl.h index e9357d87d327..400d360ac91f 100644 --- a/trunk/drivers/net/wireless/mwifiex/decl.h +++ b/trunk/drivers/net/wireless/mwifiex/decl.h @@ -28,14 +28,11 @@ #include -#define MWIFIEX_MAX_BSS_NUM (3) +#define MWIFIEX_MAX_BSS_NUM (2) #define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd) * + 4 byte alignment */ -#define MWIFIEX_MGMT_FRAME_HEADER_SIZE 8 /* sizeof(pkt_type) - * + sizeof(tx_control) - */ #define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 #define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 @@ -70,7 +67,6 @@ enum mwifiex_bss_type { MWIFIEX_BSS_TYPE_STA = 0, MWIFIEX_BSS_TYPE_UAP = 1, - MWIFIEX_BSS_TYPE_P2P = 2, MWIFIEX_BSS_TYPE_ANY = 0xff, }; diff --git a/trunk/drivers/net/wireless/mwifiex/fw.h b/trunk/drivers/net/wireless/mwifiex/fw.h index dda588b35570..b8ce78e2ba47 100644 --- a/trunk/drivers/net/wireless/mwifiex/fw.h +++ b/trunk/drivers/net/wireless/mwifiex/fw.h @@ -94,7 +94,6 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { }; #define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) -#define CAL_RSSI(SNR, NF) ((s16)((s16)(SNR)+(s16)(NF))) #define UAP_BSS_PARAMS_I 0 #define UAP_CUSTOM_IE_I 1 @@ -128,7 +127,6 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) #define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48) #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) -#define TLV_TYPE_UAP_AO_TIMER (PROPRIETARY_TLV_BASE_ID + 57) #define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 59) #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) @@ -143,7 +141,6 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) #define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) -#define TLV_TYPE_UAP_PS_AO_TIMER (PROPRIETARY_TLV_BASE_ID + 123) #define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 145) #define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) @@ -263,12 +260,9 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_TX_RATE_CFG 0x00d6 #define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4 #define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 -#define HostCmd_CMD_P2P_MODE_CFG 0x00eb #define HostCmd_CMD_CAU_REG_ACCESS 0x00ed #define HostCmd_CMD_SET_BSS_MODE 0x00f7 #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa -#define HostCmd_CMD_MGMT_FRAME_REG 0x010c -#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d #define PROTOCOL_NO_SECURITY 0x01 #define PROTOCOL_STATIC_WEP 0x02 @@ -294,17 +288,9 @@ enum ENH_PS_MODES { DIS_AUTO_PS = 0xfe, }; -enum P2P_MODES { - P2P_MODE_DISABLE = 0, - P2P_MODE_DEVICE = 1, - P2P_MODE_GO = 2, - P2P_MODE_CLIENT = 3, -}; - #define HostCmd_RET_BIT 0x8000 #define HostCmd_ACT_GEN_GET 0x0000 #define HostCmd_ACT_GEN_SET 0x0001 -#define HostCmd_ACT_GEN_REMOVE 0x0004 #define HostCmd_ACT_BITWISE_SET 0x0002 #define HostCmd_ACT_BITWISE_CLR 0x0003 #define HostCmd_RESULT_OK 0x0000 @@ -402,7 +388,6 @@ enum P2P_MODES { #define EVENT_BW_CHANGE 0x00000048 #define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c #define EVENT_HOSTWAKE_STAIE 0x0000004d -#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f #define EVENT_ID_MASK 0xffff #define BSS_NUM_MASK 0xf @@ -1346,35 +1331,11 @@ struct host_cmd_tlv_channel_band { u8 channel; } __packed; -struct host_cmd_tlv_ageout_timer { - struct host_cmd_tlv tlv; - __le32 sta_ao_timer; -} __packed; - struct host_cmd_ds_version_ext { u8 version_str_sel; char version_str[128]; } __packed; -struct host_cmd_ds_mgmt_frame_reg { - __le16 action; - __le32 mask; -} __packed; - -struct host_cmd_ds_p2p_mode_cfg { - __le16 action; - __le16 mode; -} __packed; - -struct host_cmd_ds_remain_on_chan { - __le16 action; - u8 status; - u8 reserved; - u8 band_cfg; - u8 channel; - __le32 duration; -} __packed; - struct host_cmd_ds_802_11_ibss_status { __le16 action; __le16 enable; @@ -1386,7 +1347,6 @@ struct host_cmd_ds_802_11_ibss_status { #define CONNECTION_TYPE_INFRA 0 #define CONNECTION_TYPE_ADHOC 1 -#define CONNECTION_TYPE_AP 2 struct host_cmd_ds_set_bss_mode { u8 con_type; @@ -1484,9 +1444,6 @@ struct host_cmd_ds_command { struct host_cmd_ds_wmm_get_status get_wmm_status; struct host_cmd_ds_802_11_key_material key_material; struct host_cmd_ds_version_ext verext; - struct host_cmd_ds_mgmt_frame_reg reg_mask; - struct host_cmd_ds_remain_on_chan roc_cfg; - struct host_cmd_ds_p2p_mode_cfg mode_cfg; struct host_cmd_ds_802_11_ibss_status ibss_coalescing; struct host_cmd_ds_mac_reg_access mac_reg; struct host_cmd_ds_bbp_reg_access bbp_reg; diff --git a/trunk/drivers/net/wireless/mwifiex/ie.c b/trunk/drivers/net/wireless/mwifiex/ie.c index e38342f86c51..1d8dd003e396 100644 --- a/trunk/drivers/net/wireless/mwifiex/ie.c +++ b/trunk/drivers/net/wireless/mwifiex/ie.c @@ -114,6 +114,9 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv, cpu_to_le16(mask); ie->ie_index = cpu_to_le16(index); + ie->ie_length = priv->mgmt_ie[index].ie_length; + memcpy(&ie->ie_buffer, &priv->mgmt_ie[index].ie_buffer, + le16_to_cpu(priv->mgmt_ie[index].ie_length)); } else { if (mask != MWIFIEX_DELETE_MASK) return -1; @@ -157,7 +160,7 @@ mwifiex_update_uap_custom_ie(struct mwifiex_private *priv, u16 len; int ret; - ap_custom_ie = kzalloc(sizeof(*ap_custom_ie), GFP_KERNEL); + ap_custom_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); if (!ap_custom_ie) return -ENOMEM; @@ -211,35 +214,30 @@ mwifiex_update_uap_custom_ie(struct mwifiex_private *priv, return ret; } -/* This function checks if the vendor specified IE is present in passed buffer - * and copies it to mwifiex_ie structure. +/* This function checks if WPS IE is present in passed buffer and copies it to + * mwifiex_ie structure. * Function takes pointer to struct mwifiex_ie pointer as argument. - * If the vendor specified IE is present then memory is allocated for - * mwifiex_ie pointer and filled in with IE. Caller should take care of freeing - * this memory. + * If WPS IE is present memory is allocated for mwifiex_ie pointer and filled + * in with WPS IE. Caller should take care of freeing this memory. */ -static int mwifiex_update_vs_ie(const u8 *ies, int ies_len, - struct mwifiex_ie **ie_ptr, u16 mask, - unsigned int oui, u8 oui_type) +static int mwifiex_update_wps_ie(const u8 *ies, int ies_len, + struct mwifiex_ie **ie_ptr, u16 mask) { - struct ieee_types_header *vs_ie; - struct mwifiex_ie *ie = *ie_ptr; + struct ieee_types_header *wps_ie; + struct mwifiex_ie *ie = NULL; const u8 *vendor_ie; - vendor_ie = cfg80211_find_vendor_ie(oui, oui_type, ies, ies_len); + vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS, + ies, ies_len); if (vendor_ie) { - if (!*ie_ptr) { - *ie_ptr = kzalloc(sizeof(struct mwifiex_ie), - GFP_KERNEL); - if (!*ie_ptr) - return -ENOMEM; - ie = *ie_ptr; - } + ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); + if (!ie) + return -ENOMEM; - vs_ie = (struct ieee_types_header *)vendor_ie; - memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length), - vs_ie, vs_ie->len + 2); - le16_add_cpu(&ie->ie_length, vs_ie->len + 2); + wps_ie = (struct ieee_types_header *)vendor_ie; + memcpy(ie->ie_buffer, wps_ie, wps_ie->len + 2); + ie->ie_length = cpu_to_le16(wps_ie->len + 2); ie->mgmt_subtype_mask = cpu_to_le16(mask); ie->ie_index = cpu_to_le16(MWIFIEX_AUTO_IDX_MASK); } @@ -259,40 +257,20 @@ static int mwifiex_set_mgmt_beacon_data_ies(struct mwifiex_private *priv, u16 ar_idx = MWIFIEX_AUTO_IDX_MASK; int ret = 0; - if (data->beacon_ies && data->beacon_ies_len) { - mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len, - &beacon_ie, MGMT_MASK_BEACON, - WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS); - mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len, - &beacon_ie, MGMT_MASK_BEACON, - WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P); - } + if (data->beacon_ies && data->beacon_ies_len) + mwifiex_update_wps_ie(data->beacon_ies, data->beacon_ies_len, + &beacon_ie, MGMT_MASK_BEACON); - if (data->proberesp_ies && data->proberesp_ies_len) { - mwifiex_update_vs_ie(data->proberesp_ies, - data->proberesp_ies_len, &pr_ie, - MGMT_MASK_PROBE_RESP, WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS); - mwifiex_update_vs_ie(data->proberesp_ies, - data->proberesp_ies_len, &pr_ie, - MGMT_MASK_PROBE_RESP, - WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P); - } + if (data->proberesp_ies && data->proberesp_ies_len) + mwifiex_update_wps_ie(data->proberesp_ies, + data->proberesp_ies_len, &pr_ie, + MGMT_MASK_PROBE_RESP); - if (data->assocresp_ies && data->assocresp_ies_len) { - mwifiex_update_vs_ie(data->assocresp_ies, - data->assocresp_ies_len, &ar_ie, - MGMT_MASK_ASSOC_RESP | - MGMT_MASK_REASSOC_RESP, - WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS); - mwifiex_update_vs_ie(data->assocresp_ies, - data->assocresp_ies_len, &ar_ie, - MGMT_MASK_ASSOC_RESP | - MGMT_MASK_REASSOC_RESP, WLAN_OUI_WFA, - WLAN_OUI_TYPE_WFA_P2P); - } + if (data->assocresp_ies && data->assocresp_ies_len) + mwifiex_update_wps_ie(data->assocresp_ies, + data->assocresp_ies_len, &ar_ie, + MGMT_MASK_ASSOC_RESP | + MGMT_MASK_REASSOC_RESP); if (beacon_ie || pr_ie || ar_ie) { ret = mwifiex_update_uap_custom_ie(priv, beacon_ie, diff --git a/trunk/drivers/net/wireless/mwifiex/init.c b/trunk/drivers/net/wireless/mwifiex/init.c index b5d37a8caa09..9c1549ee4c09 100644 --- a/trunk/drivers/net/wireless/mwifiex/init.c +++ b/trunk/drivers/net/wireless/mwifiex/init.c @@ -118,7 +118,6 @@ static void scan_delay_timer_fn(unsigned long data) mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); - queue_work(adapter->workqueue, &adapter->main_work); goto done; } } else { @@ -144,7 +143,7 @@ static void scan_delay_timer_fn(unsigned long data) * Additionally, it also initializes all the locks and sets up all the * lists. */ -int mwifiex_init_priv(struct mwifiex_private *priv) +static int mwifiex_init_priv(struct mwifiex_private *priv) { u32 i; @@ -214,7 +213,6 @@ int mwifiex_init_priv(struct mwifiex_private *priv) priv->wps_ie = NULL; priv->wps_ie_len = 0; priv->ap_11n_enabled = 0; - memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg)); priv->scan_block = false; @@ -648,17 +646,6 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) } } -/* - * This function frees the private structure, including cleans - * up the TX and RX queues and frees the BSS priority tables. - */ -void mwifiex_free_priv(struct mwifiex_private *priv) -{ - mwifiex_clean_txrx(priv); - mwifiex_delete_bss_prio_tbl(priv); - mwifiex_free_curr_bcn(priv); -} - /* * This function is used to shutdown the driver. * diff --git a/trunk/drivers/net/wireless/mwifiex/ioctl.h b/trunk/drivers/net/wireless/mwifiex/ioctl.h index 4e31c6013ebe..8688535e95eb 100644 --- a/trunk/drivers/net/wireless/mwifiex/ioctl.h +++ b/trunk/drivers/net/wireless/mwifiex/ioctl.h @@ -105,8 +105,6 @@ struct mwifiex_uap_bss_param { struct wep_key wep_cfg[NUM_WEP_KEYS]; struct ieee80211_ht_cap ht_cap; u8 rates[MWIFIEX_SUPPORTED_RATES]; - u32 sta_ao_timer; - u32 ps_sta_ao_timer; }; enum { diff --git a/trunk/drivers/net/wireless/mwifiex/main.c b/trunk/drivers/net/wireless/mwifiex/main.c index eb22dd248d54..bfd6667be01e 100644 --- a/trunk/drivers/net/wireless/mwifiex/main.c +++ b/trunk/drivers/net/wireless/mwifiex/main.c @@ -369,13 +369,6 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) dev_err(adapter->dev, "cannot create default AP interface\n"); goto err_add_intf; } - - /* Create P2P interface by default */ - if (!mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", - NL80211_IFTYPE_P2P_CLIENT, NULL, NULL)) { - dev_err(adapter->dev, "cannot create default P2P interface\n"); - goto err_add_intf; - } rtnl_unlock(); mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); @@ -475,27 +468,6 @@ mwifiex_close(struct net_device *dev) return 0; } -/* - * Add buffer into wmm tx queue and queue work to transmit it. - */ -int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) -{ - mwifiex_wmm_add_buf_txqueue(priv, skb); - atomic_inc(&priv->adapter->tx_pending); - - if (priv->adapter->scan_delay_cnt) - atomic_set(&priv->adapter->is_tx_received, true); - - if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { - mwifiex_set_trans_start(priv->netdev); - mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); - } - - queue_work(priv->adapter->workqueue, &priv->adapter->main_work); - - return 0; -} - /* * CFG802.11 network device handler for data transmission. */ @@ -544,7 +516,18 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_info->bss_type = priv->bss_type; mwifiex_fill_buffer(skb); - mwifiex_queue_tx_pkt(priv, skb); + mwifiex_wmm_add_buf_txqueue(priv, skb); + atomic_inc(&priv->adapter->tx_pending); + + if (priv->adapter->scan_delay_cnt) + atomic_set(&priv->adapter->is_tx_received, true); + + if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { + mwifiex_set_trans_start(dev); + mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); + } + + queue_work(priv->adapter->workqueue, &priv->adapter->main_work); return 0; } diff --git a/trunk/drivers/net/wireless/mwifiex/main.h b/trunk/drivers/net/wireless/mwifiex/main.h index bfb3fa69805c..12ceea47b4b4 100644 --- a/trunk/drivers/net/wireless/mwifiex/main.h +++ b/trunk/drivers/net/wireless/mwifiex/main.h @@ -91,15 +91,11 @@ enum { #define MWIFIEX_MAX_EMPTY_TX_Q_CNT 10 #define MWIFIEX_SCAN_DELAY_MSEC 20 -#define MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN 2 - #define RSN_GTK_OUI_OFFSET 2 #define MWIFIEX_OUI_NOT_PRESENT 0 #define MWIFIEX_OUI_PRESENT 1 -#define PKT_TYPE_MGMT 0xE5 - /* * Do not check for data_received for USB, as data_received * is handled in mwifiex_usb_recv for USB @@ -370,12 +366,6 @@ struct wps { u8 session_enable; }; -struct mwifiex_roc_cfg { - u64 cookie; - struct ieee80211_channel chan; - enum nl80211_channel_type chan_type; -}; - struct mwifiex_adapter; struct mwifiex_private; @@ -502,8 +492,6 @@ struct mwifiex_private { u16 rsn_idx; struct timer_list scan_delay_timer; u8 ap_11n_enabled; - u32 mgmt_frame_mask; - struct mwifiex_roc_cfg roc_cfg; }; enum mwifiex_ba_status { @@ -535,7 +523,6 @@ struct mwifiex_rx_reorder_tbl { int win_size; void **rx_reorder_ptr; struct reorder_tmr_cnxt timer_context; - u8 flags; }; struct mwifiex_bss_prio_node { @@ -737,9 +724,6 @@ void mwifiex_stop_net_dev_queue(struct net_device *netdev, void mwifiex_wake_up_net_dev_queue(struct net_device *netdev, struct mwifiex_adapter *adapter); -int mwifiex_init_priv(struct mwifiex_private *priv); -void mwifiex_free_priv(struct mwifiex_private *priv); - int mwifiex_init_fw(struct mwifiex_adapter *adapter); int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); @@ -752,9 +736,6 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); -int mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb); - int mwifiex_process_event(struct mwifiex_adapter *adapter); int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, @@ -977,14 +958,6 @@ mwifiex_netdev_get_priv(struct net_device *dev) return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev)); } -/* - * This function checks if a skb holds a management frame. - */ -static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb) -{ - return (*(u32 *)skb->data == PKT_TYPE_MGMT); -} - int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, u32 func_init_shutdown); int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8); @@ -1017,13 +990,6 @@ int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); int mwifiex_get_ver_ext(struct mwifiex_private *priv); -int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, - struct ieee80211_channel *chan, - enum nl80211_channel_type *channel_type, - unsigned int duration); - -int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role); - int mwifiex_get_stats_info(struct mwifiex_private *priv, struct mwifiex_ds_get_stats *log); @@ -1054,8 +1020,6 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, int mwifiex_main_process(struct mwifiex_adapter *); -int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb); - int mwifiex_get_bss_info(struct mwifiex_private *, struct mwifiex_bss_info *); int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, @@ -1066,10 +1030,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, int mwifiex_check_network_compatibility(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc); -u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type); - struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, - const char *name, + char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params); diff --git a/trunk/drivers/net/wireless/mwifiex/scan.c b/trunk/drivers/net/wireless/mwifiex/scan.c index e36a75988f87..9e077e5fc64a 100644 --- a/trunk/drivers/net/wireless/mwifiex/scan.c +++ b/trunk/drivers/net/wireless/mwifiex/scan.c @@ -614,8 +614,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, /* Increment the TLV header length by the size appended */ - le16_add_cpu(&chan_tlv_out->header.len, - sizeof(chan_tlv_out->chan_scan_param)); + chan_tlv_out->header.len = + cpu_to_le16(le16_to_cpu(chan_tlv_out->header.len) + + (sizeof(chan_tlv_out->chan_scan_param))); /* * The tlv buffer length is set to the number of bytes diff --git a/trunk/drivers/net/wireless/mwifiex/sta_cmd.c b/trunk/drivers/net/wireless/mwifiex/sta_cmd.c index 5d87195390f8..3a4161cfeed7 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1167,31 +1167,6 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, S_DS_GEN); ret = 0; break; - case HostCmd_CMD_MGMT_FRAME_REG: - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->params.reg_mask.action = cpu_to_le16(cmd_action); - cmd_ptr->params.reg_mask.mask = cpu_to_le32(*(u32 *)data_buf); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) + - S_DS_GEN); - ret = 0; - break; - case HostCmd_CMD_REMAIN_ON_CHAN: - cmd_ptr->command = cpu_to_le16(cmd_no); - memcpy(&cmd_ptr->params, data_buf, - sizeof(struct host_cmd_ds_remain_on_chan)); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + - S_DS_GEN); - break; - case HostCmd_CMD_P2P_MODE_CFG: - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action); - cmd_ptr->params.mode_cfg.mode = cpu_to_le16(*(u16 *)data_buf); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg) + - S_DS_GEN); - break; case HostCmd_CMD_FUNC_INIT: if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; @@ -1261,8 +1236,6 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, else if (priv->bss_mode == NL80211_IFTYPE_STATION) cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_INFRA; - else if (priv->bss_mode == NL80211_IFTYPE_AP) - cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_AP; cmd_ptr->size = cpu_to_le16(sizeof(struct host_cmd_ds_set_bss_mode) + S_DS_GEN); ret = 0; @@ -1312,35 +1285,35 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) if (first_sta) { if (priv->adapter->iface_type == MWIFIEX_PCIE) { - ret = mwifiex_send_cmd_sync(priv, + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_PCIE_DESC_DETAILS, HostCmd_ACT_GEN_SET, 0, NULL); if (ret) return -1; } - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_FUNC_INIT, - HostCmd_ACT_GEN_SET, 0, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT, + HostCmd_ACT_GEN_SET, 0, NULL); if (ret) return -1; /* Read MAC address from HW */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_GET_HW_SPEC, - HostCmd_ACT_GEN_GET, 0, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_GET_HW_SPEC, + HostCmd_ACT_GEN_GET, 0, NULL); if (ret) return -1; /* Reconfigure tx buf size */ - ret = mwifiex_send_cmd_sync(priv, - HostCmd_CMD_RECONFIGURE_TX_BUFF, - HostCmd_ACT_GEN_SET, 0, - &priv->adapter->tx_buf_size); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_RECONFIGURE_TX_BUFF, + HostCmd_ACT_GEN_SET, 0, + &priv->adapter->tx_buf_size); if (ret) return -1; if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { /* Enable IEEE PS by default */ priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - ret = mwifiex_send_cmd_sync( + ret = mwifiex_send_cmd_async( priv, HostCmd_CMD_802_11_PS_MODE_ENH, EN_AUTO_PS, BITMAP_STA_PS, NULL); if (ret) @@ -1349,21 +1322,21 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) } /* get tx rate */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, - HostCmd_ACT_GEN_GET, 0, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TX_RATE_CFG, + HostCmd_ACT_GEN_GET, 0, NULL); if (ret) return -1; priv->data_rate = 0; /* get tx power */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_TX_PWR, - HostCmd_ACT_GEN_GET, 0, NULL); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_RF_TX_PWR, + HostCmd_ACT_GEN_GET, 0, NULL); if (ret) return -1; if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) { /* set ibss coalescing_status */ - ret = mwifiex_send_cmd_sync( + ret = mwifiex_send_cmd_async( priv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, HostCmd_ACT_GEN_SET, 0, &enable); if (ret) @@ -1373,16 +1346,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); amsdu_aggr_ctrl.enable = true; /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, - HostCmd_ACT_GEN_SET, 0, - &amsdu_aggr_ctrl); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, + HostCmd_ACT_GEN_SET, 0, + &amsdu_aggr_ctrl); if (ret) return -1; /* MAC Control must be the last command in init_fw */ /* set MAC Control */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, + &priv->curr_pkt_filter); if (ret) return -1; @@ -1391,10 +1364,10 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) /* Enable auto deep sleep */ auto_ds.auto_ds = DEEP_SLEEP_ON; auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; - ret = mwifiex_send_cmd_sync(priv, - HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_AUTO_DS, - &auto_ds); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_PS_MODE_ENH, + EN_AUTO_PS, BITMAP_AUTO_DS, + &auto_ds); if (ret) return -1; } @@ -1402,24 +1375,23 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { /* Send cmd to FW to enable/disable 11D function */ state_11d = ENABLE_11D; - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, DOT11D_I, - &state_11d); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, DOT11D_I, + &state_11d); if (ret) dev_err(priv->adapter->dev, "11D: failed to enable 11D\n"); } - /* set last_init_cmd before sending the command */ - priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; - /* Send cmd to FW to configure 11n specific configuration * (Short GI, Channel BW, Green field support etc.) for transmit */ tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG; - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_11N_CFG, - HostCmd_ACT_GEN_SET, 0, &tx_cfg); + ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_CFG, + HostCmd_ACT_GEN_SET, 0, &tx_cfg); + /* set last_init_cmd */ + priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; ret = -EINPROGRESS; return ret; diff --git a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c b/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c index e380171c4c5d..31f80e10e29e 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -653,38 +653,6 @@ static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, return 0; } -/* - * This function handles the command response of remain on channel. - */ -static int -mwifiex_ret_remain_on_chan(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - struct host_cmd_ds_remain_on_chan *roc_cfg) -{ - struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg; - - if (roc_cfg) - memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg)); - - return 0; -} - -/* - * This function handles the command response of P2P mode cfg. - */ -static int -mwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg; - - if (data_buf) - *((u16 *)data_buf) = le16_to_cpu(mode_cfg->mode); - - return 0; -} - /* * This function handles the command response of register access. * @@ -907,13 +875,6 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_VERSION_EXT: ret = mwifiex_ret_ver_ext(priv, resp, data_buf); break; - case HostCmd_CMD_REMAIN_ON_CHAN: - ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf); - break; - case HostCmd_CMD_P2P_MODE_CFG: - ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf); - break; - case HostCmd_CMD_MGMT_FRAME_REG: case HostCmd_CMD_FUNC_INIT: case HostCmd_CMD_FUNC_SHUTDOWN: break; diff --git a/trunk/drivers/net/wireless/mwifiex/sta_event.c b/trunk/drivers/net/wireless/mwifiex/sta_event.c index aafde30e714a..dff51d55271c 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_event.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_event.c @@ -410,18 +410,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); break; - case EVENT_REMAIN_ON_CHAN_EXPIRED: - dev_dbg(adapter->dev, "event: Remain on channel expired\n"); - cfg80211_remain_on_channel_expired(priv->wdev, - priv->roc_cfg.cookie, - &priv->roc_cfg.chan, - priv->roc_cfg.chan_type, - GFP_ATOMIC); - - memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg)); - - break; - default: dev_dbg(adapter->dev, "event: unknown event id: %#x\n", eventcause); diff --git a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c index 0c9f70b2cbe6..d7ad2d4a069f 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -26,9 +26,6 @@ #include "11n.h" #include "cfg80211.h" -static int disconnect_on_suspend = 1; -module_param(disconnect_on_suspend, int, 0644); - /* * Copies the multicast address list from device to driver. * @@ -451,16 +448,6 @@ EXPORT_SYMBOL_GPL(mwifiex_cancel_hs); int mwifiex_enable_hs(struct mwifiex_adapter *adapter) { struct mwifiex_ds_hs_cfg hscfg; - struct mwifiex_private *priv; - int i; - - if (disconnect_on_suspend) { - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (priv) - mwifiex_deauthenticate(priv, NULL); - } - } if (adapter->hs_activated) { dev_dbg(adapter->dev, "cmd: HS Already actived\n"); @@ -1043,65 +1030,6 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv) return 0; } -int -mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, - struct ieee80211_channel *chan, - enum nl80211_channel_type *ct, - unsigned int duration) -{ - struct host_cmd_ds_remain_on_chan roc_cfg; - u8 sc; - - memset(&roc_cfg, 0, sizeof(roc_cfg)); - roc_cfg.action = cpu_to_le16(action); - if (action == HostCmd_ACT_GEN_SET) { - roc_cfg.band_cfg = chan->band; - sc = mwifiex_chan_type_to_sec_chan_offset(*ct); - roc_cfg.band_cfg |= (sc << 2); - - roc_cfg.channel = - ieee80211_frequency_to_channel(chan->center_freq); - roc_cfg.duration = cpu_to_le32(duration); - } - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_REMAIN_ON_CHAN, - action, 0, &roc_cfg)) { - dev_err(priv->adapter->dev, "failed to remain on channel\n"); - return -1; - } - - return roc_cfg.status; -} - -int -mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role) -{ - if (GET_BSS_ROLE(priv) == bss_role) { - dev_dbg(priv->adapter->dev, - "info: already in the desired role.\n"); - return 0; - } - - mwifiex_free_priv(priv); - mwifiex_init_priv(priv); - - priv->bss_role = bss_role; - switch (bss_role) { - case MWIFIEX_BSS_ROLE_UAP: - priv->bss_mode = NL80211_IFTYPE_AP; - break; - case MWIFIEX_BSS_ROLE_STA: - case MWIFIEX_BSS_ROLE_ANY: - default: - priv->bss_mode = NL80211_IFTYPE_STATION; - break; - } - - mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, NULL); - - return mwifiex_sta_init_cmd(priv, false); -} - /* * Sends IOCTL request to get statistics information. * diff --git a/trunk/drivers/net/wireless/mwifiex/sta_rx.c b/trunk/drivers/net/wireless/mwifiex/sta_rx.c index 07d32b73783e..d91d5c08c73a 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_rx.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_rx.c @@ -174,12 +174,6 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, dev_err(adapter->dev, "Rx of A-MSDU failed"); } return 0; - } else if (rx_pkt_type == PKT_TYPE_MGMT) { - ret = mwifiex_process_mgmt_packet(adapter, skb); - if (ret) - dev_err(adapter->dev, "Rx of mgmt packet failed"); - dev_kfree_skb_any(skb); - return ret; } /* diff --git a/trunk/drivers/net/wireless/mwifiex/sta_tx.c b/trunk/drivers/net/wireless/mwifiex/sta_tx.c index 7b581af24f5f..0a046d3a0c16 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_tx.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_tx.c @@ -48,7 +48,6 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, struct txpd *local_tx_pd; struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); u8 pad; - u16 pkt_type, pkt_offset; if (!skb->len) { dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len); @@ -56,8 +55,6 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, return skb->data; } - pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; - /* If skb->data is not aligned; add padding */ pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4; @@ -96,14 +93,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, } /* Offset of actual data */ - pkt_offset = sizeof(struct txpd) + pad; - if (pkt_type == PKT_TYPE_MGMT) { - /* Set the packet type and add header for management frame */ - local_tx_pd->tx_pkt_type = cpu_to_le16(pkt_type); - pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE; - } - - local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset); + local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + pad); /* make space for INTF_HEADER_LEN */ skb_push(skb, INTF_HEADER_LEN); diff --git a/trunk/drivers/net/wireless/mwifiex/uap_cmd.c b/trunk/drivers/net/wireless/mwifiex/uap_cmd.c index d95a2d558fcf..8a627d856d18 100644 --- a/trunk/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/trunk/drivers/net/wireless/mwifiex/uap_cmd.c @@ -343,7 +343,6 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; struct host_cmd_tlv_auth_type *auth_type; struct host_cmd_tlv_rates *tlv_rates; - struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer; struct mwifiex_ie_types_htcap *htcap; struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; int i; @@ -498,27 +497,6 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) tlv += sizeof(struct mwifiex_ie_types_htcap); } - if (bss_cfg->sta_ao_timer) { - ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; - ao_timer->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER); - ao_timer->tlv.len = cpu_to_le16(sizeof(*ao_timer) - - sizeof(struct host_cmd_tlv)); - ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer); - cmd_size += sizeof(*ao_timer); - tlv += sizeof(*ao_timer); - } - - if (bss_cfg->ps_sta_ao_timer) { - ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; - ps_ao_timer->tlv.type = cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER); - ps_ao_timer->tlv.len = cpu_to_le16(sizeof(*ps_ao_timer) - - sizeof(struct host_cmd_tlv)); - ps_ao_timer->sta_ao_timer = - cpu_to_le32(bss_cfg->ps_sta_ao_timer); - cmd_size += sizeof(*ps_ao_timer); - tlv += sizeof(*ps_ao_timer); - } - *param_size = cmd_size; return 0; diff --git a/trunk/drivers/net/wireless/mwifiex/uap_txrx.c b/trunk/drivers/net/wireless/mwifiex/uap_txrx.c index 0966ac24b3b4..df17d08715fe 100644 --- a/trunk/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/trunk/drivers/net/wireless/mwifiex/uap_txrx.c @@ -217,12 +217,6 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, } return 0; - } else if (rx_pkt_type == PKT_TYPE_MGMT) { - ret = mwifiex_process_mgmt_packet(adapter, skb); - if (ret) - dev_err(adapter->dev, "Rx of mgmt packet failed"); - dev_kfree_skb_any(skb); - return ret; } memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); @@ -284,7 +278,6 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, struct uap_txpd *txpd; struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); int pad, len; - u16 pkt_type; if (!skb->len) { dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len); @@ -292,8 +285,6 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, return skb->data; } - pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; - /* If skb->data is not aligned, add padding */ pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4; @@ -321,12 +312,6 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]); /* Offset of actual data */ - if (pkt_type == PKT_TYPE_MGMT) { - /* Set the packet type and add header for management frame */ - txpd->tx_pkt_type = cpu_to_le16(pkt_type); - len += MWIFIEX_MGMT_FRAME_HEADER_SIZE; - } - txpd->tx_pkt_offset = cpu_to_le16(len); /* make space for INTF_HEADER_LEN */ diff --git a/trunk/drivers/net/wireless/mwifiex/util.c b/trunk/drivers/net/wireless/mwifiex/util.c index ae88f80cf86b..2864c74bdb6f 100644 --- a/trunk/drivers/net/wireless/mwifiex/util.c +++ b/trunk/drivers/net/wireless/mwifiex/util.c @@ -141,46 +141,6 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, return 0; } -/* - * This function processes the received management packet and send it - * to the kernel. - */ -int -mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - struct rxpd *rx_pd; - struct mwifiex_private *priv; - u16 pkt_len; - - if (!skb) - return -1; - - rx_pd = (struct rxpd *)skb->data; - priv = mwifiex_get_priv_by_id(adapter, rx_pd->bss_num, rx_pd->bss_type); - if (!priv) - return -1; - - skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset)); - skb_pull(skb, sizeof(pkt_len)); - - pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); - - /* Remove address4 */ - memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), - skb->data + sizeof(struct ieee80211_hdr), - pkt_len - sizeof(struct ieee80211_hdr)); - - pkt_len -= ETH_ALEN + sizeof(pkt_len); - rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); - - cfg80211_rx_mgmt(priv->wdev, priv->roc_cfg.chan.center_freq, - CAL_RSSI(rx_pd->snr, rx_pd->nf), - skb->data, pkt_len, GFP_ATOMIC); - - return 0; -} - /* * This function processes the received packet before sending it to the * kernel. diff --git a/trunk/drivers/net/wireless/mwifiex/wmm.c b/trunk/drivers/net/wireless/mwifiex/wmm.c index 600d8194610e..766d45294c86 100644 --- a/trunk/drivers/net/wireless/mwifiex/wmm.c +++ b/trunk/drivers/net/wireless/mwifiex/wmm.c @@ -462,7 +462,7 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) for (i = 0; i < adapter->priv_num; ++i) { priv = adapter->priv[i]; if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) - return false; + return false; } return true; @@ -648,7 +648,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, u8 ra[ETH_ALEN], tid_down; unsigned long flags; - if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) { + if (!priv->media_connected) { dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); mwifiex_write_data_complete(adapter, skb, -1); return; @@ -663,8 +663,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, /* In case of infra as we have already created the list during association we just don't have to call get_queue_raptr, we will have only 1 raptr for a tid in case of infra */ - if (!mwifiex_queuing_ra_based(priv) && - !mwifiex_is_skb_mgmt_frame(skb)) { + if (!mwifiex_queuing_ra_based(priv)) { if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list)) ra_list = list_first_entry( &priv->wmm.tid_tbl_ptr[tid_down].ra_list, @@ -673,7 +672,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, ra_list = NULL; } else { memcpy(ra, skb->data, ETH_ALEN); - if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb)) + if (ra[0] & 0x01) memset(ra, 0xff, ETH_ALEN); ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra); } diff --git a/trunk/drivers/net/wireless/p54/main.c b/trunk/drivers/net/wireless/p54/main.c index aadda99989c0..2969d5321ca6 100644 --- a/trunk/drivers/net/wireless/p54/main.c +++ b/trunk/drivers/net/wireless/p54/main.c @@ -515,17 +515,6 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, if (modparam_nohwcrypt) return -EOPNOTSUPP; - if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) { - /* - * Unfortunately most/all firmwares are trying to decrypt - * incoming management frames if a suitable key can be found. - * However, in doing so the data in these frames gets - * corrupted. So, we can't have firmware supported crypto - * offload in this case. - */ - return -EOPNOTSUPP; - } - mutex_lock(&priv->conf_mutex); if (cmd == SET_KEY) { switch (key->cipher) { @@ -749,7 +738,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_REPORTS_TX_ACK_STATUS; dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | diff --git a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c index e3a2d9070cf6..6458ab87717b 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1789,6 +1789,7 @@ static const struct data_queue_desc rt2400pci_queue_atim = { static const struct rt2x00_ops rt2400pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c index 479d756e275b..68bca1456cda 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c @@ -2081,6 +2081,7 @@ static const struct data_queue_desc rt2500pci_queue_atim = { static const struct rt2x00_ops rt2500pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c index a12e84f892be..f95b5516c50a 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1896,6 +1896,7 @@ static const struct data_queue_desc rt2500usb_queue_atim = { static const struct rt2x00_ops rt2500usb_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index 540c94f8505a..9e09367c9739 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1763,15 +1763,36 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); - rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, - rt2x00dev->default_ant.rx_chain_num <= 1); - rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, - rt2x00dev->default_ant.rx_chain_num <= 2); rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); - rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, - rt2x00dev->default_ant.tx_chain_num <= 1); - rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, - rt2x00dev->default_ant.tx_chain_num <= 2); + if (rt2x00_rt(rt2x00dev, RT3390)) { + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, + rt2x00dev->default_ant.rx_chain_num == 1); + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, + rt2x00dev->default_ant.tx_chain_num == 1); + } else { + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); + + switch (rt2x00dev->default_ant.tx_chain_num) { + case 1: + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); + /* fall through */ + case 2: + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); + break; + } + + switch (rt2x00dev->default_ant.rx_chain_num) { + case 1: + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); + /* fall through */ + case 2: + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); + break; + } + } rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); @@ -2875,32 +2896,23 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats); static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) { - u8 vgc; - if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071) || rt2x00_rt(rt2x00dev, RT3090) || rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT3390) || - rt2x00_rt(rt2x00dev, RT3572) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) - vgc = 0x1c + (2 * rt2x00dev->lna_gain); + return 0x1c + (2 * rt2x00dev->lna_gain); else - vgc = 0x2e + rt2x00dev->lna_gain; - } else { /* 5GHZ band */ - if (rt2x00_rt(rt2x00dev, RT3572)) - vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3; - else { - if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) - vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3; - else - vgc = 0x3a + (rt2x00dev->lna_gain * 5) / 3; - } + return 0x2e + rt2x00dev->lna_gain; } - return vgc; + if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) + return 0x32 + (rt2x00dev->lna_gain * 5) / 3; + else + return 0x3a + (rt2x00dev->lna_gain * 5) / 3; } static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, @@ -3069,7 +3081,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); } else if (rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) { + rt2x00_rt(rt2x00dev, RT5392)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); @@ -3514,11 +3526,6 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) } else if (rt2800_is_305x_soc(rt2x00dev)) { rt2800_bbp_write(rt2x00dev, 78, 0x0e); rt2800_bbp_write(rt2x00dev, 80, 0x08); - } else if (rt2x00_rt(rt2x00dev, RT3290)) { - rt2800_bbp_write(rt2x00dev, 74, 0x0b); - rt2800_bbp_write(rt2x00dev, 79, 0x18); - rt2800_bbp_write(rt2x00dev, 80, 0x09); - rt2800_bbp_write(rt2x00dev, 81, 0x33); } else if (rt2x00_rt(rt2x00dev, RT3352)) { rt2800_bbp_write(rt2x00dev, 78, 0x0e); rt2800_bbp_write(rt2x00dev, 80, 0x08); @@ -3527,6 +3534,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 81, 0x37); } + if (rt2x00_rt(rt2x00dev, RT3290)) { + rt2800_bbp_write(rt2x00dev, 74, 0x0b); + rt2800_bbp_write(rt2x00dev, 79, 0x18); + rt2800_bbp_write(rt2x00dev, 80, 0x09); + rt2800_bbp_write(rt2x00dev, 81, 0x33); + } + rt2800_bbp_write(rt2x00dev, 82, 0x62); if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390) || diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c index 27829e1e2e38..391e08fa054b 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1088,6 +1088,7 @@ static const struct data_queue_desc rt2800pci_queue_bcn = { static const struct rt2x00_ops rt2800pci_ops = { .name = KBUILD_MODNAME, .drv_data_size = sizeof(struct rt2800_drv_data), + .max_sta_intf = 1, .max_ap_intf = 8, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c index c9e9370eb789..603b65d6f28b 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c @@ -870,6 +870,7 @@ static const struct data_queue_desc rt2800usb_queue_bcn = { static const struct rt2x00_ops rt2800usb_ops = { .name = KBUILD_MODNAME, .drv_data_size = sizeof(struct rt2800_drv_data), + .max_sta_intf = 1, .max_ap_intf = 8, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00.h b/trunk/drivers/net/wireless/rt2x00/rt2x00.h index 0751b35ef6dc..49375c86c334 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00.h @@ -656,6 +656,7 @@ struct rt2x00lib_ops { struct rt2x00_ops { const char *name; const unsigned int drv_data_size; + const unsigned int max_sta_intf; const unsigned int max_ap_intf; const unsigned int eeprom_size; const unsigned int rf_size; @@ -740,14 +741,6 @@ enum rt2x00_capability_flags { CAPABILITY_VCO_RECALIBRATION, }; -/* - * Interface combinations - */ -enum { - IF_COMB_AP = 0, - NUM_IF_COMB, -}; - /* * rt2x00 device structure. */ @@ -874,12 +867,6 @@ struct rt2x00_dev { unsigned int intf_associated; unsigned int intf_beaconing; - /* - * Interface combinations - */ - struct ieee80211_iface_limit if_limits_ap; - struct ieee80211_iface_combination if_combinations[NUM_IF_COMB]; - /* * Link quality */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index 69097d1faeb6..10cf67267775 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1118,34 +1118,6 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) rt2x00dev->intf_associated = 0; } -static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) -{ - struct ieee80211_iface_limit *if_limit; - struct ieee80211_iface_combination *if_combination; - - /* - * Build up AP interface limits structure. - */ - if_limit = &rt2x00dev->if_limits_ap; - if_limit->max = rt2x00dev->ops->max_ap_intf; - if_limit->types = BIT(NL80211_IFTYPE_AP); - - /* - * Build up AP interface combinations structure. - */ - if_combination = &rt2x00dev->if_combinations[IF_COMB_AP]; - if_combination->limits = if_limit; - if_combination->n_limits = 1; - if_combination->max_interfaces = if_limit->max; - if_combination->num_different_channels = 1; - - /* - * Finally, specify the possible combinations to mac80211. - */ - rt2x00dev->hw->wiphy->iface_combinations = rt2x00dev->if_combinations; - rt2x00dev->hw->wiphy->n_iface_combinations = 1; -} - /* * driver allocation handlers. */ @@ -1153,11 +1125,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) { int retval = -ENOMEM; - /* - * Set possible interface combinations. - */ - rt2x00lib_set_if_combinations(rt2x00dev); - /* * Allocate the driver data memory, if necessary. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c index 98a9e48f8e4a..c3d0f2f87b69 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -214,6 +214,46 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) return -ENODEV; + switch (vif->type) { + case NL80211_IFTYPE_AP: + /* + * We don't support mixed combinations of + * sta and ap interfaces. + */ + if (rt2x00dev->intf_sta_count) + return -ENOBUFS; + + /* + * Check if we exceeded the maximum amount + * of supported interfaces. + */ + if (rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) + return -ENOBUFS; + + break; + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_WDS: + /* + * We don't support mixed combinations of + * sta and ap interfaces. + */ + if (rt2x00dev->intf_ap_count) + return -ENOBUFS; + + /* + * Check if we exceeded the maximum amount + * of supported interfaces. + */ + if (rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf) + return -ENOBUFS; + + break; + default: + return -EINVAL; + } + /* * Loop through all beacon queues to find a free * entry. Since there are as much beacon entries diff --git a/trunk/drivers/net/wireless/rt2x00/rt61pci.c b/trunk/drivers/net/wireless/rt2x00/rt61pci.c index d6582a2fa353..2673e058caaf 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt61pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt61pci.c @@ -3045,6 +3045,7 @@ static const struct data_queue_desc rt61pci_queue_bcn = { static const struct rt2x00_ops rt61pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, .max_ap_intf = 4, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.c b/trunk/drivers/net/wireless/rt2x00/rt73usb.c index e5eb43b3eee7..cfa9f37cccc2 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt73usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.c @@ -2382,6 +2382,7 @@ static const struct data_queue_desc rt73usb_queue_bcn = { static const struct rt2x00_ops rt73usb_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, .max_ap_intf = 4, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 2925094b2d91..04c3aef8a4f6 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -117,7 +117,6 @@ #define CHIP_VER_B BIT(4) #define CHIP_92C_BITMASK BIT(0) -#define CHIP_UNKNOWN BIT(7) #define CHIP_92C_1T2R 0x03 #define CHIP_92C 0x01 #define CHIP_88C 0x00 diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 86d73b32d995..cc895828c0ea 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -994,16 +994,8 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw) version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C : VERSION_A_CHIP_88C; } else { - version = (enum version_8192c) (CHIP_VER_B | - ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) | - ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); - if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 & - CHIP_VER_RTL_MASK)) { - version = (enum version_8192c)(version | - ((((value32 & CHIP_VER_RTL_MASK) == BIT(12)) - ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | - CHIP_VENDOR_UMC)); - } + version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C : + VERSION_B_CHIP_88C; } switch (version) { diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index ea2e1bd847c8..60451eea4d82 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -162,12 +162,10 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) /* request fw */ if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && - !IS_92C_SERIAL(rtlhal->version)) { + !IS_92C_SERIAL(rtlhal->version)) rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; - } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { + else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; - pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n"); - } rtlpriv->max_fw_size = 0x4000; pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); diff --git a/trunk/drivers/net/wireless/ti/wl12xx/main.c b/trunk/drivers/net/wireless/ti/wl12xx/main.c index dadf1dbb002a..f429fc110cb0 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/main.c +++ b/trunk/drivers/net/wireless/ti/wl12xx/main.c @@ -32,6 +32,7 @@ #include "../wlcore/acx.h" #include "../wlcore/tx.h" #include "../wlcore/rx.h" +#include "../wlcore/io.h" #include "../wlcore/boot.h" #include "wl12xx.h" @@ -1184,16 +1185,9 @@ static int wl12xx_enable_interrupts(struct wl1271 *wl) ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); if (ret < 0) - goto disable_interrupts; + goto out; ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); - if (ret < 0) - goto disable_interrupts; - - return ret; - -disable_interrupts: - wlcore_disable_interrupts(wl); out: return ret; @@ -1589,10 +1583,7 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, return wlcore_set_key(wl, cmd, vif, sta, key_conf); } -static int wl12xx_setup(struct wl1271 *wl); - static struct wlcore_ops wl12xx_ops = { - .setup = wl12xx_setup, .identify_chip = wl12xx_identify_chip, .identify_fw = wl12xx_identify_fw, .boot = wl12xx_boot, @@ -1633,15 +1624,26 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { }, }; -static int wl12xx_setup(struct wl1271 *wl) +static int __devinit wl12xx_probe(struct platform_device *pdev) { - struct wl12xx_priv *priv = wl->priv; - struct wl12xx_platform_data *pdata = wl->pdev->dev.platform_data; + struct wl12xx_platform_data *pdata = pdev->dev.platform_data; + struct wl1271 *wl; + struct ieee80211_hw *hw; + struct wl12xx_priv *priv; + hw = wlcore_alloc_hw(sizeof(*priv)); + if (IS_ERR(hw)) { + wl1271_error("can't allocate hw"); + return PTR_ERR(hw); + } + + wl = hw->priv; + priv = wl->priv; + wl->ops = &wl12xx_ops; + wl->ptable = wl12xx_ptable; wl->rtable = wl12xx_rtable; - wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; - wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; - wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES; + wl->num_tx_desc = 16; + wl->num_rx_desc = 8; wl->band_rate_to_idx = wl12xx_band_rate_to_idx; wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; @@ -1693,36 +1695,7 @@ static int wl12xx_setup(struct wl1271 *wl) wl1271_error("Invalid tcxo parameter %s", tcxo_param); } - return 0; -} - -static int __devinit wl12xx_probe(struct platform_device *pdev) -{ - struct wl1271 *wl; - struct ieee80211_hw *hw; - int ret; - - hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv), - WL12XX_AGGR_BUFFER_SIZE); - if (IS_ERR(hw)) { - wl1271_error("can't allocate hw"); - ret = PTR_ERR(hw); - goto out; - } - - wl = hw->priv; - wl->ops = &wl12xx_ops; - wl->ptable = wl12xx_ptable; - ret = wlcore_probe(wl, pdev); - if (ret) - goto out_free; - - return ret; - -out_free: - wlcore_free_hw(wl); -out: - return ret; + return wlcore_probe(wl, pdev); } static const struct platform_device_id wl12xx_id_table[] __devinitconst = { @@ -1741,7 +1714,17 @@ static struct platform_driver wl12xx_driver = { } }; -module_platform_driver(wl12xx_driver); +static int __init wl12xx_init(void) +{ + return platform_driver_register(&wl12xx_driver); +} +module_init(wl12xx_init); + +static void __exit wl12xx_exit(void) +{ + platform_driver_unregister(&wl12xx_driver); +} +module_exit(wl12xx_exit); module_param_named(fref, fref_param, charp, 0); MODULE_PARM_DESC(fref, "FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52"); diff --git a/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h b/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h index 7182bbf6625d..26990fb4edea 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h @@ -38,13 +38,6 @@ #define WL128X_SUBTYPE_VER 2 #define WL128X_MINOR_VER 115 -#define WL12XX_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) - -#define WL12XX_NUM_TX_DESCRIPTORS 16 -#define WL12XX_NUM_RX_DESCRIPTORS 8 - -#define WL12XX_NUM_MAC_ADDRESSES 2 - struct wl127x_rx_mem_pool_addr { u32 addr; u32 addr_extra; diff --git a/trunk/drivers/net/wireless/ti/wl18xx/debugfs.c b/trunk/drivers/net/wireless/ti/wl18xx/debugfs.c index 7f1669cdea09..3ce6f1039af3 100644 --- a/trunk/drivers/net/wireless/ti/wl18xx/debugfs.c +++ b/trunk/drivers/net/wireless/ti/wl18xx/debugfs.c @@ -220,7 +220,7 @@ static ssize_t clear_fw_stats_write(struct file *file, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (wl->state == WL1271_STATE_OFF) goto out; ret = wl18xx_acx_clear_statistics(wl); diff --git a/trunk/drivers/net/wireless/ti/wl18xx/main.c b/trunk/drivers/net/wireless/ti/wl18xx/main.c index a39682a7c25f..31cf6eba3a9e 100644 --- a/trunk/drivers/net/wireless/ti/wl18xx/main.c +++ b/trunk/drivers/net/wireless/ti/wl18xx/main.c @@ -45,6 +45,7 @@ static char *ht_mode_param = NULL; static char *board_type_param = NULL; static bool checksum_param = false; +static bool enable_11a_param = true; static int num_rx_desc_param = -1; /* phy paramters */ @@ -414,7 +415,7 @@ static struct wlcore_conf wl18xx_conf = { .snr_threshold = 0, }, .ht = { - .rx_ba_win_size = 32, + .rx_ba_win_size = 10, .tx_ba_win_size = 64, .inactivity_timeout = 10000, .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, @@ -504,8 +505,8 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { .rdl = 0x01, .auto_detect = 0x00, .dedicated_fem = FEM_NONE, - .low_band_component = COMPONENT_3_WAY_SWITCH, - .low_band_component_type = 0x04, + .low_band_component = COMPONENT_2_WAY_SWITCH, + .low_band_component_type = 0x06, .high_band_component = COMPONENT_2_WAY_SWITCH, .high_band_component_type = 0x09, .tcxo_ldo_voltage = 0x00, @@ -811,13 +812,6 @@ static int wl18xx_enable_interrupts(struct wl1271 *wl) ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL & ~intr_mask); - if (ret < 0) - goto disable_interrupts; - - return ret; - -disable_interrupts: - wlcore_disable_interrupts(wl); out: return ret; @@ -1208,12 +1202,6 @@ static int wl18xx_handle_static_data(struct wl1271 *wl, struct wl18xx_static_data_priv *static_data_priv = (struct wl18xx_static_data_priv *) static_data->priv; - strncpy(wl->chip.phy_fw_ver_str, static_data_priv->phy_version, - sizeof(wl->chip.phy_fw_ver_str)); - - /* make sure the string is NULL-terminated */ - wl->chip.phy_fw_ver_str[sizeof(wl->chip.phy_fw_ver_str) - 1] = '\0'; - wl1271_info("PHY firmware version: %s", static_data_priv->phy_version); return 0; @@ -1252,6 +1240,13 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, if (!change_spare) return wlcore_set_key(wl, cmd, vif, sta, key_conf); + /* + * stop the queues and flush to ensure the next packets are + * in sync with FW spare block accounting + */ + wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); + wl1271_tx_flush(wl); + ret = wlcore_set_key(wl, cmd, vif, sta, key_conf); if (ret < 0) goto out; @@ -1274,6 +1269,7 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, } out: + wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); return ret; } @@ -1296,10 +1292,7 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl, return buf_offset; } -static int wl18xx_setup(struct wl1271 *wl); - static struct wlcore_ops wl18xx_ops = { - .setup = wl18xx_setup, .identify_chip = wl18xx_identify_chip, .boot = wl18xx_boot, .plt_init = wl18xx_plt_init, @@ -1380,15 +1373,27 @@ static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { }, }; -static int wl18xx_setup(struct wl1271 *wl) +static int __devinit wl18xx_probe(struct platform_device *pdev) { - struct wl18xx_priv *priv = wl->priv; + struct wl1271 *wl; + struct ieee80211_hw *hw; + struct wl18xx_priv *priv; int ret; + hw = wlcore_alloc_hw(sizeof(*priv)); + if (IS_ERR(hw)) { + wl1271_error("can't allocate hw"); + ret = PTR_ERR(hw); + goto out; + } + + wl = hw->priv; + priv = wl->priv; + wl->ops = &wl18xx_ops; + wl->ptable = wl18xx_ptable; wl->rtable = wl18xx_rtable; - wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; - wl->num_rx_desc = WL18XX_NUM_TX_DESCRIPTORS; - wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES; + wl->num_tx_desc = 32; + wl->num_rx_desc = 32; wl->band_rate_to_idx = wl18xx_band_rate_to_idx; wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; @@ -1399,9 +1404,9 @@ static int wl18xx_setup(struct wl1271 *wl) if (num_rx_desc_param != -1) wl->num_rx_desc = num_rx_desc_param; - ret = wl18xx_conf_init(wl, wl->dev); + ret = wl18xx_conf_init(wl, &pdev->dev); if (ret < 0) - return ret; + goto out_free; /* If the module param is set, update it in conf */ if (board_type_param) { @@ -1418,14 +1423,27 @@ static int wl18xx_setup(struct wl1271 *wl) } else { wl1271_error("invalid board type '%s'", board_type_param); - return -EINVAL; + ret = -EINVAL; + goto out_free; } } - if (priv->conf.phy.board_type >= NUM_BOARD_TYPES) { + /* HACK! Just for now we hardcode COM8 and HDK to 0x06 */ + switch (priv->conf.phy.board_type) { + case BOARD_TYPE_HDK_18XX: + case BOARD_TYPE_COM8_18XX: + priv->conf.phy.low_band_component_type = 0x06; + break; + case BOARD_TYPE_FPGA_18XX: + case BOARD_TYPE_DVP_18XX: + case BOARD_TYPE_EVB_18XX: + priv->conf.phy.low_band_component_type = 0x05; + break; + default: wl1271_error("invalid board type '%d'", priv->conf.phy.board_type); - return -EINVAL; + ret = -EINVAL; + goto out_free; } if (low_band_component_param != -1) @@ -1457,21 +1475,22 @@ static int wl18xx_setup(struct wl1271 *wl) priv->conf.ht.mode = HT_MODE_SISO20; else { wl1271_error("invalid ht_mode '%s'", ht_mode_param); - return -EINVAL; + ret = -EINVAL; + goto out_free; } } if (priv->conf.ht.mode == HT_MODE_DEFAULT) { /* * Only support mimo with multiple antennas. Fall back to - * siso40. + * siso20. */ if (wl18xx_is_mimo_supported(wl)) wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl18xx_mimo_ht_cap_2ghz); else wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, - &wl18xx_siso40_ht_cap_2ghz); + &wl18xx_siso20_ht_cap); /* 5Ghz is always wide */ wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, @@ -1493,34 +1512,9 @@ static int wl18xx_setup(struct wl1271 *wl) wl18xx_ops.init_vif = NULL; } - /* Enable 11a Band only if we have 5G antennas */ - wl->enable_11a = (priv->conf.phy.number_of_assembled_ant5 != 0); - - return 0; -} + wl->enable_11a = enable_11a_param; -static int __devinit wl18xx_probe(struct platform_device *pdev) -{ - struct wl1271 *wl; - struct ieee80211_hw *hw; - int ret; - - hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv), - WL18XX_AGGR_BUFFER_SIZE); - if (IS_ERR(hw)) { - wl1271_error("can't allocate hw"); - ret = PTR_ERR(hw); - goto out; - } - - wl = hw->priv; - wl->ops = &wl18xx_ops; - wl->ptable = wl18xx_ptable; - ret = wlcore_probe(wl, pdev); - if (ret) - goto out_free; - - return ret; + return wlcore_probe(wl, pdev); out_free: wlcore_free_hw(wl); @@ -1544,7 +1538,18 @@ static struct platform_driver wl18xx_driver = { } }; -module_platform_driver(wl18xx_driver); +static int __init wl18xx_init(void) +{ + return platform_driver_register(&wl18xx_driver); +} +module_init(wl18xx_init); + +static void __exit wl18xx_exit(void) +{ + platform_driver_unregister(&wl18xx_driver); +} +module_exit(wl18xx_exit); + module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR); MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20"); @@ -1555,6 +1560,9 @@ MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or " module_param_named(checksum, checksum_param, bool, S_IRUSR); MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to false)"); +module_param_named(enable_11a, enable_11a_param, bool, S_IRUSR); +MODULE_PARM_DESC(enable_11a, "Enable 11a (5GHz): boolean (defaults to true)"); + module_param_named(dc2dc, dc2dc_param, int, S_IRUSR); MODULE_PARM_DESC(dc2dc, "External DC2DC: u8 (defaults to 0)"); diff --git a/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h b/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h index 96a1e438d677..6452396fa1d4 100644 --- a/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h @@ -33,13 +33,6 @@ #define WL18XX_CMD_MAX_SIZE 740 -#define WL18XX_AGGR_BUFFER_SIZE (13 * PAGE_SIZE) - -#define WL18XX_NUM_TX_DESCRIPTORS 32 -#define WL18XX_NUM_RX_DESCRIPTORS 32 - -#define WL18XX_NUM_MAC_ADDRESSES 3 - struct wl18xx_priv { /* buffer for sending commands to FW */ u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; diff --git a/trunk/drivers/net/wireless/ti/wlcore/cmd.c b/trunk/drivers/net/wireless/ti/wlcore/cmd.c index eaef3f41b252..20e1bd923832 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/cmd.c +++ b/trunk/drivers/net/wireless/ti/wlcore/cmd.c @@ -59,9 +59,6 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, u16 status; u16 poll_count = 0; - if (WARN_ON(unlikely(wl->state == WLCORE_STATE_RESTARTING))) - return -EIO; - cmd = buf; cmd->id = cpu_to_le16(id); cmd->status = 0; @@ -993,7 +990,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_KLV, skb->data, skb->len, - wlvif->sta.klv_template_id, + CMD_TEMPL_KLV_IDX_NULL_DATA, wlvif->basic_rate); out: @@ -1788,16 +1785,9 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) wlvif->bss_type == BSS_TYPE_IBSS))) return -EINVAL; - ret = wl12xx_cmd_role_enable(wl, - wl12xx_wlvif_to_vif(wlvif)->addr, - WL1271_ROLE_DEVICE, - &wlvif->dev_role_id); - if (ret < 0) - goto out; - ret = wl12xx_cmd_role_start_dev(wl, wlvif); if (ret < 0) - goto out_disable; + goto out; ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); if (ret < 0) @@ -1807,8 +1797,6 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) out_stop: wl12xx_cmd_role_stop_dev(wl, wlvif); -out_disable: - wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); out: return ret; } @@ -1836,11 +1824,6 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) ret = wl12xx_cmd_role_stop_dev(wl, wlvif); if (ret < 0) goto out; - - ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); - if (ret < 0) - goto out; - out: return ret; } diff --git a/trunk/drivers/net/wireless/ti/wlcore/cmd.h b/trunk/drivers/net/wireless/ti/wlcore/cmd.h index 2409f3d71f63..4ef0b095f0d6 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/cmd.h +++ b/trunk/drivers/net/wireless/ti/wlcore/cmd.h @@ -157,6 +157,11 @@ enum wl1271_commands { #define MAX_CMD_PARAMS 572 +enum { + CMD_TEMPL_KLV_IDX_NULL_DATA = 0, + CMD_TEMPL_KLV_IDX_MAX = 4 +}; + enum cmd_templ { CMD_TEMPL_NULL_DATA = 0, CMD_TEMPL_BEACON, diff --git a/trunk/drivers/net/wireless/ti/wlcore/conf.h b/trunk/drivers/net/wireless/ti/wlcore/conf.h index 9e40760bafe1..d77224f2ac6b 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/conf.h +++ b/trunk/drivers/net/wireless/ti/wlcore/conf.h @@ -412,7 +412,8 @@ struct conf_rx_settings { #define CONF_TX_RATE_RETRY_LIMIT 10 /* basic rates for p2p operations (probe req/resp, etc.) */ -#define CONF_TX_RATE_MASK_BASIC_P2P CONF_HW_BIT_RATE_6MBPS +#define CONF_TX_RATE_MASK_BASIC_P2P (CONF_HW_BIT_RATE_6MBPS | \ + CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS) /* * Rates supported for data packets when operating as AP. Note the absence diff --git a/trunk/drivers/net/wireless/ti/wlcore/debug.h b/trunk/drivers/net/wireless/ti/wlcore/debug.h index db4bf5a68ce2..6b800b3cbea5 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/debug.h +++ b/trunk/drivers/net/wireless/ti/wlcore/debug.h @@ -28,7 +28,7 @@ #include #include -#define DRIVER_NAME "wlcore" +#define DRIVER_NAME "wl12xx" #define DRIVER_PREFIX DRIVER_NAME ": " enum { @@ -73,21 +73,11 @@ extern u32 wl12xx_debug_level; #define wl1271_info(fmt, arg...) \ pr_info(DRIVER_PREFIX fmt "\n", ##arg) -/* define the debug macro differently if dynamic debug is supported */ -#if defined(CONFIG_DYNAMIC_DEBUG) #define wl1271_debug(level, fmt, arg...) \ do { \ - if (unlikely(level & wl12xx_debug_level)) \ - dynamic_pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ - } while (0) -#else -#define wl1271_debug(level, fmt, arg...) \ - do { \ - if (unlikely(level & wl12xx_debug_level)) \ - printk(KERN_DEBUG pr_fmt(DRIVER_PREFIX fmt "\n"), \ - ##arg); \ + if (level & wl12xx_debug_level) \ + pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ } while (0) -#endif /* TODO: use pr_debug_hex_dump when it becomes available */ #define wl1271_dump(level, prefix, buf, len) \ diff --git a/trunk/drivers/net/wireless/ti/wlcore/debugfs.c b/trunk/drivers/net/wireless/ti/wlcore/debugfs.c index c86bb00c2488..80dbc5304fac 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/trunk/drivers/net/wireless/ti/wlcore/debugfs.c @@ -62,14 +62,11 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) - goto out; - ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; - if (!wl->plt && + if (wl->state == WL1271_STATE_ON && !wl->plt && time_after(jiffies, wl->stats.fw_stats_update + msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { wl1271_acx_statistics(wl, wl->stats.fw_stats); @@ -289,7 +286,7 @@ static ssize_t dynamic_ps_timeout_write(struct file *file, wl->conf.conn.dynamic_ps_timeout = value; - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (wl->state == WL1271_STATE_OFF) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -356,7 +353,7 @@ static ssize_t forced_ps_write(struct file *file, wl->conf.conn.forced_ps = value; - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (wl->state == WL1271_STATE_OFF) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -489,7 +486,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_HEX(platform_quirks); DRIVER_STATE_PRINT_HEX(chip.id); DRIVER_STATE_PRINT_STR(chip.fw_ver_str); - DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str); DRIVER_STATE_PRINT_INT(sched_scanning); #undef DRIVER_STATE_PRINT_INT @@ -1003,7 +999,7 @@ static ssize_t sleep_auth_write(struct file *file, wl->conf.conn.sta_sleep_auth = value; - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (wl->state == WL1271_STATE_OFF) { /* this will show up on "read" in case we are off */ wl->sleep_auth = value; goto out; @@ -1064,16 +1060,14 @@ static ssize_t dev_mem_read(struct file *file, mutex_lock(&wl->mutex); - if (unlikely(wl->state == WLCORE_STATE_OFF)) { + if (wl->state == WL1271_STATE_OFF) { ret = -EFAULT; goto skip_read; } - /* - * Don't fail if elp_wakeup returns an error, so the device's memory - * could be read even if the FW crashed - */ - wl1271_ps_elp_wakeup(wl); + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto skip_read; /* store current partition and switch partition */ memcpy(&old_part, &wl->curr_part, sizeof(old_part)); @@ -1151,16 +1145,14 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf, mutex_lock(&wl->mutex); - if (unlikely(wl->state == WLCORE_STATE_OFF)) { + if (wl->state == WL1271_STATE_OFF) { ret = -EFAULT; goto skip_write; } - /* - * Don't fail if elp_wakeup returns an error, so the device's memory - * could be read even if the FW crashed - */ - wl1271_ps_elp_wakeup(wl); + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto skip_write; /* store current partition and switch partition */ memcpy(&old_part, &wl->curr_part, sizeof(old_part)); diff --git a/trunk/drivers/net/wireless/ti/wlcore/init.c b/trunk/drivers/net/wireless/ti/wlcore/init.c index 32d157f62f31..a3c867786df8 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/init.c +++ b/trunk/drivers/net/wireless/ti/wlcore/init.c @@ -141,7 +141,7 @@ int wl1271_init_templates_config(struct wl1271 *wl) if (ret < 0) return ret; - for (i = 0; i < WLCORE_MAX_KLV_TEMPLATES; i++) { + for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, CMD_TEMPL_KLV, NULL, sizeof(struct ieee80211_qos_hdr), @@ -371,7 +371,15 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl, struct ieee80211_vif *vif) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - int ret; + int ret, i; + + /* disable all keep-alive templates */ + for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { + ret = wl1271_acx_keep_alive_config(wl, wlvif, i, + ACX_KEEP_ALIVE_TPL_INVALID); + if (ret < 0) + return ret; + } /* disable the keep-alive feature */ ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); diff --git a/trunk/drivers/net/wireless/ti/wlcore/io.h b/trunk/drivers/net/wireless/ti/wlcore/io.h index f48530fec14f..259149f36fae 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/io.h +++ b/trunk/drivers/net/wireless/ti/wlcore/io.h @@ -64,7 +64,7 @@ static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr, return -EIO; ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed); - if (ret && wl->state != WLCORE_STATE_OFF) + if (ret && wl->state != WL1271_STATE_OFF) set_bit(WL1271_FLAG_IO_FAILED, &wl->flags); return ret; @@ -80,7 +80,7 @@ static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr, return -EIO; ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed); - if (ret && wl->state != WLCORE_STATE_OFF) + if (ret && wl->state != WL1271_STATE_OFF) set_bit(WL1271_FLAG_IO_FAILED, &wl->flags); return ret; diff --git a/trunk/drivers/net/wireless/ti/wlcore/main.c b/trunk/drivers/net/wireless/ti/wlcore/main.c index 25530c8760cb..ff830cf50c70 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/main.c +++ b/trunk/drivers/net/wireless/ti/wlcore/main.c @@ -248,7 +248,7 @@ static void wl12xx_tx_watchdog_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; /* Tx went out in the meantime - everything is ok */ @@ -512,7 +512,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) wl1271_debug(DEBUG_IRQ, "IRQ work"); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -696,7 +696,7 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) * we can't call wl12xx_get_vif_count() here because * wl->mutex is taken, so use the cached last_vif_count value */ - if (wl->last_vif_count > 1 && wl->mr_fw_name) { + if (wl->last_vif_count > 1) { fw_type = WL12XX_FW_TYPE_MULTI; fw_name = wl->mr_fw_name; } else { @@ -744,14 +744,38 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) return ret; } +static void wl1271_fetch_nvs(struct wl1271 *wl) +{ + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev); + + if (ret < 0) { + wl1271_debug(DEBUG_BOOT, "could not get nvs file %s: %d", + WL12XX_NVS_NAME, ret); + return; + } + + wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); + + if (!wl->nvs) { + wl1271_error("could not allocate memory for the nvs file"); + goto out; + } + + wl->nvs_len = fw->size; + +out: + release_firmware(fw); +} + void wl12xx_queue_recovery_work(struct wl1271 *wl) { WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); /* Avoid a recursive recovery */ - if (wl->state == WLCORE_STATE_ON) { - wl->state = WLCORE_STATE_RESTARTING; - set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); + if (!test_and_set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { wlcore_disable_interrupts_nosync(wl); ieee80211_queue_work(wl->hw, &wl->recovery_work); } @@ -889,7 +913,7 @@ static void wl1271_recovery_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (wl->state == WLCORE_STATE_OFF || wl->plt) + if (wl->state != WL1271_STATE_ON || wl->plt) goto out_unlock; if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) { @@ -1057,7 +1081,7 @@ int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode) wl1271_notice("power up"); - if (wl->state != WLCORE_STATE_OFF) { + if (wl->state != WL1271_STATE_OFF) { wl1271_error("cannot go into PLT state because not " "in off state: %d", wl->state); ret = -EBUSY; @@ -1078,7 +1102,7 @@ int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode) if (ret < 0) goto power_off; - wl->state = WLCORE_STATE_ON; + wl->state = WL1271_STATE_ON; wl1271_notice("firmware booted in PLT mode %s (%s)", PLT_MODE[plt_mode], wl->chip.fw_ver_str); @@ -1147,7 +1171,7 @@ int wl1271_plt_stop(struct wl1271 *wl) wl1271_power_off(wl); wl->flags = 0; wl->sleep_auth = WL1271_PSM_ILLEGAL; - wl->state = WLCORE_STATE_OFF; + wl->state = WL1271_STATE_OFF; wl->plt = false; wl->plt_mode = PLT_OFF; wl->rx_counter = 0; @@ -1578,6 +1602,12 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) goto out; + if ((wl->conf.conn.suspend_wake_up_event == + wl->conf.conn.wake_up_event) && + (wl->conf.conn.suspend_listen_interval == + wl->conf.conn.listen_interval)) + goto out; + ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; @@ -1586,12 +1616,6 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, if (ret < 0) goto out_sleep; - if ((wl->conf.conn.suspend_wake_up_event == - wl->conf.conn.wake_up_event) && - (wl->conf.conn.suspend_listen_interval == - wl->conf.conn.listen_interval)) - goto out_sleep; - ret = wl1271_acx_wake_up_conditions(wl, wlvif, wl->conf.conn.suspend_wake_up_event, wl->conf.conn.suspend_listen_interval); @@ -1647,7 +1671,11 @@ static void wl1271_configure_resume(struct wl1271 *wl, if ((!is_ap) && (!is_sta)) return; - if (is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + if (is_sta && + ((wl->conf.conn.suspend_wake_up_event == + wl->conf.conn.wake_up_event) && + (wl->conf.conn.suspend_listen_interval == + wl->conf.conn.listen_interval))) return; ret = wl1271_ps_elp_wakeup(wl); @@ -1657,12 +1685,6 @@ static void wl1271_configure_resume(struct wl1271 *wl, if (is_sta) { wl1271_configure_wowlan(wl, NULL); - if ((wl->conf.conn.suspend_wake_up_event == - wl->conf.conn.wake_up_event) && - (wl->conf.conn.suspend_listen_interval == - wl->conf.conn.listen_interval)) - goto out_sleep; - ret = wl1271_acx_wake_up_conditions(wl, wlvif, wl->conf.conn.wake_up_event, wl->conf.conn.listen_interval); @@ -1675,7 +1697,6 @@ static void wl1271_configure_resume(struct wl1271 *wl, ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); } -out_sleep: wl1271_ps_elp_sleep(wl); } @@ -1812,7 +1833,7 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) { int i; - if (wl->state == WLCORE_STATE_OFF) { + if (wl->state == WL1271_STATE_OFF) { if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) wlcore_enable_interrupts(wl); @@ -1824,7 +1845,7 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) * this must be before the cancel_work calls below, so that the work * functions don't perform further work. */ - wl->state = WLCORE_STATE_OFF; + wl->state = WL1271_STATE_OFF; /* * Use the nosync variant to disable interrupts, so the mutex could be @@ -1835,8 +1856,6 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) mutex_unlock(&wl->mutex); wlcore_synchronize_interrupts(wl); - if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) - cancel_work_sync(&wl->recovery_work); wl1271_flush_deferred_work(wl); cancel_delayed_work_sync(&wl->scan_complete_work); cancel_work_sync(&wl->netstack_work); @@ -1939,27 +1958,6 @@ static void wl12xx_free_rate_policy(struct wl1271 *wl, u8 *idx) *idx = WL12XX_MAX_RATE_POLICIES; } -static int wlcore_allocate_klv_template(struct wl1271 *wl, u8 *idx) -{ - u8 policy = find_first_zero_bit(wl->klv_templates_map, - WLCORE_MAX_KLV_TEMPLATES); - if (policy >= WLCORE_MAX_KLV_TEMPLATES) - return -EBUSY; - - __set_bit(policy, wl->klv_templates_map); - *idx = policy; - return 0; -} - -static void wlcore_free_klv_template(struct wl1271 *wl, u8 *idx) -{ - if (WARN_ON(*idx >= WLCORE_MAX_KLV_TEMPLATES)) - return; - - __clear_bit(*idx, wl->klv_templates_map); - *idx = WLCORE_MAX_KLV_TEMPLATES; -} - static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) { switch (wlvif->bss_type) { @@ -2024,7 +2022,6 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx); wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx); wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx); - wlcore_allocate_klv_template(wl, &wlvif->sta.klv_template_id); wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -2101,7 +2098,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) /* Unlocking the mutex in the middle of handling is inherently unsafe. In this case we deem it safe to do, because we need to let any possibly pending IRQ out of - the system (and while we are WLCORE_STATE_OFF the IRQ + the system (and while we are WL1271_STATE_OFF the IRQ work function will not do anything.) Also, any other possible concurrent operations will fail due to the current state, hence the wl1271 struct should be safe. */ @@ -2136,7 +2133,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", wl->enable_11a ? "" : "not "); - wl->state = WLCORE_STATE_ON; + wl->state = WL1271_STATE_ON; out: return booted; } @@ -2170,11 +2167,7 @@ static bool wl12xx_need_fw_change(struct wl1271 *wl, wl->last_vif_count = vif_count; /* no need for fw change if the device is OFF */ - if (wl->state == WLCORE_STATE_OFF) - return false; - - /* no need for fw change if a single fw is used */ - if (!wl->mr_fw_name) + if (wl->state == WL1271_STATE_OFF) return false; if (vif_count > 1 && current_fw == WL12XX_FW_TYPE_NORMAL) @@ -2256,7 +2249,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, * TODO: after the nvs issue will be solved, move this block * to start(), and make sure here the driver is ON. */ - if (wl->state == WLCORE_STATE_OFF) { + if (wl->state == WL1271_STATE_OFF) { /* * we still need this in order to configure the fw * while uploading the nvs @@ -2270,6 +2263,21 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, } } + if (wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS) { + /* + * The device role is a special role used for + * rx and tx frames prior to association (as + * the STA role can get packets only from + * its associated bssid) + */ + ret = wl12xx_cmd_role_enable(wl, vif->addr, + WL1271_ROLE_DEVICE, + &wlvif->dev_role_id); + if (ret < 0) + goto out; + } + ret = wl12xx_cmd_role_enable(wl, vif->addr, role_type, &wlvif->role_id); if (ret < 0) @@ -2308,7 +2316,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, return; /* because of hardware recovery, we may get here twice */ - if (wl->state == WLCORE_STATE_OFF) + if (wl->state != WL1271_STATE_ON) return; wl1271_info("down"); @@ -2338,6 +2346,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wlvif->bss_type == BSS_TYPE_IBSS) { if (wl12xx_dev_role_started(wlvif)) wl12xx_stop_dev(wl, wlvif); + + ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); + if (ret < 0) + goto deinit; } ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id); @@ -2356,7 +2368,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl12xx_free_rate_policy(wl, &wlvif->sta.basic_rate_idx); wl12xx_free_rate_policy(wl, &wlvif->sta.ap_rate_idx); wl12xx_free_rate_policy(wl, &wlvif->sta.p2p_rate_idx); - wlcore_free_klv_template(wl, &wlvif->sta.klv_template_id); } else { wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; @@ -2421,11 +2432,12 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl12xx_vif *iter; struct vif_counter_data vif_count; + bool cancel_recovery = true; wl12xx_get_vif_count(hw, vif, &vif_count); mutex_lock(&wl->mutex); - if (wl->state == WLCORE_STATE_OFF || + if (wl->state == WL1271_STATE_OFF || !test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) goto out; @@ -2445,9 +2457,12 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, wl12xx_force_active_psm(wl); set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); wl12xx_queue_recovery_work(wl); + cancel_recovery = false; } out: mutex_unlock(&wl->mutex); + if (cancel_recovery) + cancel_work_sync(&wl->recovery_work); } static int wl12xx_op_change_interface(struct ieee80211_hw *hw, @@ -2521,7 +2536,7 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; ret = wl1271_acx_keep_alive_config(wl, wlvif, - wlvif->sta.klv_template_id, + CMD_TEMPL_KLV_IDX_NULL_DATA, ACX_KEEP_ALIVE_TPL_VALID); if (ret < 0) goto out; @@ -2541,11 +2556,6 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) ieee80211_chswitch_done(vif, false); } - /* invalidate keep-alive template */ - wl1271_acx_keep_alive_config(wl, wlvif, - wlvif->sta.klv_template_id, - ACX_KEEP_ALIVE_TPL_INVALID); - /* to stop listening to a channel, we disconnect */ ret = wl12xx_cmd_role_stop_sta(wl, wlvif); if (ret < 0) @@ -2584,6 +2594,11 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, wlvif->rate_set = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); ret = wl1271_acx_sta_rate_policies(wl, wlvif); + if (ret < 0) + goto out; + ret = wl1271_acx_keep_alive_config( + wl, wlvif, CMD_TEMPL_KLV_IDX_NULL_DATA, + ACX_KEEP_ALIVE_TPL_INVALID); if (ret < 0) goto out; clear_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); @@ -2757,7 +2772,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_POWER) wl->power_level = conf->power_level; - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -2791,6 +2806,10 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, { struct wl1271_filter_params *fp; struct netdev_hw_addr *ha; + struct wl1271 *wl = hw->priv; + + if (unlikely(wl->state == WL1271_STATE_OFF)) + return 0; fp = kzalloc(sizeof(*fp), GFP_ATOMIC); if (!fp) { @@ -2839,7 +2858,7 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, *total &= WL1271_SUPPORTED_FILTERS; changed &= WL1271_SUPPORTED_FILTERS; - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -3063,45 +3082,8 @@ static int wlcore_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key_conf) { struct wl1271 *wl = hw->priv; - int ret; - bool might_change_spare = - key_conf->cipher == WL1271_CIPHER_SUITE_GEM || - key_conf->cipher == WLAN_CIPHER_SUITE_TKIP; - if (might_change_spare) { - /* - * stop the queues and flush to ensure the next packets are - * in sync with FW spare block accounting - */ - mutex_lock(&wl->mutex); - wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); - mutex_unlock(&wl->mutex); - - wl1271_tx_flush(wl); - } - - mutex_lock(&wl->mutex); - - if (unlikely(wl->state != WLCORE_STATE_ON)) { - ret = -EAGAIN; - goto out_wake_queues; - } - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out_wake_queues; - - ret = wlcore_hw_set_key(wl, cmd, vif, sta, key_conf); - - wl1271_ps_elp_sleep(wl); - -out_wake_queues: - if (might_change_spare) - wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); - - mutex_unlock(&wl->mutex); - - return ret; + return wlcore_hw_set_key(wl, cmd, vif, sta, key_conf); } int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, @@ -3123,6 +3105,17 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, key_conf->keylen, key_conf->flags); wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EAGAIN; + goto out_unlock; + } + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out_unlock; + switch (key_conf->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: @@ -3152,7 +3145,8 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, default: wl1271_error("Unknown key algo 0x%x", key_conf->cipher); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto out_sleep; } switch (cmd) { @@ -3163,7 +3157,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, tx_seq_32, tx_seq_16, sta); if (ret < 0) { wl1271_error("Could not add or replace key"); - return ret; + goto out_sleep; } /* @@ -3177,7 +3171,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, ret = wl1271_cmd_build_arp_rsp(wl, wlvif); if (ret < 0) { wl1271_warning("build arp rsp failed: %d", ret); - return ret; + goto out_sleep; } } break; @@ -3189,15 +3183,22 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, 0, 0, sta); if (ret < 0) { wl1271_error("Could not remove key"); - return ret; + goto out_sleep; } break; default: wl1271_error("Unsupported key cmd 0x%x", cmd); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + break; } +out_sleep: + wl1271_ps_elp_sleep(wl); + +out_unlock: + mutex_unlock(&wl->mutex); + return ret; } EXPORT_SYMBOL_GPL(wlcore_set_key); @@ -3220,7 +3221,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (wl->state == WL1271_STATE_OFF) { /* * We cannot return -EBUSY here because cfg80211 will expect * a call to ieee80211_scan_completed if we do - in this case @@ -3260,7 +3261,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (wl->state == WL1271_STATE_OFF) goto out; if (wl->scan.state == WL1271_SCAN_STATE_IDLE) @@ -3309,7 +3310,7 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (wl->state == WL1271_STATE_OFF) { ret = -EAGAIN; goto out; } @@ -3346,7 +3347,7 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (wl->state == WL1271_STATE_OFF) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -3367,7 +3368,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (unlikely(wl->state == WL1271_STATE_OFF)) { ret = -EAGAIN; goto out; } @@ -3396,7 +3397,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (unlikely(wl->state == WL1271_STATE_OFF)) { ret = -EAGAIN; goto out; } @@ -4172,7 +4173,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; if (unlikely(!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))) @@ -4256,7 +4257,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -4455,7 +4456,7 @@ static int wl12xx_op_sta_state(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (unlikely(wl->state == WL1271_STATE_OFF)) { ret = -EBUSY; goto out; } @@ -4494,7 +4495,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (unlikely(wl->state == WL1271_STATE_OFF)) { ret = -EAGAIN; goto out; } @@ -4612,7 +4613,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, mask->control[i].legacy, i); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; if (wlvif->bss_type == BSS_TYPE_STA_BSS && @@ -4648,14 +4649,12 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state == WLCORE_STATE_OFF)) { + if (unlikely(wl->state == WL1271_STATE_OFF)) { wl12xx_for_each_wlvif_sta(wl, wlvif) { struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); ieee80211_chswitch_done(vif, false); } goto out; - } else if (unlikely(wl->state != WLCORE_STATE_ON)) { - goto out; } ret = wl1271_ps_elp_wakeup(wl); @@ -4690,7 +4689,7 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; /* packets are considered pending if in the TX queue or the FW */ @@ -4939,7 +4938,7 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, wl->sg_enabled = res; - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (wl->state == WL1271_STATE_OFF) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -5057,7 +5056,7 @@ static void wl1271_connection_loss_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; /* Call mac80211 connection loss */ @@ -5071,17 +5070,18 @@ static void wl1271_connection_loss_work(struct work_struct *work) mutex_unlock(&wl->mutex); } -static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic) +static void wl12xx_derive_mac_addresses(struct wl1271 *wl, + u32 oui, u32 nic, int n) { int i; - wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x", - oui, nic); + wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x, n %d", + oui, nic, n); - if (nic + WLCORE_NUM_MAC_ADDRESSES - wl->num_mac_addr > 0xffffff) + if (nic + n - 1 > 0xffffff) wl1271_warning("NIC part of the MAC address wraps around!"); - for (i = 0; i < wl->num_mac_addr; i++) { + for (i = 0; i < n; i++) { wl->addresses[i].addr[0] = (u8)(oui >> 16); wl->addresses[i].addr[1] = (u8)(oui >> 8); wl->addresses[i].addr[2] = (u8) oui; @@ -5091,22 +5091,7 @@ static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic) nic++; } - /* we may be one address short at the most */ - WARN_ON(wl->num_mac_addr + 1 < WLCORE_NUM_MAC_ADDRESSES); - - /* - * turn on the LAA bit in the first address and use it as - * the last address. - */ - if (wl->num_mac_addr < WLCORE_NUM_MAC_ADDRESSES) { - int idx = WLCORE_NUM_MAC_ADDRESSES - 1; - memcpy(&wl->addresses[idx], &wl->addresses[0], - sizeof(wl->addresses[0])); - /* LAA bit */ - wl->addresses[idx].addr[2] |= BIT(1); - } - - wl->hw->wiphy->n_addresses = WLCORE_NUM_MAC_ADDRESSES; + wl->hw->wiphy->n_addresses = n; wl->hw->wiphy->addresses = wl->addresses; } @@ -5145,7 +5130,8 @@ static int wl1271_register_hw(struct wl1271 *wl) if (wl->mac80211_registered) return 0; - if (wl->nvs_len >= 12) { + wl1271_fetch_nvs(wl); + if (wl->nvs != NULL) { /* NOTE: The wl->nvs->nvs element must be first, in * order to simplify the casting, we assume it is at * the beginning of the wl->nvs structure. @@ -5165,7 +5151,7 @@ static int wl1271_register_hw(struct wl1271 *wl) nic_addr = wl->fuse_nic_addr + 1; } - wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr); + wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr, 2); ret = ieee80211_register_hw(wl->hw); if (ret < 0) { @@ -5195,7 +5181,7 @@ static void wl1271_unregister_hw(struct wl1271 *wl) static const struct ieee80211_iface_limit wlcore_iface_limits[] = { { - .max = 3, + .max = 2, .types = BIT(NL80211_IFTYPE_STATION), }, { @@ -5210,7 +5196,7 @@ static const struct ieee80211_iface_combination wlcore_iface_combinations[] = { { .num_different_channels = 1, - .max_interfaces = 3, + .max_interfaces = 2, .limits = wlcore_iface_limits, .n_limits = ARRAY_SIZE(wlcore_iface_limits), }, @@ -5326,7 +5312,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) #define WL1271_DEFAULT_CHANNEL 0 -struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size) +struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) { struct ieee80211_hw *hw; struct wl1271 *wl; @@ -5406,19 +5392,17 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size) spin_lock_init(&wl->wl_lock); - wl->state = WLCORE_STATE_OFF; + wl->state = WL1271_STATE_OFF; wl->fw_type = WL12XX_FW_TYPE_NONE; mutex_init(&wl->mutex); mutex_init(&wl->flush_mutex); - init_completion(&wl->nvs_loading_complete); - order = get_order(aggr_buf_size); + order = get_order(WL1271_AGGR_BUFFER_SIZE); wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); if (!wl->aggr_buf) { ret = -ENOMEM; goto err_wq; } - wl->aggr_buf_size = aggr_buf_size; wl->dummy_packet = wl12xx_alloc_dummy_packet(wl); if (!wl->dummy_packet) { @@ -5481,7 +5465,8 @@ int wlcore_free_hw(struct wl1271 *wl) device_remove_file(wl->dev, &dev_attr_bt_coex_state); free_page((unsigned long)wl->fwlog); dev_kfree_skb(wl->dummy_packet); - free_pages((unsigned long)wl->aggr_buf, get_order(wl->aggr_buf_size)); + free_pages((unsigned long)wl->aggr_buf, + get_order(WL1271_AGGR_BUFFER_SIZE)); wl1271_debugfs_exit(wl); @@ -5531,32 +5516,17 @@ static irqreturn_t wl12xx_hardirq(int irq, void *cookie) return IRQ_WAKE_THREAD; } -static void wlcore_nvs_cb(const struct firmware *fw, void *context) +int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) { - struct wl1271 *wl = context; - struct platform_device *pdev = wl->pdev; struct wl12xx_platform_data *pdata = pdev->dev.platform_data; unsigned long irqflags; int ret; - if (fw) { - wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); - if (!wl->nvs) { - wl1271_error("Could not allocate nvs data"); - goto out; - } - wl->nvs_len = fw->size; - } else { - wl1271_debug(DEBUG_BOOT, "Could not get nvs file %s", - WL12XX_NVS_NAME); - wl->nvs = NULL; - wl->nvs_len = 0; + if (!wl->ops || !wl->ptable) { + ret = -EINVAL; + goto out_free_hw; } - ret = wl->ops->setup(wl); - if (ret < 0) - goto out_free_nvs; - BUG_ON(wl->num_tx_desc > WLCORE_MAX_TX_DESCRIPTORS); /* adjust some runtime configuration parameters */ @@ -5565,8 +5535,11 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) wl->irq = platform_get_irq(pdev, 0); wl->platform_quirks = pdata->platform_quirks; wl->set_power = pdata->set_power; + wl->dev = &pdev->dev; wl->if_ops = pdata->ops; + platform_set_drvdata(pdev, wl); + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) irqflags = IRQF_TRIGGER_RISING; else @@ -5577,7 +5550,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) pdev->name, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); - goto out_free_nvs; + goto out_free_hw; } #ifdef CONFIG_PM @@ -5636,7 +5609,6 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) goto out_hw_pg_ver; } - wl->initialized = true; goto out; out_hw_pg_ver: @@ -5651,33 +5623,10 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) out_irq: free_irq(wl->irq, wl); -out_free_nvs: - kfree(wl->nvs); +out_free_hw: + wlcore_free_hw(wl); out: - release_firmware(fw); - complete_all(&wl->nvs_loading_complete); -} - -int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) -{ - int ret; - - if (!wl->ops || !wl->ptable) - return -EINVAL; - - wl->dev = &pdev->dev; - wl->pdev = pdev; - platform_set_drvdata(pdev, wl); - - ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - WL12XX_NVS_NAME, &pdev->dev, GFP_KERNEL, - wl, wlcore_nvs_cb); - if (ret < 0) { - wl1271_error("request_firmware_nowait failed: %d", ret); - complete_all(&wl->nvs_loading_complete); - } - return ret; } EXPORT_SYMBOL_GPL(wlcore_probe); @@ -5686,10 +5635,6 @@ int __devexit wlcore_remove(struct platform_device *pdev) { struct wl1271 *wl = platform_get_drvdata(pdev); - wait_for_completion(&wl->nvs_loading_complete); - if (!wl->initialized) - return 0; - if (wl->irq_wake_enabled) { device_init_wakeup(wl->dev, 0); disable_irq_wake(wl->irq); @@ -5720,4 +5665,3 @@ MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck."); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); -MODULE_FIRMWARE(WL12XX_NVS_NAME); diff --git a/trunk/drivers/net/wireless/ti/wlcore/ps.c b/trunk/drivers/net/wireless/ti/wlcore/ps.c index 4d1414a673fb..46d36fd30eba 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/ps.c +++ b/trunk/drivers/net/wireless/ti/wlcore/ps.c @@ -28,7 +28,7 @@ #define WL1271_WAKEUP_TIMEOUT 500 -#define ELP_ENTRY_DELAY 30 +#define ELP_ENTRY_DELAY 5 void wl1271_elp_work(struct work_struct *work) { @@ -44,7 +44,7 @@ void wl1271_elp_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; /* our work might have been already cancelled */ @@ -98,7 +98,11 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) return; } - timeout = ELP_ENTRY_DELAY; + if (wl->conf.conn.forced_ps) + timeout = ELP_ENTRY_DELAY; + else + timeout = wl->conf.conn.dynamic_ps_timeout; + ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, msecs_to_jiffies(timeout)); } diff --git a/trunk/drivers/net/wireless/ti/wlcore/rx.c b/trunk/drivers/net/wireless/ti/wlcore/rx.c index 9ee0ec6fd1db..f55e2f9e7ac5 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/rx.c +++ b/trunk/drivers/net/wireless/ti/wlcore/rx.c @@ -221,7 +221,7 @@ int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) pkt_len = wlcore_rx_get_buf_size(wl, des); align_pkt_len = wlcore_rx_get_align_buf_size(wl, pkt_len); - if (buf_size + align_pkt_len > wl->aggr_buf_size) + if (buf_size + align_pkt_len > WL1271_AGGR_BUFFER_SIZE) break; buf_size += align_pkt_len; rx_counter++; diff --git a/trunk/drivers/net/wireless/ti/wlcore/scan.c b/trunk/drivers/net/wireless/ti/wlcore/scan.c index d00501493dfe..dbeca1bfbb2c 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/scan.c +++ b/trunk/drivers/net/wireless/ti/wlcore/scan.c @@ -46,7 +46,7 @@ void wl1271_scan_complete_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (wl->state == WL1271_STATE_OFF) goto out; if (wl->scan.state == WL1271_SCAN_STATE_IDLE) @@ -184,7 +184,11 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, if (passive) scan_options |= WL1271_SCAN_OPT_PASSIVE; - cmd->params.role_id = wlvif->role_id; + if (wlvif->bss_type == BSS_TYPE_AP_BSS || + test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + cmd->params.role_id = wlvif->role_id; + else + cmd->params.role_id = wlvif->dev_role_id; if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) { ret = -EINVAL; @@ -589,7 +593,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, goto out; } - cmd->role_id = wlvif->role_id; + cmd->role_id = wlvif->dev_role_id; if (!n_match_ssids) { /* No filter, with ssids */ type = SCAN_SSID_FILTER_DISABLED; @@ -679,7 +683,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, if (!cfg) return -ENOMEM; - cfg->role_id = wlvif->role_id; + cfg->role_id = wlvif->dev_role_id; cfg->rssi_threshold = c->rssi_threshold; cfg->snr_threshold = c->snr_threshold; cfg->n_probe_reqs = c->num_probe_reqs; @@ -714,7 +718,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, if (!force_passive && cfg->active[0]) { u8 band = IEEE80211_BAND_2GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, - wlvif->role_id, band, + wlvif->dev_role_id, band, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[band], @@ -728,7 +732,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, if (!force_passive && cfg->active[1]) { u8 band = IEEE80211_BAND_5GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, - wlvif->role_id, band, + wlvif->dev_role_id, band, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[band], @@ -770,7 +774,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (!start) return -ENOMEM; - start->role_id = wlvif->role_id; + start->role_id = wlvif->dev_role_id; start->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, @@ -806,7 +810,7 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) return; } - stop->role_id = wlvif->role_id; + stop->role_id = wlvif->dev_role_id; stop->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, diff --git a/trunk/drivers/net/wireless/ti/wlcore/spi.c b/trunk/drivers/net/wireless/ti/wlcore/spi.c index a519bc3adec1..8da4ed243ebc 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/spi.c +++ b/trunk/drivers/net/wireless/ti/wlcore/spi.c @@ -66,13 +66,7 @@ /* HW limitation: maximum possible chunk size is 4095 bytes */ #define WSPI_MAX_CHUNK_SIZE 4092 -/* - * only support SPI for 12xx - this code should be reworked when 18xx - * support is introduced - */ -#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) - -#define WSPI_MAX_NUM_OF_CHUNKS (SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) +#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) struct wl12xx_spi_glue { struct device *dev; @@ -277,7 +271,7 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, u32 chunk_len; int i; - WARN_ON(len > SPI_AGGR_BUFFER_SIZE); + WARN_ON(len > WL1271_AGGR_BUFFER_SIZE); spi_message_init(&m); memset(t, 0, sizeof(t)); diff --git a/trunk/drivers/net/wireless/ti/wlcore/testmode.c b/trunk/drivers/net/wireless/ti/wlcore/testmode.c index f3442762d884..49e5ee1525c9 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/testmode.c +++ b/trunk/drivers/net/wireless/ti/wlcore/testmode.c @@ -92,7 +92,7 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (wl->state == WL1271_STATE_OFF) { ret = -EINVAL; goto out; } @@ -164,7 +164,7 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (wl->state == WL1271_STATE_OFF) { ret = -EINVAL; goto out; } diff --git a/trunk/drivers/net/wireless/ti/wlcore/tx.c b/trunk/drivers/net/wireless/ti/wlcore/tx.c index a90d3cd09408..1a2f31c289c5 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/tx.c +++ b/trunk/drivers/net/wireless/ti/wlcore/tx.c @@ -193,7 +193,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, int id, ret = -EBUSY, ac; u32 spare_blocks; - if (buf_offset + total_len > wl->aggr_buf_size) + if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) return -EAGAIN; spare_blocks = wlcore_hw_get_spare_blocks(wl, is_gem); @@ -319,12 +319,8 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (hlid == wlvif->ap.global_hlid) rate_idx = wlvif->ap.mgmt_rate_idx; else if (hlid == wlvif->ap.bcast_hlid || - skb->protocol == cpu_to_be16(ETH_P_PAE) || - !ieee80211_is_data(frame_control)) - /* - * send non-data, bcast and EAPOLs using the - * min basic rate - */ + skb->protocol == cpu_to_be16(ETH_P_PAE)) + /* send AP bcast and EAPOLs using the min basic rate */ rate_idx = wlvif->ap.bcast_rate_idx; else rate_idx = wlvif->ap.ucast_rate_idx[ac]; @@ -691,7 +687,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl) int bus_ret = 0; u8 hlid; - if (unlikely(wl->state != WLCORE_STATE_ON)) + if (unlikely(wl->state == WL1271_STATE_OFF)) return 0; while ((skb = wl1271_skb_dequeue(wl, &hlid))) { @@ -1076,54 +1072,39 @@ void wl12xx_tx_reset(struct wl1271 *wl) /* caller must *NOT* hold wl->mutex */ void wl1271_tx_flush(struct wl1271 *wl) { - unsigned long timeout, start_time; + unsigned long timeout; int i; - start_time = jiffies; - timeout = start_time + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); + timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); /* only one flush should be in progress, for consistent queue state */ mutex_lock(&wl->flush_mutex); - mutex_lock(&wl->mutex); - if (wl->tx_frames_cnt == 0 && wl1271_tx_total_queue_count(wl) == 0) { - mutex_unlock(&wl->mutex); - goto out; - } - wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); while (!time_after(jiffies, timeout)) { - wl1271_debug(DEBUG_MAC80211, "flushing tx buffer: %d %d", + mutex_lock(&wl->mutex); + wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", wl->tx_frames_cnt, wl1271_tx_total_queue_count(wl)); - - /* force Tx and give the driver some time to flush data */ - mutex_unlock(&wl->mutex); - if (wl1271_tx_total_queue_count(wl)) - wl1271_tx_work(&wl->tx_work); - msleep(20); - mutex_lock(&wl->mutex); - if ((wl->tx_frames_cnt == 0) && (wl1271_tx_total_queue_count(wl) == 0)) { - wl1271_debug(DEBUG_MAC80211, "tx flush took %d ms", - jiffies_to_msecs(jiffies - start_time)); - goto out_wake; + mutex_unlock(&wl->mutex); + goto out; } + mutex_unlock(&wl->mutex); + msleep(1); } - wl1271_warning("Unable to flush all TX buffers, " - "timed out (timeout %d ms", - WL1271_TX_FLUSH_TIMEOUT / 1000); + wl1271_warning("Unable to flush all TX buffers, timed out."); /* forcibly flush all Tx buffers on our queues */ + mutex_lock(&wl->mutex); for (i = 0; i < WL12XX_MAX_LINKS; i++) wl1271_tx_reset_link_queues(wl, i); - -out_wake: - wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); mutex_unlock(&wl->mutex); + out: + wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); mutex_unlock(&wl->flush_mutex); } EXPORT_SYMBOL_GPL(wl1271_tx_flush); diff --git a/trunk/drivers/net/wireless/ti/wlcore/wlcore.h b/trunk/drivers/net/wireless/ti/wlcore/wlcore.h index 68584aa0f2b0..0ce7a8ebbd46 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/trunk/drivers/net/wireless/ti/wlcore/wlcore.h @@ -31,19 +31,12 @@ /* The maximum number of Tx descriptors in all chip families */ #define WLCORE_MAX_TX_DESCRIPTORS 32 -/* - * We always allocate this number of mac addresses. If we don't - * have enough allocated addresses, the LAA bit is used - */ -#define WLCORE_NUM_MAC_ADDRESSES 3 - /* forward declaration */ struct wl1271_tx_hw_descr; enum wl_rx_buf_align; struct wl1271_rx_descriptor; struct wlcore_ops { - int (*setup)(struct wl1271 *wl); int (*identify_chip)(struct wl1271 *wl); int (*identify_fw)(struct wl1271 *wl); int (*boot)(struct wl1271 *wl); @@ -146,12 +139,10 @@ struct wl1271_stats { }; struct wl1271 { - bool initialized; struct ieee80211_hw *hw; bool mac80211_registered; struct device *dev; - struct platform_device *pdev; void *if_priv; @@ -162,7 +153,7 @@ struct wl1271 { spinlock_t wl_lock; - enum wlcore_state state; + enum wl1271_state state; enum wl12xx_fw_type fw_type; bool plt; enum plt_mode plt_mode; @@ -190,7 +181,7 @@ struct wl1271 { u32 fuse_nic_addr; /* we have up to 2 MAC addresses */ - struct mac_address addresses[WLCORE_NUM_MAC_ADDRESSES]; + struct mac_address addresses[2]; int channel; u8 system_hlid; @@ -199,8 +190,6 @@ struct wl1271 { unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; unsigned long rate_policies_map[ BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)]; - unsigned long klv_templates_map[ - BITS_TO_LONGS(WLCORE_MAX_KLV_TEMPLATES)]; struct list_head wlvif_list; @@ -248,7 +237,6 @@ struct wl1271 { /* Intermediate buffer, used for packet aggregation */ u8 *aggr_buf; - u32 aggr_buf_size; /* Reusable dummy packet template */ struct sk_buff *dummy_packet; @@ -405,18 +393,13 @@ struct wl1271 { /* sleep auth value currently configured to FW */ int sleep_auth; - /* the number of allocated MAC addresses in this chip */ - int num_mac_addr; - /* the minimum FW version required for the driver to work */ unsigned int min_fw_ver[NUM_FW_VER]; - - struct completion nvs_loading_complete; }; int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); int __devexit wlcore_remove(struct platform_device *pdev); -struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size); +struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size); int wlcore_free_hw(struct wl1271 *wl); int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, struct ieee80211_vif *vif, diff --git a/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h b/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h index 6678d4b18611..c0505635bb00 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -66,7 +66,6 @@ #define WLCORE_NUM_BANDS 2 #define WL12XX_MAX_RATE_POLICIES 16 -#define WLCORE_MAX_KLV_TEMPLATES 4 /* Defined by FW as 0. Will not be freed or allocated. */ #define WL12XX_SYSTEM_HLID 0 @@ -84,10 +83,11 @@ #define WL1271_AP_BSS_INDEX 0 #define WL1271_AP_DEF_BEACON_EXP 20 -enum wlcore_state { - WLCORE_STATE_OFF, - WLCORE_STATE_RESTARTING, - WLCORE_STATE_ON, +#define WL1271_AGGR_BUFFER_SIZE (5 * PAGE_SIZE) + +enum wl1271_state { + WL1271_STATE_OFF, + WL1271_STATE_ON, }; enum wl12xx_fw_type { @@ -124,7 +124,6 @@ struct wl1271_chip { u32 id; char fw_ver_str[ETHTOOL_BUSINFO_LEN]; unsigned int fw_ver[NUM_FW_VER]; - char phy_fw_ver_str[ETHTOOL_BUSINFO_LEN]; }; #define NUM_TX_QUEUES 4 @@ -338,8 +337,6 @@ struct wl12xx_vif { u8 ap_rate_idx; u8 p2p_rate_idx; - u8 klv_template_id; - bool qos; } sta; struct { diff --git a/trunk/drivers/nfc/Kconfig b/trunk/drivers/nfc/Kconfig index ec857676c39f..3b20b73ee649 100644 --- a/trunk/drivers/nfc/Kconfig +++ b/trunk/drivers/nfc/Kconfig @@ -5,9 +5,21 @@ menu "Near Field Communication (NFC) devices" depends on NFC +config PN544_NFC + tristate "PN544 NFC driver" + depends on I2C + select CRC_CCITT + default n + ---help--- + Say yes if you want PN544 Near Field Communication driver. + This is for i2c connected version. If unsure, say N here. + + To compile this driver as a module, choose m here. The module will + be called pn544. + config PN544_HCI_NFC tristate "HCI PN544 NFC driver" - depends on I2C && NFC_HCI && NFC_SHDLC + depends on I2C && NFC_SHDLC select CRC_CCITT default n ---help--- diff --git a/trunk/drivers/nfc/Makefile b/trunk/drivers/nfc/Makefile index bf05831fdf09..473e44cef612 100644 --- a/trunk/drivers/nfc/Makefile +++ b/trunk/drivers/nfc/Makefile @@ -2,6 +2,7 @@ # Makefile for nfc devices # +obj-$(CONFIG_PN544_NFC) += pn544.o obj-$(CONFIG_PN544_HCI_NFC) += pn544_hci.o obj-$(CONFIG_NFC_PN533) += pn533.o obj-$(CONFIG_NFC_WILINK) += nfcwilink.o diff --git a/trunk/drivers/nfc/nfcwilink.c b/trunk/drivers/nfc/nfcwilink.c index 50b1ee41afc6..e7fd4938f9bc 100644 --- a/trunk/drivers/nfc/nfcwilink.c +++ b/trunk/drivers/nfc/nfcwilink.c @@ -352,6 +352,8 @@ static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) struct nfcwilink *drv = priv_data; int rc; + nfc_dev_dbg(&drv->pdev->dev, "receive entry, len %d", skb->len); + if (!skb) return -EFAULT; @@ -360,8 +362,6 @@ static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) return -EFAULT; } - nfc_dev_dbg(&drv->pdev->dev, "receive entry, len %d", skb->len); - /* strip the ST header (apart for the chnl byte, which is not received in the hdr) */ skb_pull(skb, (NFCWILINK_HDR_LEN-1)); @@ -604,7 +604,21 @@ static struct platform_driver nfcwilink_driver = { }, }; -module_platform_driver(nfcwilink_driver); +/* ------- Module Init/Exit interfaces ------ */ +static int __init nfcwilink_init(void) +{ + printk(KERN_INFO "NFC Driver for TI WiLink"); + + return platform_driver_register(&nfcwilink_driver); +} + +static void __exit nfcwilink_exit(void) +{ + platform_driver_unregister(&nfcwilink_driver); +} + +module_init(nfcwilink_init); +module_exit(nfcwilink_exit); /* ------ Module Info ------ */ diff --git a/trunk/drivers/nfc/pn533.c b/trunk/drivers/nfc/pn533.c index 97c440a8cd61..d606f52fec84 100644 --- a/trunk/drivers/nfc/pn533.c +++ b/trunk/drivers/nfc/pn533.c @@ -356,7 +356,6 @@ struct pn533 { struct workqueue_struct *wq; struct work_struct cmd_work; - struct work_struct cmd_complete_work; struct work_struct poll_work; struct work_struct mi_work; struct work_struct tg_work; @@ -384,19 +383,6 @@ struct pn533 { u8 tgt_mode; u32 device_type; - - struct list_head cmd_queue; - u8 cmd_pending; -}; - -struct pn533_cmd { - struct list_head queue; - struct pn533_frame *out_frame; - struct pn533_frame *in_frame; - int in_frame_len; - pn533_cmd_complete_t cmd_complete; - void *arg; - gfp_t flags; }; struct pn533_frame { @@ -501,7 +487,7 @@ static bool pn533_rx_frame_is_cmd_response(struct pn533_frame *frame, u8 cmd) static void pn533_wq_cmd_complete(struct work_struct *work) { - struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work); + struct pn533 *dev = container_of(work, struct pn533, cmd_work); struct pn533_frame *in_frame; int rc; @@ -516,7 +502,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work) PN533_FRAME_CMD_PARAMS_LEN(in_frame)); if (rc != -EINPROGRESS) - queue_work(dev->wq, &dev->cmd_work); + mutex_unlock(&dev->cmd_lock); } static void pn533_recv_response(struct urb *urb) @@ -564,7 +550,7 @@ static void pn533_recv_response(struct urb *urb) dev->wq_in_frame = in_frame; sched_wq: - queue_work(dev->wq, &dev->cmd_complete_work); + queue_work(dev->wq, &dev->cmd_work); } static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags) @@ -620,7 +606,7 @@ static void pn533_recv_ack(struct urb *urb) sched_wq: dev->wq_in_frame = NULL; - queue_work(dev->wq, &dev->cmd_complete_work); + queue_work(dev->wq, &dev->cmd_work); } static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags) @@ -683,31 +669,6 @@ static int __pn533_send_cmd_frame_async(struct pn533 *dev, return rc; } -static void pn533_wq_cmd(struct work_struct *work) -{ - struct pn533 *dev = container_of(work, struct pn533, cmd_work); - struct pn533_cmd *cmd; - - mutex_lock(&dev->cmd_lock); - - if (list_empty(&dev->cmd_queue)) { - dev->cmd_pending = 0; - mutex_unlock(&dev->cmd_lock); - return; - } - - cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue); - - mutex_unlock(&dev->cmd_lock); - - __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, - cmd->in_frame_len, cmd->cmd_complete, - cmd->arg, cmd->flags); - - list_del(&cmd->queue); - kfree(cmd); -} - static int pn533_send_cmd_frame_async(struct pn533 *dev, struct pn533_frame *out_frame, struct pn533_frame *in_frame, @@ -715,44 +676,21 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, pn533_cmd_complete_t cmd_complete, void *arg, gfp_t flags) { - struct pn533_cmd *cmd; - int rc = 0; + int rc; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - mutex_lock(&dev->cmd_lock); - - if (!dev->cmd_pending) { - rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, - in_frame_len, cmd_complete, - arg, flags); - if (!rc) - dev->cmd_pending = 1; - - goto unlock; - } - - nfc_dev_dbg(&dev->interface->dev, "%s Queueing command", __func__); - - cmd = kzalloc(sizeof(struct pn533_cmd), flags); - if (!cmd) { - rc = -ENOMEM; - goto unlock; - } - - INIT_LIST_HEAD(&cmd->queue); - cmd->out_frame = out_frame; - cmd->in_frame = in_frame; - cmd->in_frame_len = in_frame_len; - cmd->cmd_complete = cmd_complete; - cmd->arg = arg; - cmd->flags = flags; + if (!mutex_trylock(&dev->cmd_lock)) + return -EBUSY; - list_add_tail(&cmd->queue, &dev->cmd_queue); + rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, + in_frame_len, cmd_complete, arg, flags); + if (rc) + goto error; -unlock: + return 0; +error: mutex_unlock(&dev->cmd_lock); - return rc; } @@ -1367,6 +1305,8 @@ static void pn533_listen_mode_timer(unsigned long data) dev->cancel_listen = 1; + mutex_unlock(&dev->cmd_lock); + pn533_poll_next_mod(dev); queue_work(dev->wq, &dev->poll_work); @@ -2191,7 +2131,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) kfree(arg); - queue_work(dev->wq, &dev->cmd_work); + mutex_unlock(&dev->cmd_lock); } static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, @@ -2390,12 +2330,13 @@ static int pn533_probe(struct usb_interface *interface, NULL, 0, pn533_send_complete, dev); - INIT_WORK(&dev->cmd_work, pn533_wq_cmd); - INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete); + INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete); INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); INIT_WORK(&dev->poll_work, pn533_wq_poll); - dev->wq = alloc_ordered_workqueue("pn533", 0); + dev->wq = alloc_workqueue("pn533", + WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, + 1); if (dev->wq == NULL) goto error; @@ -2405,8 +2346,6 @@ static int pn533_probe(struct usb_interface *interface, skb_queue_head_init(&dev->resp_q); - INIT_LIST_HEAD(&dev->cmd_queue); - usb_set_intfdata(interface, dev); pn533_tx_frame_init(dev->out_frame, PN533_CMD_GET_FIRMWARE_VERSION); @@ -2478,7 +2417,6 @@ static int pn533_probe(struct usb_interface *interface, static void pn533_disconnect(struct usb_interface *interface) { struct pn533 *dev; - struct pn533_cmd *cmd, *n; dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); @@ -2495,11 +2433,6 @@ static void pn533_disconnect(struct usb_interface *interface) del_timer(&dev->listen_timer); - list_for_each_entry_safe(cmd, n, &dev->cmd_queue, queue) { - list_del(&cmd->queue); - kfree(cmd); - } - kfree(dev->in_frame); usb_free_urb(dev->in_urb); kfree(dev->out_frame); diff --git a/trunk/drivers/nfc/pn544.c b/trunk/drivers/nfc/pn544.c new file mode 100644 index 000000000000..724f65d8f9e4 --- /dev/null +++ b/trunk/drivers/nfc/pn544.c @@ -0,0 +1,893 @@ +/* + * Driver for the PN544 NFC chip. + * + * Copyright (C) Nokia Corporation + * + * Author: Jari Vanhala + * Contact: Matti Aaltonen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for TCGETS */ +#include + +#define DRIVER_CARD "PN544 NFC" +#define DRIVER_DESC "NFC driver for PN544" + +static struct i2c_device_id pn544_id_table[] = { + { PN544_DRIVER_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pn544_id_table); + +#define HCI_MODE 0 +#define FW_MODE 1 + +enum pn544_state { + PN544_ST_COLD, + PN544_ST_FW_READY, + PN544_ST_READY, +}; + +enum pn544_irq { + PN544_NONE, + PN544_INT, +}; + +struct pn544_info { + struct miscdevice miscdev; + struct i2c_client *i2c_dev; + struct regulator_bulk_data regs[3]; + + enum pn544_state state; + wait_queue_head_t read_wait; + loff_t read_offset; + enum pn544_irq read_irq; + struct mutex read_mutex; /* Serialize read_irq access */ + struct mutex mutex; /* Serialize info struct access */ + u8 *buf; + size_t buflen; +}; + +static const char reg_vdd_io[] = "Vdd_IO"; +static const char reg_vbat[] = "VBat"; +static const char reg_vsim[] = "VSim"; + +/* sysfs interface */ +static ssize_t pn544_test(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pn544_info *info = dev_get_drvdata(dev); + struct i2c_client *client = info->i2c_dev; + struct pn544_nfc_platform_data *pdata = client->dev.platform_data; + + return snprintf(buf, PAGE_SIZE, "%d\n", pdata->test()); +} + +static int pn544_enable(struct pn544_info *info, int mode) +{ + struct pn544_nfc_platform_data *pdata; + struct i2c_client *client = info->i2c_dev; + + int r; + + r = regulator_bulk_enable(ARRAY_SIZE(info->regs), info->regs); + if (r < 0) + return r; + + pdata = client->dev.platform_data; + info->read_irq = PN544_NONE; + if (pdata->enable) + pdata->enable(mode); + + if (mode) { + info->state = PN544_ST_FW_READY; + dev_dbg(&client->dev, "now in FW-mode\n"); + } else { + info->state = PN544_ST_READY; + dev_dbg(&client->dev, "now in HCI-mode\n"); + } + + usleep_range(10000, 15000); + + return 0; +} + +static void pn544_disable(struct pn544_info *info) +{ + struct pn544_nfc_platform_data *pdata; + struct i2c_client *client = info->i2c_dev; + + pdata = client->dev.platform_data; + if (pdata->disable) + pdata->disable(); + + info->state = PN544_ST_COLD; + + dev_dbg(&client->dev, "Now in OFF-mode\n"); + + msleep(PN544_RESETVEN_TIME); + + info->read_irq = PN544_NONE; + regulator_bulk_disable(ARRAY_SIZE(info->regs), info->regs); +} + +static int check_crc(u8 *buf, int buflen) +{ + u8 len; + u16 crc; + + len = buf[0] + 1; + if (len < 4 || len != buflen || len > PN544_MSG_MAX_SIZE) { + pr_err(PN544_DRIVER_NAME + ": CRC; corrupt packet len %u (%d)\n", len, buflen); + print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, + 16, 2, buf, buflen, false); + return -EPERM; + } + crc = crc_ccitt(0xffff, buf, len - 2); + crc = ~crc; + + if (buf[len-2] != (crc & 0xff) || buf[len-1] != (crc >> 8)) { + pr_err(PN544_DRIVER_NAME ": CRC error 0x%x != 0x%x 0x%x\n", + crc, buf[len-1], buf[len-2]); + + print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, + 16, 2, buf, buflen, false); + return -EPERM; + } + return 0; +} + +static int pn544_i2c_write(struct i2c_client *client, u8 *buf, int len) +{ + int r; + + if (len < 4 || len != (buf[0] + 1)) { + dev_err(&client->dev, "%s: Illegal message length: %d\n", + __func__, len); + return -EINVAL; + } + + if (check_crc(buf, len)) + return -EINVAL; + + usleep_range(3000, 6000); + + r = i2c_master_send(client, buf, len); + dev_dbg(&client->dev, "send: %d\n", r); + + if (r == -EREMOTEIO) { /* Retry, chip was in standby */ + usleep_range(6000, 10000); + r = i2c_master_send(client, buf, len); + dev_dbg(&client->dev, "send2: %d\n", r); + } + + if (r != len) + return -EREMOTEIO; + + return r; +} + +static int pn544_i2c_read(struct i2c_client *client, u8 *buf, int buflen) +{ + int r; + u8 len; + + /* + * You could read a packet in one go, but then you'd need to read + * max size and rest would be 0xff fill, so we do split reads. + */ + r = i2c_master_recv(client, &len, 1); + dev_dbg(&client->dev, "recv1: %d\n", r); + + if (r != 1) + return -EREMOTEIO; + + if (len < PN544_LLC_HCI_OVERHEAD) + len = PN544_LLC_HCI_OVERHEAD; + else if (len > (PN544_MSG_MAX_SIZE - 1)) + len = PN544_MSG_MAX_SIZE - 1; + + if (1 + len > buflen) /* len+(data+crc16) */ + return -EMSGSIZE; + + buf[0] = len; + + r = i2c_master_recv(client, buf + 1, len); + dev_dbg(&client->dev, "recv2: %d\n", r); + + if (r != len) + return -EREMOTEIO; + + usleep_range(3000, 6000); + + return r + 1; +} + +static int pn544_fw_write(struct i2c_client *client, u8 *buf, int len) +{ + int r; + + dev_dbg(&client->dev, "%s\n", __func__); + + if (len < PN544_FW_HEADER_SIZE || + (PN544_FW_HEADER_SIZE + (buf[1] << 8) + buf[2]) != len) + return -EINVAL; + + r = i2c_master_send(client, buf, len); + dev_dbg(&client->dev, "fw send: %d\n", r); + + if (r == -EREMOTEIO) { /* Retry, chip was in standby */ + usleep_range(6000, 10000); + r = i2c_master_send(client, buf, len); + dev_dbg(&client->dev, "fw send2: %d\n", r); + } + + if (r != len) + return -EREMOTEIO; + + return r; +} + +static int pn544_fw_read(struct i2c_client *client, u8 *buf, int buflen) +{ + int r, len; + + if (buflen < PN544_FW_HEADER_SIZE) + return -EINVAL; + + r = i2c_master_recv(client, buf, PN544_FW_HEADER_SIZE); + dev_dbg(&client->dev, "FW recv1: %d\n", r); + + if (r < 0) + return r; + + if (r < PN544_FW_HEADER_SIZE) + return -EINVAL; + + len = (buf[1] << 8) + buf[2]; + if (len == 0) /* just header, no additional data */ + return r; + + if (len > buflen - PN544_FW_HEADER_SIZE) + return -EMSGSIZE; + + r = i2c_master_recv(client, buf + PN544_FW_HEADER_SIZE, len); + dev_dbg(&client->dev, "fw recv2: %d\n", r); + + if (r != len) + return -EINVAL; + + return r + PN544_FW_HEADER_SIZE; +} + +static irqreturn_t pn544_irq_thread_fn(int irq, void *dev_id) +{ + struct pn544_info *info = dev_id; + struct i2c_client *client = info->i2c_dev; + + BUG_ON(!info); + BUG_ON(irq != info->i2c_dev->irq); + + dev_dbg(&client->dev, "IRQ\n"); + + mutex_lock(&info->read_mutex); + info->read_irq = PN544_INT; + mutex_unlock(&info->read_mutex); + + wake_up_interruptible(&info->read_wait); + + return IRQ_HANDLED; +} + +static enum pn544_irq pn544_irq_state(struct pn544_info *info) +{ + enum pn544_irq irq; + + mutex_lock(&info->read_mutex); + irq = info->read_irq; + mutex_unlock(&info->read_mutex); + /* + * XXX: should we check GPIO-line status directly? + * return pdata->irq_status() ? PN544_INT : PN544_NONE; + */ + + return irq; +} + +static ssize_t pn544_read(struct file *file, char __user *buf, + size_t count, loff_t *offset) +{ + struct pn544_info *info = container_of(file->private_data, + struct pn544_info, miscdev); + struct i2c_client *client = info->i2c_dev; + enum pn544_irq irq; + size_t len; + int r = 0; + + dev_dbg(&client->dev, "%s: info: %p, count: %zu\n", __func__, + info, count); + + mutex_lock(&info->mutex); + + if (info->state == PN544_ST_COLD) { + r = -ENODEV; + goto out; + } + + irq = pn544_irq_state(info); + if (irq == PN544_NONE) { + if (file->f_flags & O_NONBLOCK) { + r = -EAGAIN; + goto out; + } + + if (wait_event_interruptible(info->read_wait, + (info->read_irq == PN544_INT))) { + r = -ERESTARTSYS; + goto out; + } + } + + if (info->state == PN544_ST_FW_READY) { + len = min(count, info->buflen); + + mutex_lock(&info->read_mutex); + r = pn544_fw_read(info->i2c_dev, info->buf, len); + info->read_irq = PN544_NONE; + mutex_unlock(&info->read_mutex); + + if (r < 0) { + dev_err(&info->i2c_dev->dev, "FW read failed: %d\n", r); + goto out; + } + + print_hex_dump(KERN_DEBUG, "FW read: ", DUMP_PREFIX_NONE, + 16, 2, info->buf, r, false); + + *offset += r; + if (copy_to_user(buf, info->buf, r)) { + r = -EFAULT; + goto out; + } + } else { + len = min(count, info->buflen); + + mutex_lock(&info->read_mutex); + r = pn544_i2c_read(info->i2c_dev, info->buf, len); + info->read_irq = PN544_NONE; + mutex_unlock(&info->read_mutex); + + if (r < 0) { + dev_err(&info->i2c_dev->dev, "read failed (%d)\n", r); + goto out; + } + print_hex_dump(KERN_DEBUG, "read: ", DUMP_PREFIX_NONE, + 16, 2, info->buf, r, false); + + *offset += r; + if (copy_to_user(buf, info->buf, r)) { + r = -EFAULT; + goto out; + } + } + +out: + mutex_unlock(&info->mutex); + + return r; +} + +static unsigned int pn544_poll(struct file *file, poll_table *wait) +{ + struct pn544_info *info = container_of(file->private_data, + struct pn544_info, miscdev); + struct i2c_client *client = info->i2c_dev; + int r = 0; + + dev_dbg(&client->dev, "%s: info: %p\n", __func__, info); + + mutex_lock(&info->mutex); + + if (info->state == PN544_ST_COLD) { + r = -ENODEV; + goto out; + } + + poll_wait(file, &info->read_wait, wait); + + if (pn544_irq_state(info) == PN544_INT) { + r = POLLIN | POLLRDNORM; + goto out; + } +out: + mutex_unlock(&info->mutex); + + return r; +} + +static ssize_t pn544_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct pn544_info *info = container_of(file->private_data, + struct pn544_info, miscdev); + struct i2c_client *client = info->i2c_dev; + ssize_t len; + int r; + + dev_dbg(&client->dev, "%s: info: %p, count %zu\n", __func__, + info, count); + + mutex_lock(&info->mutex); + + if (info->state == PN544_ST_COLD) { + r = -ENODEV; + goto out; + } + + /* + * XXX: should we detect rset-writes and clean possible + * read_irq state + */ + if (info->state == PN544_ST_FW_READY) { + size_t fw_len; + + if (count < PN544_FW_HEADER_SIZE) { + r = -EINVAL; + goto out; + } + + len = min(count, info->buflen); + if (copy_from_user(info->buf, buf, len)) { + r = -EFAULT; + goto out; + } + + print_hex_dump(KERN_DEBUG, "FW write: ", DUMP_PREFIX_NONE, + 16, 2, info->buf, len, false); + + fw_len = PN544_FW_HEADER_SIZE + (info->buf[1] << 8) + + info->buf[2]; + + if (len > fw_len) /* 1 msg at a time */ + len = fw_len; + + r = pn544_fw_write(info->i2c_dev, info->buf, len); + } else { + if (count < PN544_LLC_MIN_SIZE) { + r = -EINVAL; + goto out; + } + + len = min(count, info->buflen); + if (copy_from_user(info->buf, buf, len)) { + r = -EFAULT; + goto out; + } + + print_hex_dump(KERN_DEBUG, "write: ", DUMP_PREFIX_NONE, + 16, 2, info->buf, len, false); + + if (len > (info->buf[0] + 1)) /* 1 msg at a time */ + len = info->buf[0] + 1; + + r = pn544_i2c_write(info->i2c_dev, info->buf, len); + } +out: + mutex_unlock(&info->mutex); + + return r; + +} + +static long pn544_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct pn544_info *info = container_of(file->private_data, + struct pn544_info, miscdev); + struct i2c_client *client = info->i2c_dev; + struct pn544_nfc_platform_data *pdata; + unsigned int val; + int r = 0; + + dev_dbg(&client->dev, "%s: info: %p, cmd: 0x%x\n", __func__, info, cmd); + + mutex_lock(&info->mutex); + + if (info->state == PN544_ST_COLD) { + r = -ENODEV; + goto out; + } + + pdata = info->i2c_dev->dev.platform_data; + switch (cmd) { + case PN544_GET_FW_MODE: + dev_dbg(&client->dev, "%s: PN544_GET_FW_MODE\n", __func__); + + val = (info->state == PN544_ST_FW_READY); + if (copy_to_user((void __user *)arg, &val, sizeof(val))) { + r = -EFAULT; + goto out; + } + + break; + + case PN544_SET_FW_MODE: + dev_dbg(&client->dev, "%s: PN544_SET_FW_MODE\n", __func__); + + if (copy_from_user(&val, (void __user *)arg, sizeof(val))) { + r = -EFAULT; + goto out; + } + + if (val) { + if (info->state == PN544_ST_FW_READY) + break; + + pn544_disable(info); + r = pn544_enable(info, FW_MODE); + if (r < 0) + goto out; + } else { + if (info->state == PN544_ST_READY) + break; + pn544_disable(info); + r = pn544_enable(info, HCI_MODE); + if (r < 0) + goto out; + } + file->f_pos = info->read_offset; + break; + + case TCGETS: + dev_dbg(&client->dev, "%s: TCGETS\n", __func__); + + r = -ENOIOCTLCMD; + break; + + default: + dev_err(&client->dev, "Unknown ioctl 0x%x\n", cmd); + r = -ENOIOCTLCMD; + break; + } + +out: + mutex_unlock(&info->mutex); + + return r; +} + +static int pn544_open(struct inode *inode, struct file *file) +{ + struct pn544_info *info = container_of(file->private_data, + struct pn544_info, miscdev); + struct i2c_client *client = info->i2c_dev; + int r = 0; + + dev_dbg(&client->dev, "%s: info: %p, client %p\n", __func__, + info, info->i2c_dev); + + mutex_lock(&info->mutex); + + /* + * Only 1 at a time. + * XXX: maybe user (counter) would work better + */ + if (info->state != PN544_ST_COLD) { + r = -EBUSY; + goto out; + } + + file->f_pos = info->read_offset; + r = pn544_enable(info, HCI_MODE); + +out: + mutex_unlock(&info->mutex); + return r; +} + +static int pn544_close(struct inode *inode, struct file *file) +{ + struct pn544_info *info = container_of(file->private_data, + struct pn544_info, miscdev); + struct i2c_client *client = info->i2c_dev; + + dev_dbg(&client->dev, "%s: info: %p, client %p\n", + __func__, info, info->i2c_dev); + + mutex_lock(&info->mutex); + pn544_disable(info); + mutex_unlock(&info->mutex); + + return 0; +} + +static const struct file_operations pn544_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = pn544_read, + .write = pn544_write, + .poll = pn544_poll, + .open = pn544_open, + .release = pn544_close, + .unlocked_ioctl = pn544_ioctl, +}; + +#ifdef CONFIG_PM +static int pn544_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct pn544_info *info; + int r = 0; + + dev_info(&client->dev, "***\n%s: client %p\n***\n", __func__, client); + + info = i2c_get_clientdata(client); + dev_info(&client->dev, "%s: info: %p, client %p\n", __func__, + info, client); + + mutex_lock(&info->mutex); + + switch (info->state) { + case PN544_ST_FW_READY: + /* Do not suspend while upgrading FW, please! */ + r = -EPERM; + break; + + case PN544_ST_READY: + /* + * CHECK: Device should be in standby-mode. No way to check? + * Allowing low power mode for the regulator is potentially + * dangerous if pn544 does not go to suspension. + */ + break; + + case PN544_ST_COLD: + break; + }; + + mutex_unlock(&info->mutex); + return r; +} + +static int pn544_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct pn544_info *info = i2c_get_clientdata(client); + int r = 0; + + dev_dbg(&client->dev, "%s: info: %p, client %p\n", __func__, + info, client); + + mutex_lock(&info->mutex); + + switch (info->state) { + case PN544_ST_READY: + /* + * CHECK: If regulator low power mode is allowed in + * pn544_suspend, we should go back to normal mode + * here. + */ + break; + + case PN544_ST_COLD: + break; + + case PN544_ST_FW_READY: + break; + }; + + mutex_unlock(&info->mutex); + + return r; +} + +static SIMPLE_DEV_PM_OPS(pn544_pm_ops, pn544_suspend, pn544_resume); +#endif + +static struct device_attribute pn544_attr = + __ATTR(nfc_test, S_IRUGO, pn544_test, NULL); + +static int __devinit pn544_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pn544_info *info; + struct pn544_nfc_platform_data *pdata; + int r = 0; + + dev_dbg(&client->dev, "%s\n", __func__); + dev_dbg(&client->dev, "IRQ: %d\n", client->irq); + + /* private data allocation */ + info = kzalloc(sizeof(struct pn544_info), GFP_KERNEL); + if (!info) { + dev_err(&client->dev, + "Cannot allocate memory for pn544_info.\n"); + r = -ENOMEM; + goto err_info_alloc; + } + + info->buflen = max(PN544_MSG_MAX_SIZE, PN544_MAX_I2C_TRANSFER); + info->buf = kzalloc(info->buflen, GFP_KERNEL); + if (!info->buf) { + dev_err(&client->dev, + "Cannot allocate memory for pn544_info->buf.\n"); + r = -ENOMEM; + goto err_buf_alloc; + } + + info->regs[0].supply = reg_vdd_io; + info->regs[1].supply = reg_vbat; + info->regs[2].supply = reg_vsim; + r = regulator_bulk_get(&client->dev, ARRAY_SIZE(info->regs), + info->regs); + if (r < 0) + goto err_kmalloc; + + info->i2c_dev = client; + info->state = PN544_ST_COLD; + info->read_irq = PN544_NONE; + mutex_init(&info->read_mutex); + mutex_init(&info->mutex); + init_waitqueue_head(&info->read_wait); + i2c_set_clientdata(client, info); + pdata = client->dev.platform_data; + if (!pdata) { + dev_err(&client->dev, "No platform data\n"); + r = -EINVAL; + goto err_reg; + } + + if (!pdata->request_resources) { + dev_err(&client->dev, "request_resources() missing\n"); + r = -EINVAL; + goto err_reg; + } + + r = pdata->request_resources(client); + if (r) { + dev_err(&client->dev, "Cannot get platform resources\n"); + goto err_reg; + } + + r = request_threaded_irq(client->irq, NULL, pn544_irq_thread_fn, + IRQF_TRIGGER_RISING, PN544_DRIVER_NAME, + info); + if (r < 0) { + dev_err(&client->dev, "Unable to register IRQ handler\n"); + goto err_res; + } + + /* If we don't have the test we don't need the sysfs file */ + if (pdata->test) { + r = device_create_file(&client->dev, &pn544_attr); + if (r) { + dev_err(&client->dev, + "sysfs registration failed, error %d\n", r); + goto err_irq; + } + } + + info->miscdev.minor = MISC_DYNAMIC_MINOR; + info->miscdev.name = PN544_DRIVER_NAME; + info->miscdev.fops = &pn544_fops; + info->miscdev.parent = &client->dev; + r = misc_register(&info->miscdev); + if (r < 0) { + dev_err(&client->dev, "Device registration failed\n"); + goto err_sysfs; + } + + dev_dbg(&client->dev, "%s: info: %p, pdata %p, client %p\n", + __func__, info, pdata, client); + + return 0; + +err_sysfs: + if (pdata->test) + device_remove_file(&client->dev, &pn544_attr); +err_irq: + free_irq(client->irq, info); +err_res: + if (pdata->free_resources) + pdata->free_resources(); +err_reg: + regulator_bulk_free(ARRAY_SIZE(info->regs), info->regs); +err_kmalloc: + kfree(info->buf); +err_buf_alloc: + kfree(info); +err_info_alloc: + return r; +} + +static __devexit int pn544_remove(struct i2c_client *client) +{ + struct pn544_info *info = i2c_get_clientdata(client); + struct pn544_nfc_platform_data *pdata = client->dev.platform_data; + + dev_dbg(&client->dev, "%s\n", __func__); + + misc_deregister(&info->miscdev); + if (pdata->test) + device_remove_file(&client->dev, &pn544_attr); + + if (info->state != PN544_ST_COLD) { + if (pdata->disable) + pdata->disable(); + + info->read_irq = PN544_NONE; + } + + free_irq(client->irq, info); + if (pdata->free_resources) + pdata->free_resources(); + + regulator_bulk_free(ARRAY_SIZE(info->regs), info->regs); + kfree(info->buf); + kfree(info); + + return 0; +} + +static struct i2c_driver pn544_driver = { + .driver = { + .name = PN544_DRIVER_NAME, +#ifdef CONFIG_PM + .pm = &pn544_pm_ops, +#endif + }, + .probe = pn544_probe, + .id_table = pn544_id_table, + .remove = __devexit_p(pn544_remove), +}; + +static int __init pn544_init(void) +{ + int r; + + pr_debug(DRIVER_DESC ": %s\n", __func__); + + r = i2c_add_driver(&pn544_driver); + if (r) { + pr_err(PN544_DRIVER_NAME ": driver registration failed\n"); + return r; + } + + return 0; +} + +static void __exit pn544_exit(void) +{ + i2c_del_driver(&pn544_driver); + pr_info(DRIVER_DESC ", Exiting.\n"); +} + +module_init(pn544_init); +module_exit(pn544_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/trunk/drivers/nfc/pn544_hci.c b/trunk/drivers/nfc/pn544_hci.c index c9c8570273ab..aa71807189ba 100644 --- a/trunk/drivers/nfc/pn544_hci.c +++ b/trunk/drivers/nfc/pn544_hci.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include @@ -128,12 +128,10 @@ static struct nfc_hci_gate pn544_gates[] = { /* Largest headroom needed for outgoing custom commands */ #define PN544_CMDS_HEADROOM 2 -#define PN544_FRAME_HEADROOM 1 -#define PN544_FRAME_TAILROOM 2 struct pn544_hci_info { struct i2c_client *i2c_dev; - struct nfc_hci_dev *hdev; + struct nfc_shdlc *shdlc; enum pn544_state state; @@ -148,9 +146,6 @@ struct pn544_hci_info { * < 0 if hardware error occured (e.g. i2c err) * and prevents normal operation. */ - int async_cb_type; - data_exchange_cb_t async_cb; - void *async_cb_context; }; static void pn544_hci_platform_init(struct pn544_hci_info *info) @@ -235,12 +230,8 @@ static int pn544_hci_i2c_write(struct i2c_client *client, u8 *buf, int len) r = i2c_master_send(client, buf, len); } - if (r >= 0) { - if (r != len) - return -EREMOTEIO; - else - return 0; - } + if (r >= 0 && r != len) + r = -EREMOTEIO; return r; } @@ -350,16 +341,13 @@ static int pn544_hci_i2c_read(struct i2c_client *client, struct sk_buff **skb) static irqreturn_t pn544_hci_irq_thread_fn(int irq, void *dev_id) { struct pn544_hci_info *info = dev_id; - struct i2c_client *client; + struct i2c_client *client = info->i2c_dev; struct sk_buff *skb = NULL; int r; - if (!info || irq != info->i2c_dev->irq) { - WARN_ON_ONCE(1); - return IRQ_NONE; - } + BUG_ON(!info); + BUG_ON(irq != info->i2c_dev->irq); - client = info->i2c_dev; dev_dbg(&client->dev, "IRQ\n"); if (info->hard_fault != 0) @@ -369,21 +357,21 @@ static irqreturn_t pn544_hci_irq_thread_fn(int irq, void *dev_id) if (r == -EREMOTEIO) { info->hard_fault = r; - nfc_hci_recv_frame(info->hdev, NULL); + nfc_shdlc_recv_frame(info->shdlc, NULL); return IRQ_HANDLED; } else if ((r == -ENOMEM) || (r == -EBADMSG)) { return IRQ_HANDLED; } - nfc_hci_recv_frame(info->hdev, skb); + nfc_shdlc_recv_frame(info->shdlc, skb); return IRQ_HANDLED; } -static int pn544_hci_open(struct nfc_hci_dev *hdev) +static int pn544_hci_open(struct nfc_shdlc *shdlc) { - struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); + struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc); int r = 0; mutex_lock(&info->info_lock); @@ -403,9 +391,9 @@ static int pn544_hci_open(struct nfc_hci_dev *hdev) return r; } -static void pn544_hci_close(struct nfc_hci_dev *hdev) +static void pn544_hci_close(struct nfc_shdlc *shdlc) { - struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); + struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc); mutex_lock(&info->info_lock); @@ -420,8 +408,9 @@ static void pn544_hci_close(struct nfc_hci_dev *hdev) mutex_unlock(&info->info_lock); } -static int pn544_hci_ready(struct nfc_hci_dev *hdev) +static int pn544_hci_ready(struct nfc_shdlc *shdlc) { + struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); struct sk_buff *skb; static struct hw_config { u8 adr[2]; @@ -587,45 +576,21 @@ static int pn544_hci_ready(struct nfc_hci_dev *hdev) return 0; } -static void pn544_hci_add_len_crc(struct sk_buff *skb) +static int pn544_hci_xmit(struct nfc_shdlc *shdlc, struct sk_buff *skb) { - u16 crc; - int len; - - len = skb->len + 2; - *skb_push(skb, 1) = len; - - crc = crc_ccitt(0xffff, skb->data, skb->len); - crc = ~crc; - *skb_put(skb, 1) = crc & 0xff; - *skb_put(skb, 1) = crc >> 8; -} - -static void pn544_hci_remove_len_crc(struct sk_buff *skb) -{ - skb_pull(skb, PN544_FRAME_HEADROOM); - skb_trim(skb, PN544_FRAME_TAILROOM); -} - -static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) -{ - struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); + struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc); struct i2c_client *client = info->i2c_dev; - int r; if (info->hard_fault != 0) return info->hard_fault; - pn544_hci_add_len_crc(skb); - r = pn544_hci_i2c_write(client, skb->data, skb->len); - pn544_hci_remove_len_crc(skb); - - return r; + return pn544_hci_i2c_write(client, skb->data, skb->len); } -static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, +static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 im_protocols, u32 tm_protocols) { + struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); u8 phases = 0; int r; u8 duration[2]; @@ -676,7 +641,7 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, return r; } -static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, +static int pn544_hci_target_from_gate(struct nfc_shdlc *shdlc, u8 gate, struct nfc_target *target) { switch (gate) { @@ -694,10 +659,11 @@ static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, return 0; } -static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, +static int pn544_hci_complete_target_discovered(struct nfc_shdlc *shdlc, u8 gate, struct nfc_target *target) { + struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); struct sk_buff *uid_skb; int r = 0; @@ -738,26 +704,6 @@ static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, return r; } -#define PN544_CB_TYPE_READER_F 1 - -static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb, - int err) -{ - struct pn544_hci_info *info = context; - - switch (info->async_cb_type) { - case PN544_CB_TYPE_READER_F: - if (err == 0) - skb_pull(skb, 1); - info->async_cb(info->async_cb_context, skb, err); - break; - default: - if (err == 0) - kfree_skb(skb); - break; - } -} - #define MIFARE_CMD_AUTH_KEY_A 0x60 #define MIFARE_CMD_AUTH_KEY_B 0x61 #define MIFARE_CMD_HEADER 2 @@ -769,12 +715,13 @@ static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb, * <= 0: driver handled the data exchange * 1: driver doesn't especially handle, please do standard processing */ -static int pn544_hci_data_exchange(struct nfc_hci_dev *hdev, +static int pn544_hci_data_exchange(struct nfc_shdlc *shdlc, struct nfc_target *target, - struct sk_buff *skb, data_exchange_cb_t cb, - void *cb_context) + struct sk_buff *skb, + struct sk_buff **res_skb) { - struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); + struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); + int r; pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__, target->hci_reader_gate); @@ -799,43 +746,41 @@ static int pn544_hci_data_exchange(struct nfc_hci_dev *hdev, memcpy(data, uid, MIFARE_UID_LEN); } - return nfc_hci_send_cmd_async(hdev, - target->hci_reader_gate, - PN544_MIFARE_CMD, - skb->data, skb->len, - cb, cb_context); + return nfc_hci_send_cmd(hdev, target->hci_reader_gate, + PN544_MIFARE_CMD, + skb->data, skb->len, res_skb); } else return 1; case PN544_RF_READER_F_GATE: *skb_push(skb, 1) = 0; *skb_push(skb, 1) = 0; - info->async_cb_type = PN544_CB_TYPE_READER_F; - info->async_cb = cb; - info->async_cb_context = cb_context; - - return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, - PN544_FELICA_RAW, skb->data, - skb->len, - pn544_hci_data_exchange_cb, info); + r = nfc_hci_send_cmd(hdev, target->hci_reader_gate, + PN544_FELICA_RAW, + skb->data, skb->len, res_skb); + if (r == 0) + skb_pull(*res_skb, 1); + return r; case PN544_RF_READER_JEWEL_GATE: - return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, - PN544_JEWEL_RAW_CMD, skb->data, - skb->len, cb, cb_context); + return nfc_hci_send_cmd(hdev, target->hci_reader_gate, + PN544_JEWEL_RAW_CMD, + skb->data, skb->len, res_skb); default: return 1; } } -static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, +static int pn544_hci_check_presence(struct nfc_shdlc *shdlc, struct nfc_target *target) { + struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); + return nfc_hci_send_cmd(hdev, target->hci_reader_gate, PN544_RF_READER_CMD_PRESENCE_CHECK, NULL, 0, NULL); } -static struct nfc_hci_ops pn544_hci_ops = { +static struct nfc_shdlc_ops pn544_shdlc_ops = { .open = pn544_hci_open, .close = pn544_hci_close, .hci_ready = pn544_hci_ready, @@ -903,8 +848,8 @@ static int __devinit pn544_hci_probe(struct i2c_client *client, pn544_hci_platform_init(info); r = request_threaded_irq(client->irq, NULL, pn544_hci_irq_thread_fn, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - PN544_HCI_DRIVER_NAME, info); + IRQF_TRIGGER_RISING, PN544_HCI_DRIVER_NAME, + info); if (r < 0) { dev_err(&client->dev, "Unable to register IRQ handler\n"); goto err_rti; @@ -927,30 +872,22 @@ static int __devinit pn544_hci_probe(struct i2c_client *client, NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_NFC_DEP_MASK; - info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, - protocols, LLC_SHDLC_NAME, - PN544_FRAME_HEADROOM + - PN544_CMDS_HEADROOM, - PN544_FRAME_TAILROOM, - PN544_HCI_LLC_MAX_PAYLOAD); - if (!info->hdev) { - dev_err(&client->dev, "Cannot allocate nfc hdev.\n"); + info->shdlc = nfc_shdlc_allocate(&pn544_shdlc_ops, + &init_data, protocols, + PN544_CMDS_HEADROOM, 0, + PN544_HCI_LLC_MAX_PAYLOAD, + dev_name(&client->dev)); + if (!info->shdlc) { + dev_err(&client->dev, "Cannot allocate nfc shdlc.\n"); r = -ENOMEM; - goto err_alloc_hdev; + goto err_allocshdlc; } - nfc_hci_set_clientdata(info->hdev, info); - - r = nfc_hci_register_device(info->hdev); - if (r) - goto err_regdev; + nfc_shdlc_set_clientdata(info->shdlc, info); return 0; -err_regdev: - nfc_hci_free_device(info->hdev); - -err_alloc_hdev: +err_allocshdlc: free_irq(client->irq, info); err_rti: @@ -971,7 +908,7 @@ static __devexit int pn544_hci_remove(struct i2c_client *client) dev_dbg(&client->dev, "%s\n", __func__); - nfc_hci_free_device(info->hdev); + nfc_shdlc_free(info->shdlc); if (info->state != PN544_ST_COLD) { if (pdata->disable) diff --git a/trunk/drivers/ptp/ptp_clock.c b/trunk/drivers/ptp/ptp_clock.c index 79f4bce061bd..966875dcda56 100644 --- a/trunk/drivers/ptp/ptp_clock.c +++ b/trunk/drivers/ptp/ptp_clock.c @@ -143,12 +143,10 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx) kt = timespec_to_ktime(ts); delta = ktime_to_ns(kt); err = ops->adjtime(ops, delta); + } else if (tx->modes & ADJ_FREQUENCY) { + err = ops->adjfreq(ops, scaled_ppm_to_ppb(tx->freq)); - ptp->dialed_frequency = tx->freq; - } else if (tx->modes == 0) { - tx->freq = ptp->dialed_frequency; - err = 0; } return err; @@ -182,8 +180,7 @@ static void delete_ptp_clock(struct posix_clock *pc) /* public interface */ -struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, - struct device *parent) +struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info) { struct ptp_clock *ptp; int err = 0, index, major = MAJOR(ptp_devt); @@ -216,7 +213,7 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, init_waitqueue_head(&ptp->tsev_wq); /* Create a new device in our class. */ - ptp->dev = device_create(ptp_class, parent, ptp->devid, ptp, + ptp->dev = device_create(ptp_class, NULL, ptp->devid, ptp, "ptp%d", ptp->index); if (IS_ERR(ptp->dev)) goto no_device; diff --git a/trunk/drivers/ptp/ptp_ixp46x.c b/trunk/drivers/ptp/ptp_ixp46x.c index d49b85164fd2..e03c40692b00 100644 --- a/trunk/drivers/ptp/ptp_ixp46x.c +++ b/trunk/drivers/ptp/ptp_ixp46x.c @@ -298,7 +298,7 @@ static int __init ptp_ixp_init(void) ixp_clock.caps = ptp_ixp_caps; - ixp_clock.ptp_clock = ptp_clock_register(&ixp_clock.caps, NULL); + ixp_clock.ptp_clock = ptp_clock_register(&ixp_clock.caps); if (IS_ERR(ixp_clock.ptp_clock)) return PTR_ERR(ixp_clock.ptp_clock); diff --git a/trunk/drivers/ptp/ptp_pch.c b/trunk/drivers/ptp/ptp_pch.c index e624e4dd2abb..3a9c17eced10 100644 --- a/trunk/drivers/ptp/ptp_pch.c +++ b/trunk/drivers/ptp/ptp_pch.c @@ -627,7 +627,7 @@ pch_probe(struct pci_dev *pdev, const struct pci_device_id *id) } chip->caps = ptp_pch_caps; - chip->ptp_clock = ptp_clock_register(&chip->caps, &pdev->dev); + chip->ptp_clock = ptp_clock_register(&chip->caps); if (IS_ERR(chip->ptp_clock)) return PTR_ERR(chip->ptp_clock); diff --git a/trunk/drivers/ptp/ptp_private.h b/trunk/drivers/ptp/ptp_private.h index 69d32070cc65..4d5b5082c3b1 100644 --- a/trunk/drivers/ptp/ptp_private.h +++ b/trunk/drivers/ptp/ptp_private.h @@ -45,7 +45,6 @@ struct ptp_clock { dev_t devid; int index; /* index into clocks.map */ struct pps_device *pps_source; - long dialed_frequency; /* remembers the frequency adjustment */ struct timestamp_event_queue tsevq; /* simple fifo for time stamps */ struct mutex tsevq_mux; /* one process at a time reading the fifo */ wait_queue_head_t tsev_wq; diff --git a/trunk/drivers/pwm/pwm-tiecap.c b/trunk/drivers/pwm/pwm-tiecap.c index 4b6688909fee..0b66d0f25922 100644 --- a/trunk/drivers/pwm/pwm-tiecap.c +++ b/trunk/drivers/pwm/pwm-tiecap.c @@ -100,13 +100,6 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writel(period_cycles, pc->mmio_base + CAP3); } - if (!test_bit(PWMF_ENABLED, &pwm->flags)) { - reg_val = readw(pc->mmio_base + ECCTL2); - /* Disable APWM mode to put APWM output Low */ - reg_val &= ~ECCTL2_APWM_MODE; - writew(reg_val, pc->mmio_base + ECCTL2); - } - pm_runtime_put_sync(pc->chip.dev); return 0; } diff --git a/trunk/drivers/pwm/pwm-tiehrpwm.c b/trunk/drivers/pwm/pwm-tiehrpwm.c index b1996bcd5b78..c3756d1be194 100644 --- a/trunk/drivers/pwm/pwm-tiehrpwm.c +++ b/trunk/drivers/pwm/pwm-tiehrpwm.c @@ -104,7 +104,6 @@ struct ehrpwm_pwm_chip { struct pwm_chip chip; unsigned int clk_rate; void __iomem *mmio_base; - unsigned long period_cycles[NUM_PWM_CHANNEL]; }; static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) @@ -211,7 +210,6 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long long c; unsigned long period_cycles, duty_cycles; unsigned short ps_divval, tb_divval; - int i; if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) return -ERANGE; @@ -231,28 +229,6 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, duty_cycles = (unsigned long)c; } - /* - * Period values should be same for multiple PWM channels as IP uses - * same period register for multiple channels. - */ - for (i = 0; i < NUM_PWM_CHANNEL; i++) { - if (pc->period_cycles[i] && - (pc->period_cycles[i] != period_cycles)) { - /* - * Allow channel to reconfigure period if no other - * channels being configured. - */ - if (i == pwm->hwpwm) - continue; - - dev_err(chip->dev, "Period value conflicts with channel %d\n", - i); - return -EINVAL; - } - } - - pc->period_cycles[pwm->hwpwm] = period_cycles; - /* Configure clock prescaler to support Low frequency PWM wave */ if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval, &tb_divval)) { @@ -344,15 +320,10 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { - struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); - if (test_bit(PWMF_ENABLED, &pwm->flags)) { dev_warn(chip->dev, "Removing PWM device without disabling\n"); pm_runtime_put_sync(chip->dev); } - - /* set period value to zero on free */ - pc->period_cycles[pwm->hwpwm] = 0; } static const struct pwm_ops ehrpwm_pwm_ops = { diff --git a/trunk/drivers/regulator/tps65217-regulator.c b/trunk/drivers/regulator/tps65217-regulator.c index ab00cab905b7..6caa222af77a 100644 --- a/trunk/drivers/regulator/tps65217-regulator.c +++ b/trunk/drivers/regulator/tps65217-regulator.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -282,130 +281,37 @@ static const struct regulator_desc regulators[] = { NULL), }; -#ifdef CONFIG_OF -static struct of_regulator_match reg_matches[] = { - { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, - { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, - { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, - { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, - { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, - { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, - { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, -}; - -static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) -{ - struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); - struct device_node *node = tps->dev->of_node; - struct tps65217_board *pdata; - struct device_node *regs; - int i, count; - - regs = of_find_node_by_name(node, "regulators"); - if (!regs) - return NULL; - - count = of_regulator_match(pdev->dev.parent, regs, - reg_matches, TPS65217_NUM_REGULATOR); - of_node_put(regs); - if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) - return NULL; - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - for (i = 0; i < count; i++) { - if (!reg_matches[i].init_data || !reg_matches[i].of_node) - continue; - - pdata->tps65217_init_data[i] = reg_matches[i].init_data; - pdata->of_node[i] = reg_matches[i].of_node; - } - - return pdata; -} -#else -static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) -{ - return NULL; -} -#endif - static int __devinit tps65217_regulator_probe(struct platform_device *pdev) { - struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); - struct tps65217_board *pdata = dev_get_platdata(tps->dev); - struct regulator_init_data *reg_data; struct regulator_dev *rdev; + struct tps65217 *tps; + struct tps_info *info = &tps65217_pmic_regs[pdev->id]; struct regulator_config config = { }; - int i, ret; - if (tps->dev->of_node) - pdata = tps65217_parse_dt(pdev); + /* Already set by core driver */ + tps = dev_to_tps65217(pdev->dev.parent); + tps->info[pdev->id] = info; - if (!pdata) { - dev_err(&pdev->dev, "Platform data not found\n"); - return -EINVAL; - } + config.dev = &pdev->dev; + config.of_node = pdev->dev.of_node; + config.init_data = pdev->dev.platform_data; + config.driver_data = tps; - if (tps65217_chip_id(tps) != TPS65217) { - dev_err(&pdev->dev, "Invalid tps chip version\n"); - return -ENODEV; - } + rdev = regulator_register(®ulators[pdev->id], &config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); - platform_set_drvdata(pdev, tps); + platform_set_drvdata(pdev, rdev); - for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { - - reg_data = pdata->tps65217_init_data[i]; - - /* - * Regulator API handles empty constraints but not NULL - * constraints - */ - if (!reg_data) - continue; - - /* Register the regulators */ - tps->info[i] = &tps65217_pmic_regs[i]; - - config.dev = tps->dev; - config.init_data = reg_data; - config.driver_data = tps; - config.regmap = tps->regmap; - if (tps->dev->of_node) - config.of_node = pdata->of_node[i]; - - rdev = regulator_register(®ulators[i], &config); - if (IS_ERR(rdev)) { - dev_err(tps->dev, "failed to register %s regulator\n", - pdev->name); - ret = PTR_ERR(rdev); - goto err_unregister_regulator; - } - - /* Save regulator for cleanup */ - tps->rdev[i] = rdev; - } return 0; - -err_unregister_regulator: - while (--i >= 0) - regulator_unregister(tps->rdev[i]); - - return ret; } static int __devexit tps65217_regulator_remove(struct platform_device *pdev) { - struct tps65217 *tps = platform_get_drvdata(pdev); - unsigned int i; - - for (i = 0; i < TPS65217_NUM_REGULATOR; i++) - regulator_unregister(tps->rdev[i]); + struct regulator_dev *rdev = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); + regulator_unregister(rdev); return 0; } diff --git a/trunk/drivers/rpmsg/virtio_rpmsg_bus.c b/trunk/drivers/rpmsg/virtio_rpmsg_bus.c index 1859f71372e2..590cfafc7c17 100644 --- a/trunk/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/trunk/drivers/rpmsg/virtio_rpmsg_bus.c @@ -1008,8 +1008,8 @@ static int rpmsg_probe(struct virtio_device *vdev) return 0; free_coherent: - dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, - bufs_va, vrp->bufs_dma); + dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, bufs_va, + vrp->bufs_dma); vqs_del: vdev->config->del_vqs(vrp->vdev); free_vrp: @@ -1043,7 +1043,7 @@ static void __devexit rpmsg_remove(struct virtio_device *vdev) vdev->config->del_vqs(vrp->vdev); - dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, + dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, vrp->rbufs, vrp->bufs_dma); kfree(vrp); diff --git a/trunk/drivers/rtc/rtc-twl.c b/trunk/drivers/rtc/rtc-twl.c index 9277d945bf48..c5d06fe83bba 100644 --- a/trunk/drivers/rtc/rtc-twl.c +++ b/trunk/drivers/rtc/rtc-twl.c @@ -495,11 +495,6 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) if (ret < 0) goto out1; - /* ensure interrupts are disabled, bootloaders can be strange */ - ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG); - if (ret < 0) - dev_warn(&pdev->dev, "unable to disable interrupt\n"); - /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index 0595c763dafd..15370a2c5ff0 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -534,11 +534,11 @@ static void dasd_change_state(struct dasd_device *device) if (rc) device->target = device->state; - /* let user-space know that the device status changed */ - kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); - if (device->state == device->target) wake_up(&dasd_init_waitq); + + /* let user-space know that the device status changed */ + kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); } /* @@ -2157,7 +2157,6 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible) test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && (!dasd_eer_enabled(device))) { cqr->status = DASD_CQR_FAILED; - cqr->intrc = -EAGAIN; continue; } /* Don't try to start requests if device is stopped */ @@ -3271,16 +3270,6 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event) dasd_schedule_device_bh(device); } if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) { - if (!(device->path_data.opm & eventlpm) && - !(device->path_data.tbvpm & eventlpm)) { - /* - * we can not establish a pathgroup on an - * unavailable path, so trigger a path - * verification first - */ - device->path_data.tbvpm |= eventlpm; - dasd_schedule_device_bh(device); - } DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Pathgroup re-established\n"); if (device->discipline->kick_validate) diff --git a/trunk/drivers/s390/block/dasd_alias.c b/trunk/drivers/s390/block/dasd_alias.c index 6b556995bb33..157defe5e069 100644 --- a/trunk/drivers/s390/block/dasd_alias.c +++ b/trunk/drivers/s390/block/dasd_alias.c @@ -384,29 +384,6 @@ static void _remove_device_from_lcu(struct alias_lcu *lcu, group->next = NULL; }; -static int -suborder_not_supported(struct dasd_ccw_req *cqr) -{ - char *sense; - char reason; - char msg_format; - char msg_no; - - sense = dasd_get_sense(&cqr->irb); - if (!sense) - return 0; - - reason = sense[0]; - msg_format = (sense[7] & 0xF0); - msg_no = (sense[7] & 0x0F); - - /* command reject, Format 0 MSG 4 - invalid parameter */ - if ((reason == 0x80) && (msg_format == 0x00) && (msg_no == 0x04)) - return 1; - - return 0; -} - static int read_unit_address_configuration(struct dasd_device *device, struct alias_lcu *lcu) { @@ -458,8 +435,6 @@ static int read_unit_address_configuration(struct dasd_device *device, do { rc = dasd_sleep_on(cqr); - if (rc && suborder_not_supported(cqr)) - return -EOPNOTSUPP; } while (rc && (cqr->retries > 0)); if (rc) { spin_lock_irqsave(&lcu->lock, flags); @@ -546,7 +521,7 @@ static void lcu_update_work(struct work_struct *work) * processing the data */ spin_lock_irqsave(&lcu->lock, flags); - if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) { + if (rc || (lcu->flags & NEED_UAC_UPDATE)) { DBF_DEV_EVENT(DBF_WARNING, device, "could not update" " alias data in lcu (rc = %d), retry later", rc); schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index c48c72abbefc..2fb2b9ea97ec 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -1507,8 +1507,7 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device, * call might change behaviour of DASD devices. */ static int -dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, - unsigned long flags) +dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) { struct dasd_ccw_req *cqr; int rc; @@ -1517,19 +1516,10 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, if (IS_ERR(cqr)) return PTR_ERR(cqr); - /* - * set flags e.g. turn on failfast, to prevent blocking - * the calling function should handle failed requests - */ - cqr->flags |= flags; - rc = dasd_sleep_on(cqr); if (!rc) /* trigger CIO to reprobe devices */ css_schedule_reprobe(); - else if (cqr->intrc == -EAGAIN) - rc = -EAGAIN; - dasd_sfree_request(cqr, cqr->memdev); return rc; } @@ -1537,8 +1527,7 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, /* * Valide storage server of current device. */ -static int dasd_eckd_validate_server(struct dasd_device *device, - unsigned long flags) +static void dasd_eckd_validate_server(struct dasd_device *device) { int rc; struct dasd_eckd_private *private; @@ -1547,18 +1536,17 @@ static int dasd_eckd_validate_server(struct dasd_device *device, private = (struct dasd_eckd_private *) device->private; if (private->uid.type == UA_BASE_PAV_ALIAS || private->uid.type == UA_HYPER_PAV_ALIAS) - return 0; + return; if (dasd_nopav || MACHINE_IS_VM) enable_pav = 0; else enable_pav = 1; - rc = dasd_eckd_psf_ssc(device, enable_pav, flags); + rc = dasd_eckd_psf_ssc(device, enable_pav); /* may be requested feature is not available on server, * therefore just report error and go ahead */ DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " "returned rc=%d", private->uid.ssid, rc); - return rc; } /* @@ -1568,13 +1556,7 @@ static void dasd_eckd_do_validate_server(struct work_struct *work) { struct dasd_device *device = container_of(work, struct dasd_device, kick_validate); - if (dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST) - == -EAGAIN) { - /* schedule worker again if failed */ - schedule_work(&device->kick_validate); - return; - } - + dasd_eckd_validate_server(device); dasd_put_device(device); } @@ -1703,7 +1685,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) if (rc) goto out_err2; - dasd_eckd_validate_server(device, 0); + dasd_eckd_validate_server(device); /* device may report different configuration data after LCU setup */ rc = dasd_eckd_read_conf(device); @@ -4171,7 +4153,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device) rc = dasd_alias_make_device_known_to_lcu(device); if (rc) return rc; - dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST); + dasd_eckd_validate_server(device); /* RE-Read Configuration Data */ rc = dasd_eckd_read_conf(device); diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index fc916f5d7314..ed25c8740a9c 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -1426,8 +1426,6 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) return IO_SCH_REPROBE; if (cdev->online) return IO_SCH_VERIFY; - if (cdev->private->state == DEV_STATE_NOT_OPER) - return IO_SCH_UNREG_ATTACH; return IO_SCH_NOP; } @@ -1521,14 +1519,11 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) goto out; break; case IO_SCH_UNREG_ATTACH: - spin_lock_irqsave(sch->lock, flags); if (cdev->private->flags.resuming) { /* Device will be handled later. */ rc = 0; - goto out_unlock; + goto out; } - sch_set_cdev(sch, NULL); - spin_unlock_irqrestore(sch->lock, flags); /* Unregister ccw device. */ ccw_device_unregister(cdev); break; diff --git a/trunk/drivers/s390/net/ctcm_fsms.c b/trunk/drivers/s390/net/ctcm_fsms.c index fb92524d24ef..d4ade9e92fbb 100644 --- a/trunk/drivers/s390/net/ctcm_fsms.c +++ b/trunk/drivers/s390/net/ctcm_fsms.c @@ -1523,7 +1523,7 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg) goto done; default: break; - } + }; fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? CTC_STATE_RXINIT : CTC_STATE_TXINIT); diff --git a/trunk/drivers/s390/net/ctcm_main.c b/trunk/drivers/s390/net/ctcm_main.c index 98ea9cc6f1aa..5227e5734a9d 100644 --- a/trunk/drivers/s390/net/ctcm_main.c +++ b/trunk/drivers/s390/net/ctcm_main.c @@ -1454,7 +1454,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, ch_fsm_len, GFP_KERNEL); } if (ch->fsm == NULL) - goto nomem_return; + goto free_return; fsm_newstate(ch->fsm, CTC_STATE_IDLE); diff --git a/trunk/drivers/s390/net/lcs.c b/trunk/drivers/s390/net/lcs.c index 2ca0f1dd7a00..a3adf4b1c60d 100644 --- a/trunk/drivers/s390/net/lcs.c +++ b/trunk/drivers/s390/net/lcs.c @@ -282,7 +282,7 @@ lcs_setup_write_ccws(struct lcs_card *card) LCS_DBF_TEXT(3, setup, "iwritccw"); /* Setup write ccws. */ - memset(card->write.ccws, 0, sizeof(struct ccw1) * (LCS_NUM_BUFFS + 1)); + memset(card->write.ccws, 0, sizeof(struct ccw1) * LCS_NUM_BUFFS + 1); for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) { card->write.ccws[cnt].cmd_code = LCS_CCW_WRITE; card->write.ccws[cnt].count = 0; diff --git a/trunk/drivers/s390/net/qeth_core_main.c b/trunk/drivers/s390/net/qeth_core_main.c index 3af9024f1b6f..7a8b09612c41 100644 --- a/trunk/drivers/s390/net/qeth_core_main.c +++ b/trunk/drivers/s390/net/qeth_core_main.c @@ -489,7 +489,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card) atomic_set(&reply->refcnt, 1); atomic_set(&reply->received, 0); reply->card = card; - } + }; return reply; } @@ -1257,30 +1257,7 @@ static void qeth_clean_channel(struct qeth_channel *channel) kfree(channel->iob[cnt].data); } -static void qeth_set_single_write_queues(struct qeth_card *card) -{ - if ((atomic_read(&card->qdio.state) != QETH_QDIO_UNINITIALIZED) && - (card->qdio.no_out_queues == 4)) - qeth_free_qdio_buffers(card); - - card->qdio.no_out_queues = 1; - if (card->qdio.default_out_queue != 0) - dev_info(&card->gdev->dev, "Priority Queueing not supported\n"); - - card->qdio.default_out_queue = 0; -} - -static void qeth_set_multiple_write_queues(struct qeth_card *card) -{ - if ((atomic_read(&card->qdio.state) != QETH_QDIO_UNINITIALIZED) && - (card->qdio.no_out_queues == 1)) { - qeth_free_qdio_buffers(card); - card->qdio.default_out_queue = 2; - } - card->qdio.no_out_queues = 4; -} - -static void qeth_update_from_chp_desc(struct qeth_card *card) +static void qeth_get_channel_path_desc(struct qeth_card *card) { struct ccw_device *ccwdev; struct channelPath_dsc { @@ -1297,23 +1274,38 @@ static void qeth_update_from_chp_desc(struct qeth_card *card) QETH_DBF_TEXT(SETUP, 2, "chp_desc"); ccwdev = card->data.ccwdev; - chp_dsc = ccw_device_get_chp_desc(ccwdev, 0); - if (!chp_dsc) - goto out; - - card->info.func_level = 0x4100 + chp_dsc->desc; - if (card->info.type == QETH_CARD_TYPE_IQD) - goto out; - - /* CHPP field bit 6 == 1 -> single queue */ - if ((chp_dsc->chpp & 0x02) == 0x02) - qeth_set_single_write_queues(card); - else - qeth_set_multiple_write_queues(card); -out: - kfree(chp_dsc); + chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0); + if (chp_dsc != NULL) { + if (card->info.type != QETH_CARD_TYPE_IQD) { + /* CHPP field bit 6 == 1 -> single queue */ + if ((chp_dsc->chpp & 0x02) == 0x02) { + if ((atomic_read(&card->qdio.state) != + QETH_QDIO_UNINITIALIZED) && + (card->qdio.no_out_queues == 4)) + /* change from 4 to 1 outbound queues */ + qeth_free_qdio_buffers(card); + card->qdio.no_out_queues = 1; + if (card->qdio.default_out_queue != 0) + dev_info(&card->gdev->dev, + "Priority Queueing not supported\n"); + card->qdio.default_out_queue = 0; + } else { + if ((atomic_read(&card->qdio.state) != + QETH_QDIO_UNINITIALIZED) && + (card->qdio.no_out_queues == 1)) { + /* change from 1 to 4 outbound queues */ + qeth_free_qdio_buffers(card); + card->qdio.default_out_queue = 2; + } + card->qdio.no_out_queues = 4; + } + } + card->info.func_level = 0x4100 + chp_dsc->desc; + kfree(chp_dsc); + } QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues); QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level); + return; } static void qeth_init_qdio_info(struct qeth_card *card) @@ -1481,7 +1473,7 @@ static int qeth_determine_card_type(struct qeth_card *card) card->qdio.no_in_queues = 1; card->info.is_multicast_different = known_devices[i][QETH_MULTICAST_IND]; - qeth_update_from_chp_desc(card); + qeth_get_channel_path_desc(card); return 0; } i++; @@ -2037,7 +2029,7 @@ int qeth_send_control_data(struct qeth_card *card, int len, if (time_after(jiffies, timeout)) goto time_err; cpu_relax(); - } + }; } if (reply->rc == -EIO) @@ -4750,7 +4742,7 @@ int qeth_core_hardsetup_card(struct qeth_card *card) QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); atomic_set(&card->force_alloc_skb, 0); - qeth_update_from_chp_desc(card); + qeth_get_channel_path_desc(card); retry: if (retries) QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", diff --git a/trunk/drivers/s390/net/qeth_l3_main.c b/trunk/drivers/s390/net/qeth_l3_main.c index 4cd310cb5bdf..c5f03fa70fba 100644 --- a/trunk/drivers/s390/net/qeth_l3_main.c +++ b/trunk/drivers/s390/net/qeth_l3_main.c @@ -794,7 +794,6 @@ int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto, rc = -EEXIST; spin_unlock_irqrestore(&card->ip_lock, flags); if (rc) { - kfree(ipaddr); return rc; } if (!qeth_l3_add_ip(card, ipaddr)) @@ -859,7 +858,6 @@ int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto, rc = -EEXIST; spin_unlock_irqrestore(&card->ip_lock, flags); if (rc) { - kfree(ipaddr); return rc; } if (!qeth_l3_add_ip(card, ipaddr)) diff --git a/trunk/drivers/scsi/bnx2i/bnx2i_hwi.c b/trunk/drivers/scsi/bnx2i/bnx2i_hwi.c index 91eec60252ee..33d6630529de 100644 --- a/trunk/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/trunk/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1264,9 +1264,6 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba) int rc = 0; u64 mask64; - memset(&iscsi_init, 0x00, sizeof(struct iscsi_kwqe_init1)); - memset(&iscsi_init2, 0x00, sizeof(struct iscsi_kwqe_init2)); - bnx2i_adjust_qp_size(hba); iscsi_init.flags = diff --git a/trunk/drivers/scsi/hpsa.c b/trunk/drivers/scsi/hpsa.c index 2b4261cb7742..796482badf13 100644 --- a/trunk/drivers/scsi/hpsa.c +++ b/trunk/drivers/scsi/hpsa.c @@ -1315,9 +1315,8 @@ static void complete_scsi_command(struct CommandList *cp) } break; case CMD_PROTOCOL_ERR: - cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p has " - "protocol error\n", cp); + "protocol error \n", cp); break; case CMD_HARDWARE_ERR: cmd->result = DID_ERROR << 16; diff --git a/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c b/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c index 9d5a56c4b332..b25757d1e91b 100644 --- a/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1209,13 +1209,6 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc) u16 message_control; - /* Check whether controller SAS2008 B0 controller, - if it is SAS2008 B0 controller use IO-APIC instead of MSIX */ - if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 && - ioc->pdev->revision == 0x01) { - return -EINVAL; - } - base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); if (!base) { dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not " diff --git a/trunk/drivers/scsi/virtio_scsi.c b/trunk/drivers/scsi/virtio_scsi.c index 3e79a2f00042..c7030fbee79c 100644 --- a/trunk/drivers/scsi/virtio_scsi.c +++ b/trunk/drivers/scsi/virtio_scsi.c @@ -331,7 +331,7 @@ static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx, int i; for_each_sg(table->sgl, sg_elem, table->nents, i) - sg[idx++] = *sg_elem; + sg_set_buf(&sg[idx++], sg_virt(sg_elem), sg_elem->length); *p_idx = idx; } diff --git a/trunk/drivers/sh/intc/core.c b/trunk/drivers/sh/intc/core.c index 8f32a1323a79..32c26d795ed0 100644 --- a/trunk/drivers/sh/intc/core.c +++ b/trunk/drivers/sh/intc/core.c @@ -355,7 +355,7 @@ int __init register_intc_controller(struct intc_desc *desc) if (unlikely(res)) { if (res == -EEXIST) { res = irq_domain_associate(d->domain, - irq2, irq2); + irq, irq); if (unlikely(res)) { pr_err("domain association " "failure\n"); diff --git a/trunk/drivers/sh/pfc/pinctrl.c b/trunk/drivers/sh/pfc/pinctrl.c index 0646bf6e7889..2804eaae804e 100644 --- a/trunk/drivers/sh/pfc/pinctrl.c +++ b/trunk/drivers/sh/pfc/pinctrl.c @@ -208,13 +208,10 @@ static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev, break; case PINMUX_TYPE_GPIO: - case PINMUX_TYPE_INPUT: - case PINMUX_TYPE_OUTPUT: break; default: pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type); - ret = -ENOTSUPP; - goto err; + return -ENOTSUPP; } ret = 0; diff --git a/trunk/drivers/staging/nvec/nvec.c b/trunk/drivers/staging/nvec/nvec.c index d0a7e408efe9..695ea35f75b0 100644 --- a/trunk/drivers/staging/nvec/nvec.c +++ b/trunk/drivers/staging/nvec/nvec.c @@ -837,7 +837,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) } ret = mfd_add_devices(nvec->dev, -1, nvec_devices, - ARRAY_SIZE(nvec_devices), base, 0, NULL); + ARRAY_SIZE(nvec_devices), base, 0); if (ret) dev_err(nvec->dev, "error adding subdevices\n"); diff --git a/trunk/drivers/target/iscsi/iscsi_target_login.c b/trunk/drivers/target/iscsi/iscsi_target_login.c index 6aba4395e8d8..0694d9b1bce6 100644 --- a/trunk/drivers/target/iscsi/iscsi_target_login.c +++ b/trunk/drivers/target/iscsi/iscsi_target_login.c @@ -221,7 +221,6 @@ static int iscsi_login_zero_tsih_s1( { struct iscsi_session *sess = NULL; struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; - int ret; sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL); if (!sess) { @@ -258,17 +257,9 @@ static int iscsi_login_zero_tsih_s1( return -ENOMEM; } spin_lock(&sess_idr_lock); - ret = idr_get_new(&sess_idr, NULL, &sess->session_index); + idr_get_new(&sess_idr, NULL, &sess->session_index); spin_unlock(&sess_idr_lock); - if (ret < 0) { - pr_err("idr_get_new() for sess_idr failed\n"); - iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, - ISCSI_LOGIN_STATUS_NO_RESOURCES); - kfree(sess); - return -ENOMEM; - } - sess->creation_time = get_jiffies_64(); spin_lock_init(&sess->session_stats_lock); /* diff --git a/trunk/drivers/target/target_core_alua.c b/trunk/drivers/target/target_core_alua.c index 41641ba54828..91799973081a 100644 --- a/trunk/drivers/target/target_core_alua.c +++ b/trunk/drivers/target/target_core_alua.c @@ -218,13 +218,6 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return -EINVAL; } - if (cmd->data_length < 4) { - pr_warn("SET TARGET PORT GROUPS parameter list length %u too" - " small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; - } - buf = transport_kmap_data_sg(cmd); /* diff --git a/trunk/drivers/target/target_core_device.c b/trunk/drivers/target/target_core_device.c index 9fc9a6006ca0..cf2c66f3c116 100644 --- a/trunk/drivers/target/target_core_device.c +++ b/trunk/drivers/target/target_core_device.c @@ -669,13 +669,6 @@ int target_report_luns(struct se_cmd *se_cmd) unsigned char *buf; u32 lun_count = 0, offset = 8, i; - if (se_cmd->data_length < 16) { - pr_warn("REPORT LUNS allocation length %u too small\n", - se_cmd->data_length); - se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } - buf = transport_kmap_data_sg(se_cmd); if (!buf) return -ENOMEM; diff --git a/trunk/drivers/target/target_core_iblock.c b/trunk/drivers/target/target_core_iblock.c index 9ba495477fd2..76db75e836ed 100644 --- a/trunk/drivers/target/target_core_iblock.c +++ b/trunk/drivers/target/target_core_iblock.c @@ -325,30 +325,17 @@ static int iblock_execute_unmap(struct se_cmd *cmd) struct iblock_dev *ibd = dev->dev_ptr; unsigned char *buf, *ptr = NULL; sector_t lba; - int size; + int size = cmd->data_length; u32 range; int ret = 0; int dl, bd_dl; - if (cmd->data_length < 8) { - pr_warn("UNMAP parameter list length %u too small\n", - cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; - } - buf = transport_kmap_data_sg(cmd); dl = get_unaligned_be16(&buf[0]); bd_dl = get_unaligned_be16(&buf[2]); - size = cmd->data_length - 8; - if (bd_dl > size) - pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", - cmd->data_length, bd_dl); - else - size = bd_dl; - + size = min(size - 8, bd_dl); if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = -EINVAL; diff --git a/trunk/drivers/target/target_core_pr.c b/trunk/drivers/target/target_core_pr.c index 956c84c6b666..1e946502c378 100644 --- a/trunk/drivers/target/target_core_pr.c +++ b/trunk/drivers/target/target_core_pr.c @@ -1540,14 +1540,6 @@ static int core_scsi3_decode_spec_i_port( tidh_new->dest_local_nexus = 1; list_add_tail(&tidh_new->dest_list, &tid_dest_list); - if (cmd->data_length < 28) { - pr_warn("SPC-PR: Received PR OUT parameter list" - " length too small: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; - } - buf = transport_kmap_data_sg(cmd); /* * For a PERSISTENT RESERVE OUT specify initiator ports payload, diff --git a/trunk/drivers/target/target_core_pscsi.c b/trunk/drivers/target/target_core_pscsi.c index 9d7ce3daa262..5552fa7426bc 100644 --- a/trunk/drivers/target/target_core_pscsi.c +++ b/trunk/drivers/target/target_core_pscsi.c @@ -667,8 +667,7 @@ static void pscsi_free_device(void *p) kfree(pdv); } -static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, - unsigned char *sense_buffer) +static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) { struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; struct scsi_device *sd = pdv->pdv_sd; @@ -680,7 +679,7 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, * not been allocated because TCM is handling the emulation directly. */ if (!pt) - return; + return 0; cdb = &pt->pscsi_cdb[0]; result = pt->pscsi_result; @@ -688,11 +687,11 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, * Hack to make sure that Write-Protect modepage is set if R/O mode is * forced. */ - if (!cmd->se_deve || !cmd->data_length) - goto after_mode_sense; - if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && (status_byte(result) << 1) == SAM_STAT_GOOD) { + if (!cmd->se_deve) + goto after_mode_sense; + if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { unsigned char *buf = transport_kmap_data_sg(cmd); @@ -709,7 +708,7 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, } after_mode_sense: - if (sd->type != TYPE_TAPE || !cmd->data_length) + if (sd->type != TYPE_TAPE) goto after_mode_select; /* @@ -751,10 +750,10 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, } after_mode_select: - if (sense_buffer && (status_byte(result) & CHECK_CONDITION)) { - memcpy(sense_buffer, pt->pscsi_sense, TRANSPORT_SENSE_BUFFER); - cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; - } + if (status_byte(result) & CHECK_CONDITION) + return 1; + + return 0; } enum { @@ -1185,6 +1184,13 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) return -ENOMEM; } +static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd) +{ + struct pscsi_plugin_task *pt = cmd->priv; + + return pt->pscsi_sense; +} + /* pscsi_get_device_rev(): * * @@ -1267,6 +1273,7 @@ static struct se_subsystem_api pscsi_template = { .check_configfs_dev_params = pscsi_check_configfs_dev_params, .set_configfs_dev_params = pscsi_set_configfs_dev_params, .show_configfs_dev_params = pscsi_show_configfs_dev_params, + .get_sense_buffer = pscsi_get_sense_buffer, .get_device_rev = pscsi_get_device_rev, .get_device_type = pscsi_get_device_type, .get_blocks = pscsi_get_blocks, diff --git a/trunk/drivers/target/target_core_spc.c b/trunk/drivers/target/target_core_spc.c index 388a922c8f6d..4c861de538c9 100644 --- a/trunk/drivers/target/target_core_spc.c +++ b/trunk/drivers/target/target_core_spc.c @@ -877,11 +877,9 @@ static int spc_emulate_modesense(struct se_cmd *cmd) static int spc_emulate_request_sense(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; - unsigned char *rbuf; + unsigned char *buf; u8 ua_asc = 0, ua_ascq = 0; - unsigned char buf[SE_SENSE_BUF]; - - memset(buf, 0, SE_SENSE_BUF); + int err = 0; if (cdb[1] & 0x01) { pr_err("REQUEST_SENSE description emulation not" @@ -890,21 +888,20 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) return -ENOSYS; } - rbuf = transport_kmap_data_sg(cmd); - if (cmd->scsi_sense_reason != 0) { - /* - * Out of memory. We will fail with CHECK CONDITION, so - * we must not clear the unit attention condition. - */ - target_complete_cmd(cmd, CHECK_CONDITION); - return 0; - } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { + buf = transport_kmap_data_sg(cmd); + + if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { /* * CURRENT ERROR, UNIT ATTENTION */ buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; + if (cmd->data_length < 18) { + buf[7] = 0x00; + err = -EINVAL; + goto end; + } /* * The Additional Sense Code (ASC) from the UNIT ATTENTION */ @@ -918,6 +915,11 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; + if (cmd->data_length < 18) { + buf[7] = 0x00; + err = -EINVAL; + goto end; + } /* * NO ADDITIONAL SENSE INFORMATION */ @@ -925,11 +927,8 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[7] = 0x0A; } - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } - +end: + transport_kunmap_data_sg(cmd); target_complete_cmd(cmd, GOOD); return 0; } diff --git a/trunk/drivers/target/target_core_transport.c b/trunk/drivers/target/target_core_transport.c index 269f54488397..4de3186dc44e 100644 --- a/trunk/drivers/target/target_core_transport.c +++ b/trunk/drivers/target/target_core_transport.c @@ -567,34 +567,6 @@ static void target_complete_failure_work(struct work_struct *work) transport_generic_request_failure(cmd); } -/* - * Used when asking transport to copy Sense Data from the underlying - * Linux/SCSI struct scsi_cmnd - */ -static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd) -{ - unsigned char *buffer = cmd->sense_buffer; - struct se_device *dev = cmd->se_dev; - u32 offset = 0; - - WARN_ON(!cmd->se_lun); - - if (!dev) - return NULL; - - if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) - return NULL; - - offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); - - /* Automatically padded */ - cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; - - pr_debug("HBA_[%u]_PLUG[%s]: Requesting sense for SAM STATUS: 0x%02x\n", - dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); - return &buffer[offset]; -} - void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) { struct se_device *dev = cmd->se_dev; @@ -608,11 +580,11 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) cmd->transport_state &= ~CMD_T_BUSY; if (dev && dev->transport->transport_complete) { - dev->transport->transport_complete(cmd, - cmd->t_data_sg, - transport_get_sense_buffer(cmd)); - if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) + if (dev->transport->transport_complete(cmd, + cmd->t_data_sg) != 0) { + cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; success = 1; + } } /* @@ -1209,20 +1181,15 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ goto out_invalid_cdb_field; } - /* - * For the overflow case keep the existing fabric provided - * ->data_length. Otherwise for the underflow case, reset - * ->data_length to the smaller SCSI expected data transfer - * length. - */ + if (size > cmd->data_length) { cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; cmd->residual_count = (size - cmd->data_length); } else { cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; cmd->residual_count = (cmd->data_length - size); - cmd->data_length = size; } + cmd->data_length = size; } return 0; @@ -1848,6 +1815,61 @@ void target_execute_cmd(struct se_cmd *cmd) } EXPORT_SYMBOL(target_execute_cmd); +/* + * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd + */ +static int transport_get_sense_data(struct se_cmd *cmd) +{ + unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; + struct se_device *dev = cmd->se_dev; + unsigned long flags; + u32 offset = 0; + + WARN_ON(!cmd->se_lun); + + if (!dev) + return 0; + + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return 0; + } + + if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) + goto out; + + if (!dev->transport->get_sense_buffer) { + pr_err("dev->transport->get_sense_buffer is NULL\n"); + goto out; + } + + sense_buffer = dev->transport->get_sense_buffer(cmd); + if (!sense_buffer) { + pr_err("ITT 0x%08x cmd %p: Unable to locate" + " sense buffer for task with sense\n", + cmd->se_tfo->get_task_tag(cmd), cmd); + goto out; + } + + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + + offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); + + memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); + + /* Automatically padded */ + cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; + + pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", + dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); + return 0; + +out: + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return -1; +} + /* * Process all commands up to the last received ORDERED task attribute which * requires another blocking boundary @@ -1963,7 +1985,7 @@ static void transport_handle_queue_full( static void target_complete_ok_work(struct work_struct *work) { struct se_cmd *cmd = container_of(work, struct se_cmd, work); - int ret; + int reason = 0, ret; /* * Check if we need to move delayed/dormant tasks from cmds on the @@ -1980,19 +2002,23 @@ static void target_complete_ok_work(struct work_struct *work) schedule_work(&cmd->se_dev->qf_work_queue); /* - * Check if we need to send a sense buffer from + * Check if we need to retrieve a sense buffer from * the struct se_cmd in question. */ if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { - WARN_ON(!cmd->scsi_status); - ret = transport_send_check_condition_and_sense( - cmd, 0, 1); - if (ret == -EAGAIN || ret == -ENOMEM) - goto queue_full; + if (transport_get_sense_data(cmd) < 0) + reason = TCM_NON_EXISTENT_LUN; - transport_lun_remove_cmd(cmd); - transport_cmd_check_stop_to_fabric(cmd); - return; + if (cmd->scsi_status) { + ret = transport_send_check_condition_and_sense( + cmd, reason, 1); + if (ret == -EAGAIN || ret == -ENOMEM) + goto queue_full; + + transport_lun_remove_cmd(cmd); + transport_cmd_check_stop_to_fabric(cmd); + return; + } } /* * Check for a callback, used by amongst other things @@ -2190,6 +2216,7 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) struct page **pages; int i; + BUG_ON(!sg); /* * We need to take into account a possible offset here for fabrics like * tcm_loop who may be using a contig buffer from the SCSI midlayer for @@ -2197,17 +2224,13 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) */ if (!cmd->t_data_nents) return NULL; - - BUG_ON(!sg); - if (cmd->t_data_nents == 1) + else if (cmd->t_data_nents == 1) return kmap(sg_page(sg)) + sg->offset; /* >1 page. use vmap */ pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); - if (!pages) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (!pages) return NULL; - } /* convert sg[] to pages[] */ for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { @@ -2216,10 +2239,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); kfree(pages); - if (!cmd->t_data_vmap) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (!cmd->t_data_vmap) return NULL; - } return cmd->t_data_vmap + cmd->t_data_sg[0].offset; } @@ -2305,14 +2326,19 @@ int transport_generic_new_cmd(struct se_cmd *cmd) * into the fabric for data transfers, go ahead and complete it right * away. */ - if (!cmd->data_length && - cmd->t_task_cdb[0] != REQUEST_SENSE && - cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) { + if (!cmd->data_length) { spin_lock_irq(&cmd->t_state_lock); cmd->t_state = TRANSPORT_COMPLETE; cmd->transport_state |= CMD_T_ACTIVE; spin_unlock_irq(&cmd->t_state_lock); + if (cmd->t_task_cdb[0] == REQUEST_SENSE) { + u8 ua_asc = 0, ua_ascq = 0; + + core_scsi3_ua_clear_for_request_sense(cmd, + &ua_asc, &ua_ascq); + } + INIT_WORK(&cmd->work, target_complete_ok_work); queue_work(target_completion_wq, &cmd->work); return 0; diff --git a/trunk/drivers/usb/core/devices.c b/trunk/drivers/usb/core/devices.c index 3440812b4a84..d95696584762 100644 --- a/trunk/drivers/usb/core/devices.c +++ b/trunk/drivers/usb/core/devices.c @@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, /* print devices for all busses */ list_for_each_entry(bus, &usb_bus_list, bus_list) { /* recurse through all children of the root hub */ - if (!bus_to_hcd(bus)->rh_registered) + if (!bus->root_hub) continue; usb_lock_device(bus->root_hub); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, diff --git a/trunk/drivers/usb/core/hcd.c b/trunk/drivers/usb/core/hcd.c index 75ba2091f9b4..bc84106ac057 100644 --- a/trunk/drivers/usb/core/hcd.c +++ b/trunk/drivers/usb/core/hcd.c @@ -1011,7 +1011,10 @@ static int register_root_hub(struct usb_hcd *hcd) if (retval) { dev_err (parent_dev, "can't register root hub for %s, %d\n", dev_name(&usb_dev->dev), retval); - } else { + } + mutex_unlock(&usb_bus_list_lock); + + if (retval == 0) { spin_lock_irq (&hcd_root_hub_lock); hcd->rh_registered = 1; spin_unlock_irq (&hcd_root_hub_lock); @@ -1020,7 +1023,6 @@ static int register_root_hub(struct usb_hcd *hcd) if (HCD_DEAD(hcd)) usb_hc_died (hcd); /* This time clean up */ } - mutex_unlock(&usb_bus_list_lock); return retval; } diff --git a/trunk/drivers/usb/host/ohci-at91.c b/trunk/drivers/usb/host/ohci-at91.c index 0bf72f943b00..aaa8d2bce217 100644 --- a/trunk/drivers/usb/host/ohci-at91.c +++ b/trunk/drivers/usb/host/ohci-at91.c @@ -467,8 +467,7 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) /* From the GPIO notifying the over-current situation, find * out the corresponding port */ at91_for_each_port(port) { - if (gpio_is_valid(pdata->overcurrent_pin[port]) && - gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { + if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { gpio = pdata->overcurrent_pin[port]; break; } diff --git a/trunk/drivers/vfio/pci/vfio_pci_intrs.c b/trunk/drivers/vfio/pci/vfio_pci_intrs.c index d8dedc7d3910..211a4920b88a 100644 --- a/trunk/drivers/vfio/pci/vfio_pci_intrs.c +++ b/trunk/drivers/vfio/pci/vfio_pci_intrs.c @@ -76,24 +76,9 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key) schedule_work(&virqfd->inject); } - if (flags & POLLHUP) { - unsigned long flags; - spin_lock_irqsave(&virqfd->vdev->irqlock, flags); - - /* - * The eventfd is closing, if the virqfd has not yet been - * queued for release, as determined by testing whether the - * vdev pointer to it is still valid, queue it now. As - * with kvm irqfds, we know we won't race against the virqfd - * going away because we hold wqh->lock to get here. - */ - if (*(virqfd->pvirqfd) == virqfd) { - *(virqfd->pvirqfd) = NULL; - virqfd_deactivate(virqfd); - } - - spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags); - } + if (flags & POLLHUP) + /* The eventfd is closing, detach from VFIO */ + virqfd_deactivate(virqfd); return 0; } @@ -108,6 +93,7 @@ static void virqfd_ptable_queue_proc(struct file *file, static void virqfd_shutdown(struct work_struct *work) { struct virqfd *virqfd = container_of(work, struct virqfd, shutdown); + struct virqfd **pvirqfd = virqfd->pvirqfd; u64 cnt; eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt); @@ -115,6 +101,7 @@ static void virqfd_shutdown(struct work_struct *work) eventfd_ctx_put(virqfd->eventfd); kfree(virqfd); + *pvirqfd = NULL; } static void virqfd_inject(struct work_struct *work) @@ -135,11 +122,15 @@ static int virqfd_enable(struct vfio_pci_device *vdev, int ret = 0; unsigned int events; + if (*pvirqfd) + return -EBUSY; + virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL); if (!virqfd) return -ENOMEM; virqfd->pvirqfd = pvirqfd; + *pvirqfd = virqfd; virqfd->vdev = vdev; virqfd->handler = handler; virqfd->thread = thread; @@ -162,23 +153,6 @@ static int virqfd_enable(struct vfio_pci_device *vdev, virqfd->eventfd = ctx; - /* - * virqfds can be released by closing the eventfd or directly - * through ioctl. These are both done through a workqueue, so - * we update the pointer to the virqfd under lock to avoid - * pushing multiple jobs to release the same virqfd. - */ - spin_lock_irq(&vdev->irqlock); - - if (*pvirqfd) { - spin_unlock_irq(&vdev->irqlock); - ret = -EBUSY; - goto fail; - } - *pvirqfd = virqfd; - - spin_unlock_irq(&vdev->irqlock); - /* * Install our own custom wake-up handling so we are notified via * a callback whenever someone signals the underlying eventfd. @@ -213,29 +187,19 @@ static int virqfd_enable(struct vfio_pci_device *vdev, fput(file); kfree(virqfd); + *pvirqfd = NULL; return ret; } -static void virqfd_disable(struct vfio_pci_device *vdev, - struct virqfd **pvirqfd) +static void virqfd_disable(struct virqfd *virqfd) { - unsigned long flags; - - spin_lock_irqsave(&vdev->irqlock, flags); - - if (*pvirqfd) { - virqfd_deactivate(*pvirqfd); - *pvirqfd = NULL; - } + if (!virqfd) + return; - spin_unlock_irqrestore(&vdev->irqlock, flags); + virqfd_deactivate(virqfd); - /* - * Block until we know all outstanding shutdown jobs have completed. - * Even if we don't queue the job, flush the wq to be sure it's - * been released. - */ + /* Block until we know all outstanding shutdown jobs have completed. */ flush_workqueue(vfio_irqfd_cleanup_wq); } @@ -428,8 +392,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd) static void vfio_intx_disable(struct vfio_pci_device *vdev) { vfio_intx_set_signal(vdev, -1); - virqfd_disable(vdev, &vdev->ctx[0].unmask); - virqfd_disable(vdev, &vdev->ctx[0].mask); + virqfd_disable(vdev->ctx[0].unmask); + virqfd_disable(vdev->ctx[0].mask); vdev->irq_type = VFIO_PCI_NUM_IRQS; vdev->num_ctx = 0; kfree(vdev->ctx); @@ -575,8 +539,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix) vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix); for (i = 0; i < vdev->num_ctx; i++) { - virqfd_disable(vdev, &vdev->ctx[i].unmask); - virqfd_disable(vdev, &vdev->ctx[i].mask); + virqfd_disable(vdev->ctx[i].unmask); + virqfd_disable(vdev->ctx[i].mask); } if (msix) { @@ -613,7 +577,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev, vfio_send_intx_eventfd, NULL, &vdev->ctx[0].unmask, fd); - virqfd_disable(vdev, &vdev->ctx[0].unmask); + virqfd_disable(vdev->ctx[0].unmask); } return 0; diff --git a/trunk/drivers/watchdog/hpwdt.c b/trunk/drivers/watchdog/hpwdt.c index ae60406ea8a1..1eff743ec497 100644 --- a/trunk/drivers/watchdog/hpwdt.c +++ b/trunk/drivers/watchdog/hpwdt.c @@ -814,9 +814,6 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, hpwdt_timer_reg = pci_mem_addr + 0x70; hpwdt_timer_con = pci_mem_addr + 0x72; - /* Make sure that timer is disabled until /dev/watchdog is opened */ - hpwdt_stop(); - /* Make sure that we have a valid soft_margin */ if (hpwdt_change_timer(soft_margin)) hpwdt_change_timer(DEFAULT_MARGIN); diff --git a/trunk/drivers/watchdog/watchdog_core.c b/trunk/drivers/watchdog/watchdog_core.c index 3796434991fa..6aa46a90ff02 100644 --- a/trunk/drivers/watchdog/watchdog_core.c +++ b/trunk/drivers/watchdog/watchdog_core.c @@ -128,12 +128,11 @@ EXPORT_SYMBOL_GPL(watchdog_register_device); void watchdog_unregister_device(struct watchdog_device *wdd) { int ret; - int devno; + int devno = wdd->cdev.dev; if (wdd == NULL) return; - devno = wdd->cdev.dev; ret = watchdog_dev_unregister(wdd); if (ret) pr_err("error unregistering /dev/watchdog (err=%d)\n", ret); diff --git a/trunk/drivers/xen/gntdev.c b/trunk/drivers/xen/gntdev.c index 7f1241608489..1ffd03bf8e10 100644 --- a/trunk/drivers/xen/gntdev.c +++ b/trunk/drivers/xen/gntdev.c @@ -314,9 +314,8 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) } } - err = gnttab_unmap_refs(map->unmap_ops + offset, - use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset, - pages); + err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset, + pages, true); if (err) return err; diff --git a/trunk/drivers/xen/grant-table.c b/trunk/drivers/xen/grant-table.c index 006726688baf..0bfc1ef11259 100644 --- a/trunk/drivers/xen/grant-table.c +++ b/trunk/drivers/xen/grant-table.c @@ -870,8 +870,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, EXPORT_SYMBOL_GPL(gnttab_map_refs); int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, - struct gnttab_map_grant_ref *kmap_ops, - struct page **pages, unsigned int count) + struct page **pages, unsigned int count, bool clear_pte) { int i, ret; bool lazy = false; @@ -889,8 +888,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, } for (i = 0; i < count; i++) { - ret = m2p_remove_override(pages[i], kmap_ops ? - &kmap_ops[i] : NULL); + ret = m2p_remove_override(pages[i], clear_pte); if (ret) return ret; } diff --git a/trunk/fs/btrfs/qgroup.c b/trunk/fs/btrfs/qgroup.c index b65015581744..38b42e7bc91d 100644 --- a/trunk/fs/btrfs/qgroup.c +++ b/trunk/fs/btrfs/qgroup.c @@ -1371,8 +1371,10 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, if (srcid) { srcgroup = find_qgroup_rb(fs_info, srcid); - if (!srcgroup) + if (!srcgroup) { + ret = -EINVAL; goto unlock; + } dstgroup->rfer = srcgroup->rfer - level_size; dstgroup->rfer_cmpr = srcgroup->rfer_cmpr - level_size; srcgroup->excl = level_size; @@ -1381,8 +1383,10 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, qgroup_dirty(fs_info, srcgroup); } - if (!inherit) + if (!inherit) { + ret = -EINVAL; goto unlock; + } i_qgroups = (u64 *)(inherit + 1); for (i = 0; i < inherit->num_qgroups; ++i) { diff --git a/trunk/fs/cifs/cifs_unicode.c b/trunk/fs/cifs/cifs_unicode.c index 53cf2aabce87..7dab9c04ad52 100644 --- a/trunk/fs/cifs/cifs_unicode.c +++ b/trunk/fs/cifs/cifs_unicode.c @@ -328,7 +328,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, } ctoUTF16_out: - return j; + return i; } #ifdef CONFIG_CIFS_SMB2 diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index 0364af2311f4..8086636bf796 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -389,7 +389,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) * Inform try_to_ascend() that we are no longer attached to the * dentry tree */ - dentry->d_flags |= DCACHE_DENTRY_KILLED; + dentry->d_flags |= DCACHE_DISCONNECTED; if (parent) spin_unlock(&parent->d_lock); dentry_iput(dentry); @@ -1048,7 +1048,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq * or deletion */ if (new != old->d_parent || - (old->d_flags & DCACHE_DENTRY_KILLED) || + (old->d_flags & DCACHE_DISCONNECTED) || (!locked && read_seqretry(&rename_lock, seq))) { spin_unlock(&new->d_lock); new = NULL; @@ -1141,7 +1141,7 @@ int have_submounts(struct dentry *parent) EXPORT_SYMBOL(have_submounts); /* - * Search the dentry child list of the specified parent, + * Search the dentry child list for the specified parent, * and move any unused dentries to the end of the unused * list for prune_dcache(). We descend to the next level * whenever the d_subdirs list is non-empty and continue diff --git a/trunk/fs/debugfs/file.c b/trunk/fs/debugfs/file.c index c5ca6ae5a30c..2340f6978d6e 100644 --- a/trunk/fs/debugfs/file.c +++ b/trunk/fs/debugfs/file.c @@ -526,51 +526,73 @@ struct array_data { u32 elements; }; -static size_t u32_format_array(char *buf, size_t bufsize, - u32 *array, int array_size) +static int u32_array_open(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return nonseekable_open(inode, file); +} + +static size_t format_array(char *buf, size_t bufsize, const char *fmt, + u32 *array, u32 array_size) { size_t ret = 0; + u32 i; - while (--array_size >= 0) { + for (i = 0; i < array_size; i++) { size_t len; - char term = array_size ? ' ' : '\n'; - len = snprintf(buf, bufsize, "%u%c", *array++, term); + len = snprintf(buf, bufsize, fmt, array[i]); + len++; /* ' ' or '\n' */ ret += len; - buf += len; - bufsize -= len; + if (buf) { + buf += len; + bufsize -= len; + buf[-1] = (i == array_size-1) ? '\n' : ' '; + } } + + ret++; /* \0 */ + if (buf) + *buf = '\0'; + return ret; } -static int u32_array_open(struct inode *inode, struct file *file) +static char *format_array_alloc(const char *fmt, u32 *array, + u32 array_size) { - struct array_data *data = inode->i_private; - int size, elements = data->elements; - char *buf; - - /* - * Max size: - * - 10 digits + ' '/'\n' = 11 bytes per number - * - terminating NUL character - */ - size = elements*11; - buf = kmalloc(size+1, GFP_KERNEL); - if (!buf) - return -ENOMEM; - buf[size] = 0; - - file->private_data = buf; - u32_format_array(buf, size, data->array, data->elements); + size_t len = format_array(NULL, 0, fmt, array, array_size); + char *ret; - return nonseekable_open(inode, file); + ret = kmalloc(len, GFP_KERNEL); + if (ret == NULL) + return NULL; + + format_array(ret, len, fmt, array, array_size); + return ret; } static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { - size_t size = strlen(file->private_data); + struct inode *inode = file->f_path.dentry->d_inode; + struct array_data *data = inode->i_private; + size_t size; + + if (*ppos == 0) { + if (file->private_data) { + kfree(file->private_data); + file->private_data = NULL; + } + + file->private_data = format_array_alloc("%u", data->array, + data->elements); + } + + size = 0; + if (file->private_data) + size = strlen(file->private_data); return simple_read_from_buffer(buf, len, ppos, file->private_data, size); diff --git a/trunk/fs/lockd/svclock.c b/trunk/fs/lockd/svclock.c index 8d80c990dffd..fb1a2bedbe97 100644 --- a/trunk/fs/lockd/svclock.c +++ b/trunk/fs/lockd/svclock.c @@ -289,6 +289,7 @@ static void nlmsvc_free_block(struct kref *kref) dprintk("lockd: freeing block %p...\n", block); /* Remove block from file's list of blocks */ + mutex_lock(&file->f_mutex); list_del_init(&block->b_flist); mutex_unlock(&file->f_mutex); @@ -302,7 +303,7 @@ static void nlmsvc_free_block(struct kref *kref) static void nlmsvc_release_block(struct nlm_block *block) { if (block != NULL) - kref_put_mutex(&block->b_count, nlmsvc_free_block, &block->b_file->f_mutex); + kref_put(&block->b_count, nlmsvc_free_block); } /* diff --git a/trunk/fs/namespace.c b/trunk/fs/namespace.c index 7bdf7907413f..4d31f73e2561 100644 --- a/trunk/fs/namespace.c +++ b/trunk/fs/namespace.c @@ -1886,14 +1886,8 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags) return err; err = -EINVAL; - if (unlikely(!check_mnt(real_mount(path->mnt)))) { - /* that's acceptable only for automounts done in private ns */ - if (!(mnt_flags & MNT_SHRINKABLE)) - goto unlock; - /* ... and for those we'd better have mountpoint still alive */ - if (!real_mount(path->mnt)->mnt_ns) - goto unlock; - } + if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(real_mount(path->mnt))) + goto unlock; /* Refuse the same filesystem on the same mount point */ err = -EBUSY; diff --git a/trunk/fs/proc/proc_sysctl.c b/trunk/fs/proc/proc_sysctl.c index eb7cc91b7258..dfafeb2b05a0 100644 --- a/trunk/fs/proc/proc_sysctl.c +++ b/trunk/fs/proc/proc_sysctl.c @@ -462,6 +462,9 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, err = ERR_PTR(-ENOMEM); inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p); + if (h) + sysctl_head_finish(h); + if (!inode) goto out; @@ -470,8 +473,6 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, d_add(dentry, inode); out: - if (h) - sysctl_head_finish(h); sysctl_head_finish(head); return err; } diff --git a/trunk/fs/xfs/xfs_buf.c b/trunk/fs/xfs/xfs_buf.c index 933b7930b863..d7a9dd735e1e 100644 --- a/trunk/fs/xfs/xfs_buf.c +++ b/trunk/fs/xfs/xfs_buf.c @@ -96,7 +96,6 @@ xfs_buf_lru_add( atomic_inc(&bp->b_hold); list_add_tail(&bp->b_lru, &btp->bt_lru); btp->bt_lru_nr++; - bp->b_lru_flags &= ~_XBF_LRU_DISPOSE; } spin_unlock(&btp->bt_lru_lock); } @@ -155,8 +154,7 @@ xfs_buf_stale( struct xfs_buftarg *btp = bp->b_target; spin_lock(&btp->bt_lru_lock); - if (!list_empty(&bp->b_lru) && - !(bp->b_lru_flags & _XBF_LRU_DISPOSE)) { + if (!list_empty(&bp->b_lru)) { list_del_init(&bp->b_lru); btp->bt_lru_nr--; atomic_dec(&bp->b_hold); @@ -1503,7 +1501,6 @@ xfs_buftarg_shrink( */ list_move(&bp->b_lru, &dispose); btp->bt_lru_nr--; - bp->b_lru_flags |= _XBF_LRU_DISPOSE; } spin_unlock(&btp->bt_lru_lock); diff --git a/trunk/fs/xfs/xfs_buf.h b/trunk/fs/xfs/xfs_buf.h index 7c0b6a0a1557..d03b73b9604e 100644 --- a/trunk/fs/xfs/xfs_buf.h +++ b/trunk/fs/xfs/xfs_buf.h @@ -38,28 +38,27 @@ typedef enum { XBRW_ZERO = 3, /* Zero target memory */ } xfs_buf_rw_t; -#define XBF_READ (1 << 0) /* buffer intended for reading from device */ -#define XBF_WRITE (1 << 1) /* buffer intended for writing to device */ -#define XBF_READ_AHEAD (1 << 2) /* asynchronous read-ahead */ -#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */ -#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */ -#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */ +#define XBF_READ (1 << 0) /* buffer intended for reading from device */ +#define XBF_WRITE (1 << 1) /* buffer intended for writing to device */ +#define XBF_READ_AHEAD (1 << 2) /* asynchronous read-ahead */ +#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */ +#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */ +#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */ /* I/O hints for the BIO layer */ -#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */ -#define XBF_FUA (1 << 11)/* force cache write through mode */ -#define XBF_FLUSH (1 << 12)/* flush the disk cache before a write */ +#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */ +#define XBF_FUA (1 << 11)/* force cache write through mode */ +#define XBF_FLUSH (1 << 12)/* flush the disk cache before a write */ /* flags used only as arguments to access routines */ -#define XBF_TRYLOCK (1 << 16)/* lock requested, but do not wait */ -#define XBF_UNMAPPED (1 << 17)/* do not map the buffer */ +#define XBF_TRYLOCK (1 << 16)/* lock requested, but do not wait */ +#define XBF_UNMAPPED (1 << 17)/* do not map the buffer */ /* flags used only internally */ -#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */ -#define _XBF_KMEM (1 << 21)/* backed by heap memory */ -#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ -#define _XBF_COMPOUND (1 << 23)/* compound buffer */ -#define _XBF_LRU_DISPOSE (1 << 24)/* buffer being discarded */ +#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */ +#define _XBF_KMEM (1 << 21)/* backed by heap memory */ +#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ +#define _XBF_COMPOUND (1 << 23)/* compound buffer */ typedef unsigned int xfs_buf_flags_t; @@ -73,13 +72,12 @@ typedef unsigned int xfs_buf_flags_t; { XBF_SYNCIO, "SYNCIO" }, \ { XBF_FUA, "FUA" }, \ { XBF_FLUSH, "FLUSH" }, \ - { XBF_TRYLOCK, "TRYLOCK" }, /* should never be set */\ + { XBF_TRYLOCK, "TRYLOCK" }, /* should never be set */\ { XBF_UNMAPPED, "UNMAPPED" }, /* ditto */\ { _XBF_PAGES, "PAGES" }, \ { _XBF_KMEM, "KMEM" }, \ { _XBF_DELWRI_Q, "DELWRI_Q" }, \ - { _XBF_COMPOUND, "COMPOUND" }, \ - { _XBF_LRU_DISPOSE, "LRU_DISPOSE" } + { _XBF_COMPOUND, "COMPOUND" } typedef struct xfs_buftarg { dev_t bt_dev; @@ -126,12 +124,7 @@ typedef struct xfs_buf { xfs_buf_flags_t b_flags; /* status flags */ struct semaphore b_sema; /* semaphore for lockables */ - /* - * concurrent access to b_lru and b_lru_flags are protected by - * bt_lru_lock and not by b_sema - */ struct list_head b_lru; /* lru list */ - xfs_buf_flags_t b_lru_flags; /* internal lru status flags */ wait_queue_head_t b_waiters; /* unpin waiters */ struct list_head b_list; struct xfs_perag *b_pag; /* contains rbtree root */ diff --git a/trunk/fs/xfs/xfs_super.c b/trunk/fs/xfs/xfs_super.c index 19e2380fb867..bdaf4cb9f4a2 100644 --- a/trunk/fs/xfs/xfs_super.c +++ b/trunk/fs/xfs/xfs_super.c @@ -919,7 +919,6 @@ xfs_fs_put_super( struct xfs_mount *mp = XFS_M(sb); xfs_filestream_unmount(mp); - cancel_delayed_work_sync(&mp->m_sync_work); xfs_unmountfs(mp); xfs_syncd_stop(mp); xfs_freesb(mp); diff --git a/trunk/include/asm-generic/unistd.h b/trunk/include/asm-generic/unistd.h index 3748ec92dcbc..991ef01cd77e 100644 --- a/trunk/include/asm-generic/unistd.h +++ b/trunk/include/asm-generic/unistd.h @@ -691,11 +691,9 @@ __SC_COMP(__NR_process_vm_readv, sys_process_vm_readv, \ #define __NR_process_vm_writev 271 __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \ compat_sys_process_vm_writev) -#define __NR_kcmp 272 -__SYSCALL(__NR_kcmp, sys_kcmp) #undef __NR_syscalls -#define __NR_syscalls 273 +#define __NR_syscalls 272 /* * All syscalls below here should go away really, diff --git a/trunk/include/linux/atmel-ssc.h b/trunk/include/linux/atmel-ssc.h index 4eb31752e2b7..06023393fba9 100644 --- a/trunk/include/linux/atmel-ssc.h +++ b/trunk/include/linux/atmel-ssc.h @@ -3,7 +3,6 @@ #include #include -#include struct ssc_device { struct list_head list; diff --git a/trunk/include/linux/compiler-gcc4.h b/trunk/include/linux/compiler-gcc4.h index 934bc34d5f99..2f4079175afb 100644 --- a/trunk/include/linux/compiler-gcc4.h +++ b/trunk/include/linux/compiler-gcc4.h @@ -49,13 +49,6 @@ #endif #endif -#if __GNUC_MINOR__ >= 6 -/* - * Tell the optimizer that something else uses this function or variable. - */ -#define __visible __attribute__((externally_visible)) -#endif - #if __GNUC_MINOR__ > 0 #define __compiletime_object_size(obj) __builtin_object_size(obj, 0) #endif diff --git a/trunk/include/linux/compiler.h b/trunk/include/linux/compiler.h index f430e4162f41..923d093c9cea 100644 --- a/trunk/include/linux/compiler.h +++ b/trunk/include/linux/compiler.h @@ -278,10 +278,6 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); # define __section(S) __attribute__ ((__section__(#S))) #endif -#ifndef __visible -#define __visible -#endif - /* Are two types/vars the same type (ignoring qualifiers)? */ #ifndef __same_type # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) diff --git a/trunk/include/linux/dcache.h b/trunk/include/linux/dcache.h index 59200795482e..caa34e50537e 100644 --- a/trunk/include/linux/dcache.h +++ b/trunk/include/linux/dcache.h @@ -206,8 +206,6 @@ struct dentry_operations { #define DCACHE_MANAGED_DENTRY \ (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) -#define DCACHE_DENTRY_KILLED 0x100000 - extern seqlock_t rename_lock; static inline int dname_external(struct dentry *dentry) diff --git a/trunk/include/linux/filter.h b/trunk/include/linux/filter.h index 2ded090e10f4..3cf5fd561d86 100644 --- a/trunk/include/linux/filter.h +++ b/trunk/include/linux/filter.h @@ -75,7 +75,6 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */ #define BPF_RSH 0x70 #define BPF_NEG 0x80 #define BPF_MOD 0x90 -#define BPF_XOR 0xa0 #define BPF_JA 0x00 #define BPF_JEQ 0x10 @@ -205,8 +204,6 @@ enum { BPF_S_ALU_AND_X, BPF_S_ALU_OR_K, BPF_S_ALU_OR_X, - BPF_S_ALU_XOR_K, - BPF_S_ALU_XOR_X, BPF_S_ALU_LSH_K, BPF_S_ALU_LSH_X, BPF_S_ALU_RSH_K, diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index 2385119f8bb0..e02fc682bb68 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -1934,6 +1934,36 @@ static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr, return mgmt->u.action.category == WLAN_CATEGORY_PUBLIC; } +/** + * ieee80211_fhss_chan_to_freq - get channel frequency + * @channel: the FHSS channel + * + * Convert IEEE802.11 FHSS channel to frequency (MHz) + * Ref IEEE 802.11-2007 section 14.6 + */ +static inline int ieee80211_fhss_chan_to_freq(int channel) +{ + if ((channel > 1) && (channel < 96)) + return channel + 2400; + else + return -1; +} + +/** + * ieee80211_freq_to_fhss_chan - get channel + * @freq: the channels frequency + * + * Convert frequency (MHz) to IEEE802.11 FHSS channel + * Ref IEEE 802.11-2007 section 14.6 + */ +static inline int ieee80211_freq_to_fhss_chan(int freq) +{ + if ((freq > 2401) && (freq < 2496)) + return freq - 2400; + else + return -1; +} + /** * ieee80211_dsss_chan_to_freq - get channel center frequency * @channel: the DSSS channel @@ -1970,6 +2000,56 @@ static inline int ieee80211_freq_to_dsss_chan(int freq) return -1; } +/* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back + * Ref IEEE 802.11-2007 section 18.4.6.2 + * + * The channels and frequencies are the same as those defined for DSSS + */ +#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) +#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) + +/* Convert IEEE802.11 ERP channel to frequency (MHz) and back + * Ref IEEE 802.11-2007 section 19.4.2 + */ +#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) +#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) + +/** + * ieee80211_ofdm_chan_to_freq - get channel center frequency + * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz + * @channel: the OFDM channel + * + * Convert IEEE802.11 OFDM channel to center frequency (MHz) + * Ref IEEE 802.11-2007 section 17.3.8.3.2 + */ +static inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) +{ + if ((channel > 0) && (channel <= 200) && + (s_freq >= 4000)) + return s_freq + (channel * 5); + else + return -1; +} + +/** + * ieee80211_freq_to_ofdm_channel - get channel + * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz + * @freq: the frequency + * + * Convert frequency (MHz) to IEEE802.11 OFDM channel + * Ref IEEE 802.11-2007 section 17.3.8.3.2 + * + * This routine selects the channel with the closest center frequency. + */ +static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) +{ + if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && + (s_freq >= 4000)) + return (freq + 2 - s_freq) / 5; + else + return -1; +} + /** * ieee80211_tu_to_usec - convert time units (TU) to microseconds * @tu: the TUs diff --git a/trunk/include/linux/if_link.h b/trunk/include/linux/if_link.h index e4dad4ddf085..24c0dd09af54 100644 --- a/trunk/include/linux/if_link.h +++ b/trunk/include/linux/if_link.h @@ -272,22 +272,6 @@ enum macvlan_mode { #define MACVLAN_FLAG_NOPROMISC 1 -/* VXLAN section */ -enum { - IFLA_VXLAN_UNSPEC, - IFLA_VXLAN_ID, - IFLA_VXLAN_GROUP, - IFLA_VXLAN_LINK, - IFLA_VXLAN_LOCAL, - IFLA_VXLAN_TTL, - IFLA_VXLAN_TOS, - IFLA_VXLAN_LEARNING, - IFLA_VXLAN_AGEING, - IFLA_VXLAN_LIMIT, - __IFLA_VXLAN_MAX -}; -#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) - /* SR-IOV virtual function management section */ enum { @@ -420,16 +404,9 @@ struct ifla_port_vsi { enum { IFLA_IPOIB_UNSPEC, IFLA_IPOIB_PKEY, - IFLA_IPOIB_MODE, - IFLA_IPOIB_UMCAST, __IFLA_IPOIB_MAX }; -enum { - IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */ - IPOIB_MODE_CONNECTED = 1, /* using connected QPs */ -}; - #define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) #endif /* _LINUX_IF_LINK_H */ diff --git a/trunk/include/linux/kernel.h b/trunk/include/linux/kernel.h index 2451f1f7a1d9..594b419b7d20 100644 --- a/trunk/include/linux/kernel.h +++ b/trunk/include/linux/kernel.h @@ -91,7 +91,7 @@ { \ typeof(x) __x = x; \ typeof(divisor) __d = divisor; \ - (((typeof(x))-1) > 0 || (__x) > 0) ? \ + (((typeof(x))-1) >= 0 || (__x) >= 0) ? \ (((__x) + ((__d) / 2)) / (__d)) : \ (((__x) - ((__d) / 2)) / (__d)); \ } \ diff --git a/trunk/include/linux/memory.h b/trunk/include/linux/memory.h index ff9a9f8e0ed9..1ac7f6e405f9 100644 --- a/trunk/include/linux/memory.h +++ b/trunk/include/linux/memory.h @@ -19,7 +19,7 @@ #include #include -#define MIN_MEMORY_BLOCK_SIZE (1UL << SECTION_SIZE_BITS) +#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS) struct memory_block { unsigned long start_section_nr; diff --git a/trunk/include/linux/mfd/core.h b/trunk/include/linux/mfd/core.h index cebe97ee98b8..3a8435a8058f 100644 --- a/trunk/include/linux/mfd/core.h +++ b/trunk/include/linux/mfd/core.h @@ -16,8 +16,6 @@ #include -struct irq_domain; - /* * This struct describes the MFD part ("cell"). * After registration the copy of this structure will become the platform data @@ -100,7 +98,7 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev) extern int mfd_add_devices(struct device *parent, int id, struct mfd_cell *cells, int n_devs, struct resource *mem_base, - int irq_base, struct irq_domain *irq_domain); + int irq_base); extern void mfd_remove_devices(struct device *parent); diff --git a/trunk/include/linux/mfd/tps65217.h b/trunk/include/linux/mfd/tps65217.h index 7cd83d826ed8..12c06870829a 100644 --- a/trunk/include/linux/mfd/tps65217.h +++ b/trunk/include/linux/mfd/tps65217.h @@ -22,9 +22,6 @@ #include #include -/* TPS chip id list */ -#define TPS65217 0xF0 - /* I2C ID for TPS65217 part */ #define TPS65217_I2C_ID 0x24 @@ -251,11 +248,13 @@ struct tps_info { struct tps65217 { struct device *dev; struct tps65217_board *pdata; - unsigned int id; struct regulator_desc desc[TPS65217_NUM_REGULATOR]; struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; struct tps_info *info[TPS65217_NUM_REGULATOR]; struct regmap *regmap; + + /* Client devices */ + struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR]; }; static inline struct tps65217 *dev_to_tps65217(struct device *dev) @@ -263,11 +262,6 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev) return dev_get_drvdata(dev); } -static inline int tps65217_chip_id(struct tps65217 *tps65217) -{ - return tps65217->id; -} - int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, unsigned int *val); int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, diff --git a/trunk/include/linux/micrel_phy.h b/trunk/include/linux/micrel_phy.h index de201203bc7c..61f0905bdc48 100644 --- a/trunk/include/linux/micrel_phy.h +++ b/trunk/include/linux/micrel_phy.h @@ -1,15 +1,3 @@ -/* - * include/linux/micrel_phy.h - * - * Micrel PHY IDs - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - #ifndef _MICREL_PHY_H #define _MICREL_PHY_H @@ -17,11 +5,10 @@ #define PHY_ID_KSZ9021 0x00221610 #define PHY_ID_KS8737 0x00221720 -#define PHY_ID_KSZ8021 0x00221555 -#define PHY_ID_KSZ8041 0x00221510 -#define PHY_ID_KSZ8051 0x00221550 +#define PHY_ID_KS8041 0x00221510 +#define PHY_ID_KS8051 0x00221550 /* both for ks8001 Rev. A/B, and for ks8721 Rev 3. */ -#define PHY_ID_KSZ8001 0x0022161A +#define PHY_ID_KS8001 0x0022161A /* struct phy_device dev_flags definitions */ #define MICREL_PHY_50MHZ_CLK 0x00000001 diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 807a610f193c..6c131f055ab0 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -338,16 +338,18 @@ struct napi_struct { unsigned long state; int weight; - unsigned int gro_count; int (*poll)(struct napi_struct *, int); #ifdef CONFIG_NETPOLL spinlock_t poll_lock; int poll_owner; #endif + + unsigned int gro_count; + struct net_device *dev; + struct list_head dev_list; struct sk_buff *gro_list; struct sk_buff *skb; - struct list_head dev_list; }; enum { @@ -904,8 +906,7 @@ struct netdev_fcoe_hbainfo { * feature set might be less than what was returned by ndo_fix_features()). * Must return >0 or -errno if it changed dev->features itself. * - * int (*ndo_fdb_add)(struct ndmsg *ndm, struct nlattr *tb[], - * struct net_device *dev, + * int (*ndo_fdb_add)(struct ndmsg *ndm, struct net_device *dev, * const unsigned char *addr, u16 flags) * Adds an FDB entry to dev for addr. * int (*ndo_fdb_del)(struct ndmsg *ndm, struct net_device *dev, @@ -1015,7 +1016,6 @@ struct net_device_ops { void (*ndo_neigh_destroy)(struct neighbour *n); int (*ndo_fdb_add)(struct ndmsg *ndm, - struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 flags); diff --git a/trunk/include/linux/netfilter/ipset/ip_set.h b/trunk/include/linux/netfilter/ipset/ip_set.h index 528697b3c152..2edc64cab739 100644 --- a/trunk/include/linux/netfilter/ipset/ip_set.h +++ b/trunk/include/linux/netfilter/ipset/ip_set.h @@ -190,7 +190,6 @@ enum ip_set_dim { * If changed, new revision of iptables match/target is required. */ IPSET_DIM_MAX = 6, - IPSET_BIT_RETURN_NOMATCH = 7, }; /* Option flags for kernel operations */ @@ -199,7 +198,6 @@ enum ip_set_kopt { IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE), IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO), IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE), - IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH), }; #ifdef __KERNEL__ @@ -208,15 +206,9 @@ enum ip_set_kopt { #include #include #include -#include #include #include -#define _IP_SET_MODULE_DESC(a, b, c) \ - MODULE_DESCRIPTION(a " type of IP sets, revisions " b "-" c) -#define IP_SET_MODULE_DESC(a, b, c) \ - _IP_SET_MODULE_DESC(a, __stringify(b), __stringify(c)) - /* Set features */ enum ip_set_feature { IPSET_TYPE_IP_FLAG = 0, @@ -231,8 +223,6 @@ enum ip_set_feature { IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG), IPSET_TYPE_IFACE_FLAG = 5, IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG), - IPSET_TYPE_NOMATCH_FLAG = 6, - IPSET_TYPE_NOMATCH = (1 << IPSET_TYPE_NOMATCH_FLAG), /* Strictly speaking not a feature, but a flag for dumping: * this settype must be dumped last */ IPSET_DUMP_LAST_FLAG = 7, @@ -259,7 +249,7 @@ struct ip_set_type_variant { * returns negative error code, * zero for no match/success to add/delete * positive for matching element */ - int (*kadt)(struct ip_set *set, const struct sk_buff *skb, + int (*kadt)(struct ip_set *set, const struct sk_buff * skb, const struct xt_action_param *par, enum ipset_adt adt, const struct ip_set_adt_opt *opt); @@ -434,8 +424,7 @@ static inline int nla_put_ipaddr4(struct sk_buff *skb, int type, __be32 ipaddr) return ret; } -static inline int nla_put_ipaddr6(struct sk_buff *skb, int type, - const struct in6_addr *ipaddrptr) +static inline int nla_put_ipaddr6(struct sk_buff *skb, int type, const struct in6_addr *ipaddrptr) { struct nlattr *__nested = ipset_nest_start(skb, type); int ret; diff --git a/trunk/include/linux/netfilter/ipset/ip_set_ahash.h b/trunk/include/linux/netfilter/ipset/ip_set_ahash.h index ef9acd3c8450..b114d35aea5e 100644 --- a/trunk/include/linux/netfilter/ipset/ip_set_ahash.h +++ b/trunk/include/linux/netfilter/ipset/ip_set_ahash.h @@ -137,59 +137,50 @@ htable_bits(u32 hashsize) #endif #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) -#ifdef IP_SET_HASH_WITH_MULTI -#define NETS_LENGTH(family) (SET_HOST_MASK(family) + 1) -#else -#define NETS_LENGTH(family) SET_HOST_MASK(family) -#endif /* Network cidr size book keeping when the hash stores different * sized networks */ static void -add_cidr(struct ip_set_hash *h, u8 cidr, u8 nets_length) +add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) { - int i, j; + u8 i; - /* Add in increasing prefix order, so larger cidr first */ - for (i = 0, j = -1; i < nets_length && h->nets[i].nets; i++) { - if (j != -1) - continue; - else if (h->nets[i].cidr < cidr) - j = i; - else if (h->nets[i].cidr == cidr) { - h->nets[i].nets++; - return; - } - } - if (j != -1) { - for (; i > j; i--) { - h->nets[i].cidr = h->nets[i - 1].cidr; - h->nets[i].nets = h->nets[i - 1].nets; - } + ++h->nets[cidr-1].nets; + + pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets); + + if (h->nets[cidr-1].nets > 1) + return; + + /* New cidr size */ + for (i = 0; i < host_mask && h->nets[i].cidr; i++) { + /* Add in increasing prefix order, so larger cidr first */ + if (h->nets[i].cidr < cidr) + swap(h->nets[i].cidr, cidr); } - h->nets[i].cidr = cidr; - h->nets[i].nets = 1; + if (i < host_mask) + h->nets[i].cidr = cidr; } static void -del_cidr(struct ip_set_hash *h, u8 cidr, u8 nets_length) +del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) { - u8 i, j; + u8 i; + + --h->nets[cidr-1].nets; - for (i = 0; i < nets_length - 1 && h->nets[i].cidr != cidr; i++) - ; - h->nets[i].nets--; + pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets); - if (h->nets[i].nets != 0) + if (h->nets[cidr-1].nets != 0) return; - for (j = i; j < nets_length - 1 && h->nets[j].nets; j++) { - h->nets[j].cidr = h->nets[j + 1].cidr; - h->nets[j].nets = h->nets[j + 1].nets; + /* All entries with this cidr size deleted, so cleanup h->cidr[] */ + for (i = 0; i < host_mask - 1 && h->nets[i].cidr; i++) { + if (h->nets[i].cidr == cidr) + h->nets[i].cidr = cidr = h->nets[i+1].cidr; } + h->nets[i - 1].cidr = 0; } -#else -#define NETS_LENGTH(family) 0 #endif /* Destroy the hashtable part of the set */ @@ -211,14 +202,14 @@ ahash_destroy(struct htable *t) /* Calculate the actual memory size of the set data */ static size_t -ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 nets_length) +ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask) { u32 i; struct htable *t = h->table; size_t memsize = sizeof(*h) + sizeof(*t) #ifdef IP_SET_HASH_WITH_NETS - + sizeof(struct ip_set_hash_nets) * nets_length + + sizeof(struct ip_set_hash_nets) * host_mask #endif + jhash_size(t->htable_bits) * sizeof(struct hbucket); @@ -247,7 +238,7 @@ ip_set_hash_flush(struct ip_set *set) } #ifdef IP_SET_HASH_WITH_NETS memset(h->nets, 0, sizeof(struct ip_set_hash_nets) - * NETS_LENGTH(set->family)); + * SET_HOST_MASK(set->family)); #endif h->elements = 0; } @@ -280,6 +271,9 @@ ip_set_hash_destroy(struct ip_set *set) (jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval) \ & jhash_mask(htable_bits)) +#define CONCAT(a, b, c) a##b##c +#define TOKEN(a, b, c) CONCAT(a, b, c) + /* Type/family dependent function prototypes */ #define type_pf_data_equal TOKEN(TYPE, PF, _data_equal) @@ -484,7 +478,7 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags) } #ifdef IP_SET_HASH_WITH_NETS - add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); + add_cidr(h, CIDR(d->cidr), HOST_MASK); #endif h->elements++; out: @@ -519,7 +513,7 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags) n->pos--; h->elements--; #ifdef IP_SET_HASH_WITH_NETS - del_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); + del_cidr(h, CIDR(d->cidr), HOST_MASK); #endif if (n->pos + AHASH_INIT_SIZE < n->size) { void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) @@ -552,10 +546,10 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) const struct type_pf_elem *data; int i, j = 0; u32 key, multi = 0; - u8 nets_length = NETS_LENGTH(set->family); + u8 host_mask = SET_HOST_MASK(set->family); pr_debug("test by nets\n"); - for (; j < nets_length && h->nets[j].nets && !multi; j++) { + for (; j < host_mask && h->nets[j].cidr && !multi; j++) { type_pf_data_netmask(d, h->nets[j].cidr); key = HKEY(d, h->initval, t->htable_bits); n = hbucket(t, key); @@ -610,7 +604,7 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb) memsize = ahash_memsize(h, with_timeout(h->timeout) ? sizeof(struct type_pf_telem) : sizeof(struct type_pf_elem), - NETS_LENGTH(set->family)); + set->family == AF_INET ? 32 : 128); read_unlock_bh(&set->lock); nested = ipset_nest_start(skb, IPSET_ATTR_DATA); @@ -696,7 +690,7 @@ type_pf_list(const struct ip_set *set, } static int -type_pf_kadt(struct ip_set *set, const struct sk_buff *skb, +type_pf_kadt(struct ip_set *set, const struct sk_buff * skb, const struct xt_action_param *par, enum ipset_adt adt, const struct ip_set_adt_opt *opt); static int @@ -789,7 +783,7 @@ type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value, /* Delete expired elements from the hashtable */ static void -type_pf_expire(struct ip_set_hash *h, u8 nets_length) +type_pf_expire(struct ip_set_hash *h) { struct htable *t = h->table; struct hbucket *n; @@ -804,7 +798,7 @@ type_pf_expire(struct ip_set_hash *h, u8 nets_length) if (type_pf_data_expired(data)) { pr_debug("expired %u/%u\n", i, j); #ifdef IP_SET_HASH_WITH_NETS - del_cidr(h, CIDR(data->cidr), nets_length); + del_cidr(h, CIDR(data->cidr), HOST_MASK); #endif if (j != n->pos - 1) /* Not last one */ @@ -845,7 +839,7 @@ type_pf_tresize(struct ip_set *set, bool retried) if (!retried) { i = h->elements; write_lock_bh(&set->lock); - type_pf_expire(set->data, NETS_LENGTH(set->family)); + type_pf_expire(set->data); write_unlock_bh(&set->lock); if (h->elements < i) return 0; @@ -910,7 +904,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) if (h->elements >= h->maxelem) /* FIXME: when set is full, we slow down here */ - type_pf_expire(h, NETS_LENGTH(set->family)); + type_pf_expire(h); if (h->elements >= h->maxelem) { if (net_ratelimit()) pr_warning("Set %s is full, maxelem %u reached\n", @@ -939,8 +933,8 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) if (j != AHASH_MAX(h) + 1) { data = ahash_tdata(n, j); #ifdef IP_SET_HASH_WITH_NETS - del_cidr(h, CIDR(data->cidr), NETS_LENGTH(set->family)); - add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); + del_cidr(h, CIDR(data->cidr), HOST_MASK); + add_cidr(h, CIDR(d->cidr), HOST_MASK); #endif type_pf_data_copy(data, d); type_pf_data_timeout_set(data, timeout); @@ -958,7 +952,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) } #ifdef IP_SET_HASH_WITH_NETS - add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); + add_cidr(h, CIDR(d->cidr), HOST_MASK); #endif h->elements++; out: @@ -992,7 +986,7 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) n->pos--; h->elements--; #ifdef IP_SET_HASH_WITH_NETS - del_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); + del_cidr(h, CIDR(d->cidr), HOST_MASK); #endif if (n->pos + AHASH_INIT_SIZE < n->size) { void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) @@ -1022,9 +1016,9 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) struct hbucket *n; int i, j = 0; u32 key, multi = 0; - u8 nets_length = NETS_LENGTH(set->family); + u8 host_mask = SET_HOST_MASK(set->family); - for (; j < nets_length && h->nets[j].nets && !multi; j++) { + for (; j < host_mask && h->nets[j].cidr && !multi; j++) { type_pf_data_netmask(d, h->nets[j].cidr); key = HKEY(d, h->initval, t->htable_bits); n = hbucket(t, key); @@ -1153,7 +1147,7 @@ type_pf_gc(unsigned long ul_set) pr_debug("called\n"); write_lock_bh(&set->lock); - type_pf_expire(h, NETS_LENGTH(set->family)); + type_pf_expire(h); write_unlock_bh(&set->lock); h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ; diff --git a/trunk/include/linux/netfilter/nf_conntrack_ftp.h b/trunk/include/linux/netfilter/nf_conntrack_ftp.h index 8faf3f792d13..28f18df36525 100644 --- a/trunk/include/linux/netfilter/nf_conntrack_ftp.h +++ b/trunk/include/linux/netfilter/nf_conntrack_ftp.h @@ -18,17 +18,13 @@ enum nf_ct_ftp_type { #define FTP_PORT 21 -#define NF_CT_FTP_SEQ_PICKUP (1 << 0) - #define NUM_SEQ_TO_REMEMBER 2 /* This structure exists only once per master */ struct nf_ct_ftp_master { /* Valid seq positions for cmd matching after newline */ u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER]; /* 0 means seq_match_aft_nl not set */ - u_int16_t seq_aft_nl_num[IP_CT_DIR_MAX]; - /* pickup sequence tracking, useful for conntrackd */ - u_int16_t flags[IP_CT_DIR_MAX]; + int seq_aft_nl_num[IP_CT_DIR_MAX]; }; struct nf_conntrack_expect; diff --git a/trunk/include/linux/netfilter/nfnetlink_queue.h b/trunk/include/linux/netfilter/nfnetlink_queue.h index 70ec8c2bc11a..3b1c1360aedf 100644 --- a/trunk/include/linux/netfilter/nfnetlink_queue.h +++ b/trunk/include/linux/netfilter/nfnetlink_queue.h @@ -44,7 +44,6 @@ enum nfqnl_attr_type { NFQA_PAYLOAD, /* opaque data payload */ NFQA_CT, /* nf_conntrack_netlink.h */ NFQA_CT_INFO, /* enum ip_conntrack_info */ - NFQA_CAP_LEN, /* __u32 length of captured packet */ __NFQA_MAX }; diff --git a/trunk/include/linux/netfilter/xt_time.h b/trunk/include/linux/netfilter/xt_time.h index 095886019396..7c37fac576c4 100644 --- a/trunk/include/linux/netfilter/xt_time.h +++ b/trunk/include/linux/netfilter/xt_time.h @@ -17,9 +17,6 @@ enum { /* Match against local time (instead of UTC) */ XT_TIME_LOCAL_TZ = 1 << 0, - /* treat timestart > timestop (e.g. 23:00-01:00) as single period */ - XT_TIME_CONTIGUOUS = 1 << 1, - /* Shortcuts */ XT_TIME_ALL_MONTHDAYS = 0xFFFFFFFE, XT_TIME_ALL_WEEKDAYS = 0xFE, @@ -27,6 +24,4 @@ enum { XT_TIME_MAX_DAYTIME = 24 * 60 * 60 - 1, }; -#define XT_TIME_ALL_FLAGS (XT_TIME_LOCAL_TZ|XT_TIME_CONTIGUOUS) - #endif /* _XT_TIME_H */ diff --git a/trunk/include/linux/netlink.h b/trunk/include/linux/netlink.h index f80c56ac4d82..b3dc992fb25b 100644 --- a/trunk/include/linux/netlink.h +++ b/trunk/include/linux/netlink.h @@ -183,10 +183,10 @@ extern void netlink_table_ungrab(void); /* optional Netlink kernel configuration parameters */ struct netlink_kernel_cfg { unsigned int groups; - unsigned int flags; void (*input)(struct sk_buff *skb); struct mutex *cb_mutex; void (*bind)(int group); + unsigned int flags; }; extern struct sock *__netlink_kernel_create(struct net *net, int unit, diff --git a/trunk/include/linux/nfc.h b/trunk/include/linux/nfc.h index d908d17da56d..6189f27e305b 100644 --- a/trunk/include/linux/nfc.h +++ b/trunk/include/linux/nfc.h @@ -183,15 +183,4 @@ struct sockaddr_nfc_llcp { #define NFC_HEADER_SIZE 1 -/** - * Pseudo-header info for raw socket packets - * First byte is the adapter index - * Second byte contains flags - * - 0x01 - Direction (0=RX, 1=TX) - * - 0x02-0x80 - Reserved - **/ -#define NFC_LLCP_RAW_HEADER_SIZE 2 -#define NFC_LLCP_DIRECTION_RX 0x00 -#define NFC_LLCP_DIRECTION_TX 0x01 - #endif /*__LINUX_NFC_H */ diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h index 7df9b500c804..458416279347 100644 --- a/trunk/include/linux/nl80211.h +++ b/trunk/include/linux/nl80211.h @@ -573,11 +573,6 @@ * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by * its %NL80211_ATTR_WDEV identifier. * - * @NL80211_CMD_CONN_FAILED: connection request to an AP failed; used to - * notify userspace that AP has rejected the connection request from a - * station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON - * is used for this. - * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -724,8 +719,6 @@ enum nl80211_commands { NL80211_CMD_START_P2P_DEVICE, NL80211_CMD_STOP_P2P_DEVICE, - NL80211_CMD_CONN_FAILED, - /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1269,10 +1262,6 @@ enum nl80211_commands { * was used to provide the hint. For the different types of * allowed user regulatory hints see nl80211_user_reg_hint_type. * - * @NL80211_ATTR_CONN_FAILED_REASON: The reason for which AP has rejected - * the connection request from a station. nl80211_connect_failed_reason - * enum has different reasons of connection failure. - * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1528,8 +1517,6 @@ enum nl80211_attrs { NL80211_ATTR_USER_REG_HINT_TYPE, - NL80211_ATTR_CONN_FAILED_REASON, - /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -3058,15 +3045,4 @@ enum nl80211_probe_resp_offload_support_attr { NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1<<3, }; -/** - * enum nl80211_connect_failed_reason - connection request failed reasons - * @NL80211_CONN_FAIL_MAX_CLIENTS: Maximum number of clients that can be - * handled by the AP is reached. - * @NL80211_CONN_FAIL_BLOCKED_CLIENT: Client's MAC is in the AP's blocklist. - */ -enum nl80211_connect_failed_reason { - NL80211_CONN_FAIL_MAX_CLIENTS, - NL80211_CONN_FAIL_BLOCKED_CLIENT, -}; - #endif /* __LINUX_NL80211_H */ diff --git a/trunk/include/linux/perf_event.h b/trunk/include/linux/perf_event.h index bdb41612bfec..33ed9d605f91 100644 --- a/trunk/include/linux/perf_event.h +++ b/trunk/include/linux/perf_event.h @@ -274,8 +274,6 @@ struct perf_event_attr { __u64 branch_sample_type; /* enum branch_sample_type */ }; -#define perf_flags(attr) (*(&(attr)->read_format + 1)) - /* * Ioctls that can be done on a perf event fd: */ diff --git a/trunk/include/linux/ptp_clock_kernel.h b/trunk/include/linux/ptp_clock_kernel.h index f2dc6d8fc680..a644b29f1161 100644 --- a/trunk/include/linux/ptp_clock_kernel.h +++ b/trunk/include/linux/ptp_clock_kernel.h @@ -21,7 +21,6 @@ #ifndef _PTP_CLOCK_KERNEL_H_ #define _PTP_CLOCK_KERNEL_H_ -#include #include #include @@ -42,9 +41,7 @@ struct ptp_clock_request { * struct ptp_clock_info - decribes a PTP hardware clock * * @owner: The clock driver should set to THIS_MODULE. - * @name: A short "friendly name" to identify the clock and to - * help distinguish PHY based devices from MAC based ones. - * The string is not meant to be a unique id. + * @name: A short name to identify the clock. * @max_adj: The maximum possible frequency adjustment, in parts per billon. * @n_alarm: The number of programmable alarms. * @n_ext_ts: The number of external time stamp channels. @@ -96,12 +93,10 @@ struct ptp_clock; /** * ptp_clock_register() - register a PTP hardware clock driver * - * @info: Structure describing the new clock. - * @parent: Pointer to the parent device of the new clock. + * @info: Structure describing the new clock. */ -extern struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, - struct device *parent); +extern struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info); /** * ptp_clock_unregister() - unregister a PTP hardware clock driver diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 439d35ab5673..b8c86648a2f9 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -954,6 +954,7 @@ struct sched_domain { unsigned int smt_gain; int flags; /* See SD_* */ int level; + int idle_buddy; /* cpu assigned to select_idle_sibling() */ /* Runtime fields. */ unsigned long last_balance; /* init to jiffies. units in jiffies */ @@ -1529,9 +1530,6 @@ struct task_struct { * cache last used pipe for splice */ struct pipe_inode_info *splice_pipe; - - struct page_frag task_frag; - #ifdef CONFIG_TASK_DELAY_ACCT struct task_delay_info *delays; #endif diff --git a/trunk/include/linux/security.h b/trunk/include/linux/security.h index d143b8e01954..3dea6a9d568f 100644 --- a/trunk/include/linux/security.h +++ b/trunk/include/linux/security.h @@ -118,7 +118,6 @@ void reset_security_ops(void); extern unsigned long mmap_min_addr; extern unsigned long dac_mmap_min_addr; #else -#define mmap_min_addr 0UL #define dac_mmap_min_addr 0UL #endif diff --git a/trunk/include/linux/xfrm.h b/trunk/include/linux/xfrm.h index 28e493b5b94c..22e61fdf75a2 100644 --- a/trunk/include/linux/xfrm.h +++ b/trunk/include/linux/xfrm.h @@ -84,8 +84,6 @@ struct xfrm_replay_state { __u32 bitmap; }; -#define XFRMA_REPLAY_ESN_MAX 4096 - struct xfrm_replay_state_esn { unsigned int bmp_len; __u32 oseq; diff --git a/trunk/include/net/bluetooth/hci.h b/trunk/include/net/bluetooth/hci.h index 76b2b6bdcf36..23cf413e2acf 100644 --- a/trunk/include/net/bluetooth/hci.h +++ b/trunk/include/net/bluetooth/hci.h @@ -302,11 +302,8 @@ enum { /* ---- HCI Error Codes ---- */ #define HCI_ERROR_AUTH_FAILURE 0x05 -#define HCI_ERROR_CONNECTION_TIMEOUT 0x08 #define HCI_ERROR_REJ_BAD_ADDR 0x0f #define HCI_ERROR_REMOTE_USER_TERM 0x13 -#define HCI_ERROR_REMOTE_LOW_RESOURCES 0x14 -#define HCI_ERROR_REMOTE_POWER_OFF 0x15 #define HCI_ERROR_LOCAL_HOST_TERM 0x16 #define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18 @@ -1249,24 +1246,6 @@ struct hci_ev_simple_pair_complete { bdaddr_t bdaddr; } __packed; -#define HCI_EV_USER_PASSKEY_NOTIFY 0x3b -struct hci_ev_user_passkey_notify { - bdaddr_t bdaddr; - __le32 passkey; -} __packed; - -#define HCI_KEYPRESS_STARTED 0 -#define HCI_KEYPRESS_ENTERED 1 -#define HCI_KEYPRESS_ERASED 2 -#define HCI_KEYPRESS_CLEARED 3 -#define HCI_KEYPRESS_COMPLETED 4 - -#define HCI_EV_KEYPRESS_NOTIFY 0x3c -struct hci_ev_keypress_notify { - bdaddr_t bdaddr; - __u8 type; -} __packed; - #define HCI_EV_REMOTE_HOST_FEATURES 0x3d struct hci_ev_remote_host_features { bdaddr_t bdaddr; diff --git a/trunk/include/net/bluetooth/hci_core.h b/trunk/include/net/bluetooth/hci_core.h index e7d454609881..41d943926d2c 100644 --- a/trunk/include/net/bluetooth/hci_core.h +++ b/trunk/include/net/bluetooth/hci_core.h @@ -303,8 +303,6 @@ struct hci_conn { __u8 pin_length; __u8 enc_key_size; __u8 io_capability; - __u32 passkey_notify; - __u8 passkey_entered; __u16 disc_timeout; unsigned long flags; @@ -430,6 +428,15 @@ static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) test_bit(HCI_CONN_SSP_ENABLED, &conn->flags); } +static inline void hci_conn_hash_init(struct hci_dev *hdev) +{ + struct hci_conn_hash *h = &hdev->conn_hash; + INIT_LIST_HEAD(&h->list); + h->acl_num = 0; + h->sco_num = 0; + h->le_num = 0; +} + static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) { struct hci_conn_hash *h = &hdev->conn_hash; @@ -544,7 +551,9 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, return NULL; } +void hci_acl_connect(struct hci_conn *conn); void hci_acl_disconn(struct hci_conn *conn, __u8 reason); +void hci_add_sco(struct hci_conn *conn, __u16 handle); void hci_setup_sync(struct hci_conn *conn, __u16 handle); void hci_sco_setup(struct hci_conn *conn, __u8 status); @@ -554,7 +563,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev); void hci_conn_check_pending(struct hci_dev *hdev); struct hci_chan *hci_chan_create(struct hci_conn *conn); -void hci_chan_del(struct hci_chan *chan); +int hci_chan_del(struct hci_chan *chan); void hci_chan_list_flush(struct hci_conn *conn); struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, @@ -605,17 +614,11 @@ static inline void hci_conn_put(struct hci_conn *conn) /* ----- HCI Devices ----- */ static inline void hci_dev_put(struct hci_dev *d) { - BT_DBG("%s orig refcnt %d", d->name, - atomic_read(&d->dev.kobj.kref.refcount)); - put_device(&d->dev); } static inline struct hci_dev *hci_dev_hold(struct hci_dev *d) { - BT_DBG("%s orig refcnt %d", d->name, - atomic_read(&d->dev.kobj.kref.refcount)); - get_device(&d->dev); return d; } @@ -1001,7 +1004,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u32 flags, u8 *name, u8 name_len, u8 *dev_class); int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type, u8 reason); + u8 link_type, u8 addr_type); int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, @@ -1024,9 +1027,6 @@ int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); -int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type, u32 passkey, - u8 entered); int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status); diff --git a/trunk/include/net/bluetooth/l2cap.h b/trunk/include/net/bluetooth/l2cap.h index 7ed8e356425a..d206296137e2 100644 --- a/trunk/include/net/bluetooth/l2cap.h +++ b/trunk/include/net/bluetooth/l2cap.h @@ -433,10 +433,11 @@ struct l2cap_chan { struct sock *sk; struct l2cap_conn *conn; - struct kref kref; __u8 state; + atomic_t refcnt; + __le16 psm; __u16 dcid; __u16 scid; diff --git a/trunk/include/net/bluetooth/mgmt.h b/trunk/include/net/bluetooth/mgmt.h index 22980a7c3873..4348ee8bda69 100644 --- a/trunk/include/net/bluetooth/mgmt.h +++ b/trunk/include/net/bluetooth/mgmt.h @@ -405,16 +405,7 @@ struct mgmt_ev_device_connected { __u8 eir[0]; } __packed; -#define MGMT_DEV_DISCONN_UNKNOWN 0x00 -#define MGMT_DEV_DISCONN_TIMEOUT 0x01 -#define MGMT_DEV_DISCONN_LOCAL_HOST 0x02 -#define MGMT_DEV_DISCONN_REMOTE 0x03 - #define MGMT_EV_DEVICE_DISCONNECTED 0x000C -struct mgmt_ev_device_disconnected { - struct mgmt_addr_info addr; - __u8 reason; -} __packed; #define MGMT_EV_CONNECT_FAILED 0x000D struct mgmt_ev_connect_failed { @@ -478,10 +469,3 @@ struct mgmt_ev_device_unblocked { struct mgmt_ev_device_unpaired { struct mgmt_addr_info addr; } __packed; - -#define MGMT_EV_PASSKEY_NOTIFY 0x0017 -struct mgmt_ev_passkey_notify { - struct mgmt_addr_info addr; - __le32 passkey; - __u8 entered; -} __packed; diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 1b4989082244..a9a2be78e73c 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -1580,7 +1580,9 @@ struct cfg80211_gtk_rekey_data { * @set_cqm_txe_config: Configure connection quality monitor TX error * thresholds. * @sched_scan_start: Tell the driver to start a scheduled scan. - * @sched_scan_stop: Tell the driver to stop an ongoing scheduled scan. + * @sched_scan_stop: Tell the driver to stop an ongoing scheduled + * scan. The driver_initiated flag specifies whether the driver + * itself has informed that the scan has stopped. * * @mgmt_frame_register: Notify driver that a management frame type was * registered. Note that this callback may not sleep, and cannot run @@ -1628,7 +1630,7 @@ struct cfg80211_ops { void (*set_wakeup)(struct wiphy *wiphy, bool enabled); struct wireless_dev * (*add_virtual_intf)(struct wiphy *wiphy, - const char *name, + char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params); @@ -3360,25 +3362,6 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, */ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp); -/** - * cfg80211_conn_failed - connection request failed notification - * - * @dev: the netdev - * @mac_addr: the station's address - * @reason: the reason for connection failure - * @gfp: allocation flags - * - * Whenever a station tries to connect to an AP and if the station - * could not connect to the AP as the AP has rejected the connection - * for some reasons, this function is called. - * - * The reason for connection failure can be any of the value from - * nl80211_connect_failed_reason enum - */ -void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, - enum nl80211_connect_failed_reason reason, - gfp_t gfp); - /** * cfg80211_rx_mgmt - notification of received, unprocessed management frame * @wdev: wireless device receiving the frame diff --git a/trunk/include/net/gro_cells.h b/trunk/include/net/gro_cells.h deleted file mode 100644 index 4fd8a4b4b7ee..000000000000 --- a/trunk/include/net/gro_cells.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef _NET_GRO_CELLS_H -#define _NET_GRO_CELLS_H - -#include -#include -#include - -struct gro_cell { - struct sk_buff_head napi_skbs; - struct napi_struct napi; -} ____cacheline_aligned_in_smp; - -struct gro_cells { - unsigned int gro_cells_mask; - struct gro_cell *cells; -}; - -static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb) -{ - unsigned long flags; - struct gro_cell *cell = gcells->cells; - struct net_device *dev = skb->dev; - - if (!cell || skb_cloned(skb) || !(dev->features & NETIF_F_GRO)) { - netif_rx(skb); - return; - } - - if (skb_rx_queue_recorded(skb)) - cell += skb_get_rx_queue(skb) & gcells->gro_cells_mask; - - if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) { - atomic_long_inc(&dev->rx_dropped); - kfree_skb(skb); - return; - } - - spin_lock_irqsave(&cell->napi_skbs.lock, flags); - - __skb_queue_tail(&cell->napi_skbs, skb); - if (skb_queue_len(&cell->napi_skbs) == 1) - napi_schedule(&cell->napi); - - spin_unlock_irqrestore(&cell->napi_skbs.lock, flags); -} - -static inline int gro_cell_poll(struct napi_struct *napi, int budget) -{ - struct gro_cell *cell = container_of(napi, struct gro_cell, napi); - struct sk_buff *skb; - int work_done = 0; - - while (work_done < budget) { - skb = skb_dequeue(&cell->napi_skbs); - if (!skb) - break; - - napi_gro_receive(napi, skb); - work_done++; - } - - if (work_done < budget) - napi_complete(napi); - return work_done; -} - -static inline int gro_cells_init(struct gro_cells *gcells, struct net_device *dev) -{ - int i; - - gcells->gro_cells_mask = roundup_pow_of_two(netif_get_num_default_rss_queues()) - 1; - gcells->cells = kcalloc(sizeof(struct gro_cell), - gcells->gro_cells_mask + 1, - GFP_KERNEL); - if (!gcells->cells) - return -ENOMEM; - - for (i = 0; i <= gcells->gro_cells_mask; i++) { - struct gro_cell *cell = gcells->cells + i; - - skb_queue_head_init(&cell->napi_skbs); - netif_napi_add(dev, &cell->napi, gro_cell_poll, 64); - napi_enable(&cell->napi); - } - return 0; -} - -static inline void gro_cells_destroy(struct gro_cells *gcells) -{ - struct gro_cell *cell = gcells->cells; - int i; - - if (!cell) - return; - for (i = 0; i <= gcells->gro_cells_mask; i++,cell++) { - netif_napi_del(&cell->napi); - skb_queue_purge(&cell->napi_skbs); - } - kfree(gcells->cells); - gcells->cells = NULL; -} - -#endif diff --git a/trunk/include/net/inet_ecn.h b/trunk/include/net/inet_ecn.h index aab73757bc4d..2fa14691869c 100644 --- a/trunk/include/net/inet_ecn.h +++ b/trunk/include/net/inet_ecn.h @@ -15,8 +15,6 @@ enum { INET_ECN_MASK = 3, }; -extern int sysctl_tunnel_ecn_log; - static inline int INET_ECN_is_ce(__u8 dsfield) { return (dsfield & INET_ECN_MASK) == INET_ECN_CE; @@ -147,78 +145,4 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb) return 0; } -/* - * RFC 6080 4.2 - * To decapsulate the inner header at the tunnel egress, a compliant - * tunnel egress MUST set the outgoing ECN field to the codepoint at the - * intersection of the appropriate arriving inner header (row) and outer - * header (column) in Figure 4 - * - * +---------+------------------------------------------------+ - * |Arriving | Arriving Outer Header | - * | Inner +---------+------------+------------+------------+ - * | Header | Not-ECT | ECT(0) | ECT(1) | CE | - * +---------+---------+------------+------------+------------+ - * | Not-ECT | Not-ECT |Not-ECT(!!!)|Not-ECT(!!!)| (!!!)| - * | ECT(0) | ECT(0) | ECT(0) | ECT(1) | CE | - * | ECT(1) | ECT(1) | ECT(1) (!) | ECT(1) | CE | - * | CE | CE | CE | CE(!!!)| CE | - * +---------+---------+------------+------------+------------+ - * - * Figure 4: New IP in IP Decapsulation Behaviour - * - * returns 0 on success - * 1 if something is broken and should be logged (!!! above) - * 2 if packet should be dropped - */ -static inline int INET_ECN_decapsulate(struct sk_buff *skb, - __u8 outer, __u8 inner) -{ - if (INET_ECN_is_not_ect(inner)) { - switch (outer & INET_ECN_MASK) { - case INET_ECN_NOT_ECT: - return 0; - case INET_ECN_ECT_0: - case INET_ECN_ECT_1: - return 1; - case INET_ECN_CE: - return 2; - } - } - - if (INET_ECN_is_ce(outer)) - INET_ECN_set_ce(skb); - - return 0; -} - -static inline int IP_ECN_decapsulate(const struct iphdr *oiph, - struct sk_buff *skb) -{ - __u8 inner; - - if (skb->protocol == htons(ETH_P_IP)) - inner = ip_hdr(skb)->tos; - else if (skb->protocol == htons(ETH_P_IPV6)) - inner = ipv6_get_dsfield(ipv6_hdr(skb)); - else - return 0; - - return INET_ECN_decapsulate(skb, oiph->tos, inner); -} - -static inline int IP6_ECN_decapsulate(const struct ipv6hdr *oipv6h, - struct sk_buff *skb) -{ - __u8 inner; - - if (skb->protocol == htons(ETH_P_IP)) - inner = ip_hdr(skb)->tos; - else if (skb->protocol == htons(ETH_P_IPV6)) - inner = ipv6_get_dsfield(ipv6_hdr(skb)); - else - return 0; - - return INET_ECN_decapsulate(skb, ipv6_get_dsfield(oipv6h), inner); -} #endif diff --git a/trunk/include/net/inet_sock.h b/trunk/include/net/inet_sock.h index 256c1ed2d69a..613cfa401672 100644 --- a/trunk/include/net/inet_sock.h +++ b/trunk/include/net/inet_sock.h @@ -101,8 +101,10 @@ struct inet_cork { __be32 addr; struct ip_options *opt; unsigned int fragsize; - int length; /* Total length of all frames */ struct dst_entry *dst; + int length; /* Total length of all frames */ + struct page *page; + u32 off; u8 tx_flags; }; diff --git a/trunk/include/net/ip6_fib.h b/trunk/include/net/ip6_fib.h index 8a2a203eb15d..cd64cf35a49f 100644 --- a/trunk/include/net/ip6_fib.h +++ b/trunk/include/net/ip6_fib.h @@ -112,8 +112,9 @@ struct rt6_info { struct inet6_dev *rt6i_idev; unsigned long _rt6i_peer; - u32 rt6i_genid; - +#ifdef CONFIG_XFRM + u32 rt6i_flow_cache_genid; +#endif /* more non-fragment space at head required */ unsigned short rt6i_nfheader_len; diff --git a/trunk/include/net/ipip.h b/trunk/include/net/ipip.h index ddc077c51f32..a93cf6d7e94b 100644 --- a/trunk/include/net/ipip.h +++ b/trunk/include/net/ipip.h @@ -2,7 +2,6 @@ #define __NET_IPIP_H 1 #include -#include #include /* Keep error state on tunnel for 30 sec */ @@ -37,8 +36,6 @@ struct ip_tunnel { #endif struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */ unsigned int prl_count; /* # of entries in PRL */ - - struct gro_cells gro_cells; }; struct ip_tunnel_prl_entry { diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index 82558c8decf8..71f8262fc1df 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -973,29 +973,21 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) * generation in software. * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates * that the key is pairwise rather then a shared key. - * @IEEE80211_KEY_FLAG_SW_MGMT_TX: This flag should be set by the driver for a + * @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a * CCMP key if it requires CCMP encryption of management frames (MFP) to * be done in software. * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver * if space should be prepared for the IV, but the IV * itself should not be generated. Do not set together with * @IEEE80211_KEY_FLAG_GENERATE_IV on the same key. - * @IEEE80211_KEY_FLAG_RX_MGMT: This key will be used to decrypt received - * management frames. The flag can help drivers that have a hardware - * crypto implementation that doesn't deal with management frames - * properly by allowing them to not upload the keys to hardware and - * fall back to software crypto. Note that this flag deals only with - * RX, if your crypto engine can't deal with TX you can also set the - * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW. */ enum ieee80211_key_flags { IEEE80211_KEY_FLAG_WMM_STA = 1<<0, IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, - IEEE80211_KEY_FLAG_SW_MGMT_TX = 1<<4, + IEEE80211_KEY_FLAG_SW_MGMT = 1<<4, IEEE80211_KEY_FLAG_PUT_IV_SPACE = 1<<5, - IEEE80211_KEY_FLAG_RX_MGMT = 1<<6, }; /** diff --git a/trunk/include/net/net_namespace.h b/trunk/include/net/net_namespace.h index 4faf6612ecac..d61e2b36d9e3 100644 --- a/trunk/include/net/net_namespace.h +++ b/trunk/include/net/net_namespace.h @@ -110,7 +110,6 @@ struct net { #endif struct netns_ipvs *ipvs; struct sock *diag_nlsk; - atomic_t rt_genid; }; /* @@ -316,14 +315,5 @@ static inline void unregister_net_sysctl_table(struct ctl_table_header *header) } #endif -static inline int rt_genid(struct net *net) -{ - return atomic_read(&net->rt_genid); -} - -static inline void rt_genid_bump(struct net *net) -{ - atomic_inc(&net->rt_genid); -} #endif /* __NET_NET_NAMESPACE_H */ diff --git a/trunk/include/net/netns/ipv4.h b/trunk/include/net/netns/ipv4.h index 2ae2b8372cfd..7d00583d53da 100644 --- a/trunk/include/net/netns/ipv4.h +++ b/trunk/include/net/netns/ipv4.h @@ -64,6 +64,7 @@ struct netns_ipv4 { kgid_t sysctl_ping_group_range[2]; long sysctl_tcp_mem[3]; + atomic_t rt_genid; atomic_t dev_addr_genid; #ifdef CONFIG_IP_MROUTE diff --git a/trunk/include/net/nfc/hci.h b/trunk/include/net/nfc/hci.h index e900072950cb..f5169b04f082 100644 --- a/trunk/include/net/nfc/hci.h +++ b/trunk/include/net/nfc/hci.h @@ -30,11 +30,6 @@ struct nfc_hci_ops { int (*open) (struct nfc_hci_dev *hdev); void (*close) (struct nfc_hci_dev *hdev); int (*hci_ready) (struct nfc_hci_dev *hdev); - /* - * xmit must always send the complete buffer before - * returning. Returned result must be 0 for success - * or negative for failure. - */ int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); int (*start_poll) (struct nfc_hci_dev *hdev, u32 im_protocols, u32 tm_protocols); @@ -43,8 +38,8 @@ struct nfc_hci_ops { int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, struct nfc_target *target); int (*data_exchange) (struct nfc_hci_dev *hdev, - struct nfc_target *target, struct sk_buff *skb, - data_exchange_cb_t cb, void *cb_context); + struct nfc_target *target, + struct sk_buff *skb, struct sk_buff **res_skb); int (*check_presence)(struct nfc_hci_dev *hdev, struct nfc_target *target); }; @@ -79,6 +74,7 @@ struct nfc_hci_dev { struct list_head msg_tx_queue; + struct workqueue_struct *msg_tx_wq; struct work_struct msg_tx_work; struct timer_list cmd_timer; @@ -86,14 +82,13 @@ struct nfc_hci_dev { struct sk_buff_head rx_hcp_frags; + struct workqueue_struct *msg_rx_wq; struct work_struct msg_rx_work; struct sk_buff_head msg_rx_queue; struct nfc_hci_ops *ops; - struct nfc_llc *llc; - struct nfc_hci_init_data init_data; void *clientdata; @@ -110,17 +105,12 @@ struct nfc_hci_dev { u8 hw_mpw; u8 hw_software; u8 hw_bsid; - - int async_cb_type; - data_exchange_cb_t async_cb; - void *async_cb_context; }; /* hci device allocation */ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, struct nfc_hci_init_data *init_data, u32 protocols, - const char *llc_name, int tx_headroom, int tx_tailroom, int max_link_payload); @@ -212,9 +202,6 @@ int nfc_hci_set_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, const u8 *param, size_t param_len); int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, const u8 *param, size_t param_len, struct sk_buff **skb); -int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, - const u8 *param, size_t param_len, - data_exchange_cb_t cb, void *cb_context); int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response, const u8 *param, size_t param_len); int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, diff --git a/trunk/include/net/nfc/llc.h b/trunk/include/net/nfc/llc.h deleted file mode 100644 index 400ab7ae749d..000000000000 --- a/trunk/include/net/nfc/llc.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Link Layer Control manager public interface - * - * Copyright (C) 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __NFC_LLC_H_ -#define __NFC_LLC_H_ - -#include -#include - -#define LLC_NOP_NAME "nop" -#define LLC_SHDLC_NAME "shdlc" - -typedef void (*rcv_to_hci_t) (struct nfc_hci_dev *hdev, struct sk_buff *skb); -typedef int (*xmit_to_drv_t) (struct nfc_hci_dev *hdev, struct sk_buff *skb); -typedef void (*llc_failure_t) (struct nfc_hci_dev *hdev, int err); - -struct nfc_llc; - -struct nfc_llc *nfc_llc_allocate(const char *name, struct nfc_hci_dev *hdev, - xmit_to_drv_t xmit_to_drv, - rcv_to_hci_t rcv_to_hci, int tx_headroom, - int tx_tailroom, llc_failure_t llc_failure); -void nfc_llc_free(struct nfc_llc *llc); - -void nfc_llc_get_rx_head_tail_room(struct nfc_llc *llc, int *rx_headroom, - int *rx_tailroom); - - -int nfc_llc_start(struct nfc_llc *llc); -int nfc_llc_stop(struct nfc_llc *llc); -void nfc_llc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb); -int nfc_llc_xmit_from_hci(struct nfc_llc *llc, struct sk_buff *skb); - -int nfc_llc_init(void); -void nfc_llc_exit(void); - -#endif /* __NFC_LLC_H_ */ diff --git a/trunk/include/net/nfc/nci.h b/trunk/include/net/nfc/nci.h index 88785e5c6b2c..276094b91d7c 100644 --- a/trunk/include/net/nfc/nci.h +++ b/trunk/include/net/nfc/nci.h @@ -32,7 +32,6 @@ #define NCI_MAX_NUM_MAPPING_CONFIGS 10 #define NCI_MAX_NUM_RF_CONFIGS 10 #define NCI_MAX_NUM_CONN 10 -#define NCI_MAX_PARAM_LEN 251 /* NCI Status Codes */ #define NCI_STATUS_OK 0x00 @@ -103,9 +102,6 @@ #define NCI_RF_INTERFACE_ISO_DEP 0x02 #define NCI_RF_INTERFACE_NFC_DEP 0x03 -/* NCI Configuration Parameter Tags */ -#define NCI_PN_ATR_REQ_GEN_BYTES 0x29 - /* NCI Reset types */ #define NCI_RESET_TYPE_KEEP_CONFIG 0x00 #define NCI_RESET_TYPE_RESET_CONFIG 0x01 @@ -192,18 +188,6 @@ struct nci_core_reset_cmd { #define NCI_OP_CORE_INIT_CMD nci_opcode_pack(NCI_GID_CORE, 0x01) -#define NCI_OP_CORE_SET_CONFIG_CMD nci_opcode_pack(NCI_GID_CORE, 0x02) -struct set_config_param { - __u8 id; - __u8 len; - __u8 val[NCI_MAX_PARAM_LEN]; -} __packed; - -struct nci_core_set_config_cmd { - __u8 num_params; - struct set_config_param param; /* support 1 param per cmd is enough */ -} __packed; - #define NCI_OP_RF_DISCOVER_MAP_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x00) struct disc_map_config { __u8 rf_protocol; @@ -268,13 +252,6 @@ struct nci_core_init_rsp_2 { __le32 manufact_specific_info; } __packed; -#define NCI_OP_CORE_SET_CONFIG_RSP nci_opcode_pack(NCI_GID_CORE, 0x02) -struct nci_core_set_config_rsp { - __u8 status; - __u8 num_params; - __u8 params_id[0]; /* variable size array */ -} __packed; - #define NCI_OP_RF_DISCOVER_MAP_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x00) #define NCI_OP_RF_DISCOVER_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x03) @@ -351,11 +328,6 @@ struct activation_params_nfcb_poll_iso_dep { __u8 attrib_res[50]; }; -struct activation_params_poll_nfc_dep { - __u8 atr_res_len; - __u8 atr_res[63]; -}; - struct nci_rf_intf_activated_ntf { __u8 rf_discovery_id; __u8 rf_interface; @@ -379,7 +351,6 @@ struct nci_rf_intf_activated_ntf { union { struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep; struct activation_params_nfcb_poll_iso_dep nfcb_poll_iso_dep; - struct activation_params_poll_nfc_dep poll_nfc_dep; } activation_params; } __packed; diff --git a/trunk/include/net/nfc/nci_core.h b/trunk/include/net/nfc/nci_core.h index d705d8674949..feba74027ff8 100644 --- a/trunk/include/net/nfc/nci_core.h +++ b/trunk/include/net/nfc/nci_core.h @@ -54,7 +54,6 @@ enum nci_state { /* NCI timeouts */ #define NCI_RESET_TIMEOUT 5000 #define NCI_INIT_TIMEOUT 5000 -#define NCI_SET_CONFIG_TIMEOUT 5000 #define NCI_RF_DISC_TIMEOUT 5000 #define NCI_RF_DISC_SELECT_TIMEOUT 5000 #define NCI_RF_DEACTIVATE_TIMEOUT 30000 @@ -138,10 +137,6 @@ struct nci_dev { data_exchange_cb_t data_exchange_cb; void *data_exchange_cb_context; struct sk_buff *rx_data_reassembly; - - /* stored during intf_activated_ntf */ - __u8 remote_gb[NFC_MAX_GT_LEN]; - __u8 remote_gb_len; }; /* ----- NCI Devices ----- */ diff --git a/trunk/include/net/nfc/nfc.h b/trunk/include/net/nfc/nfc.h index f05b10682c9d..6735909f826d 100644 --- a/trunk/include/net/nfc/nfc.h +++ b/trunk/include/net/nfc/nfc.h @@ -72,7 +72,6 @@ struct nfc_ops { #define NFC_TARGET_IDX_ANY -1 #define NFC_MAX_GT_LEN 48 -#define NFC_ATR_RES_GT_OFFSET 15 struct nfc_target { u32 idx; @@ -113,6 +112,7 @@ struct nfc_dev { int tx_tailroom; struct timer_list check_pres_timer; + struct workqueue_struct *check_pres_wq; struct work_struct check_pres_work; struct nfc_ops *ops; diff --git a/trunk/include/net/nfc/shdlc.h b/trunk/include/net/nfc/shdlc.h new file mode 100644 index 000000000000..35e930d2f638 --- /dev/null +++ b/trunk/include/net/nfc/shdlc.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __NFC_SHDLC_H +#define __NFC_SHDLC_H + +struct nfc_shdlc; + +struct nfc_shdlc_ops { + int (*open) (struct nfc_shdlc *shdlc); + void (*close) (struct nfc_shdlc *shdlc); + int (*hci_ready) (struct nfc_shdlc *shdlc); + int (*xmit) (struct nfc_shdlc *shdlc, struct sk_buff *skb); + int (*start_poll) (struct nfc_shdlc *shdlc, + u32 im_protocols, u32 tm_protocols); + int (*target_from_gate) (struct nfc_shdlc *shdlc, u8 gate, + struct nfc_target *target); + int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate, + struct nfc_target *target); + int (*data_exchange) (struct nfc_shdlc *shdlc, + struct nfc_target *target, + struct sk_buff *skb, struct sk_buff **res_skb); + int (*check_presence)(struct nfc_shdlc *shdlc, + struct nfc_target *target); +}; + +enum shdlc_state { + SHDLC_DISCONNECTED = 0, + SHDLC_CONNECTING = 1, + SHDLC_NEGOCIATING = 2, + SHDLC_CONNECTED = 3 +}; + +struct nfc_shdlc { + struct mutex state_mutex; + enum shdlc_state state; + int hard_fault; + + struct nfc_hci_dev *hdev; + + wait_queue_head_t *connect_wq; + int connect_tries; + int connect_result; + struct timer_list connect_timer;/* aka T3 in spec 10.6.1 */ + + u8 w; /* window size */ + bool srej_support; + + struct timer_list t1_timer; /* send ack timeout */ + bool t1_active; + + struct timer_list t2_timer; /* guard/retransmit timeout */ + bool t2_active; + + int ns; /* next seq num for send */ + int nr; /* next expected seq num for receive */ + int dnr; /* oldest sent unacked seq num */ + + struct sk_buff_head rcv_q; + + struct sk_buff_head send_q; + bool rnr; /* other side is not ready to receive */ + + struct sk_buff_head ack_pending_q; + + struct workqueue_struct *sm_wq; + struct work_struct sm_work; + + struct nfc_shdlc_ops *ops; + + int client_headroom; + int client_tailroom; + + void *clientdata; +}; + +void nfc_shdlc_recv_frame(struct nfc_shdlc *shdlc, struct sk_buff *skb); + +struct nfc_shdlc *nfc_shdlc_allocate(struct nfc_shdlc_ops *ops, + struct nfc_hci_init_data *init_data, + u32 protocols, + int tx_headroom, int tx_tailroom, + int max_link_payload, const char *devname); + +void nfc_shdlc_free(struct nfc_shdlc *shdlc); + +void nfc_shdlc_set_clientdata(struct nfc_shdlc *shdlc, void *clientdata); +void *nfc_shdlc_get_clientdata(struct nfc_shdlc *shdlc); +struct nfc_hci_dev *nfc_shdlc_get_hci_dev(struct nfc_shdlc *shdlc); + +#endif /* __NFC_SHDLC_H */ diff --git a/trunk/include/net/scm.h b/trunk/include/net/scm.h index 975cca01048b..456695f5cbc4 100644 --- a/trunk/include/net/scm.h +++ b/trunk/include/net/scm.h @@ -73,7 +73,7 @@ static __inline__ void scm_destroy_cred(struct scm_cookie *scm) static __inline__ void scm_destroy(struct scm_cookie *scm) { scm_destroy_cred(scm); - if (scm->fp) + if (scm && scm->fp) __scm_destroy(scm); } diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index c9175562039f..84bdaeca1314 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -247,7 +247,8 @@ struct cg_proto; * @sk_stamp: time stamp of last packet received * @sk_socket: Identd and reporting IO signals * @sk_user_data: RPC layer private data - * @sk_frag: cached page frag + * @sk_sndmsg_page: cached page for sendmsg + * @sk_sndmsg_off: cached offset for sendmsg * @sk_peek_off: current peek_offset value * @sk_send_head: front of stuff to transmit * @sk_security: used by security modules @@ -361,8 +362,9 @@ struct sock { ktime_t sk_stamp; struct socket *sk_socket; void *sk_user_data; - struct page_frag sk_frag; + struct page *sk_sndmsg_page; struct sk_buff *sk_send_head; + __u32 sk_sndmsg_off; __s32 sk_peek_off; int sk_write_pending; #ifdef CONFIG_SECURITY @@ -1339,7 +1341,7 @@ static inline bool sk_wmem_schedule(struct sock *sk, int size) } static inline bool -sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size) +sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, unsigned int size) { if (!sk_has_account(sk)) return true; @@ -2032,23 +2034,18 @@ static inline void sk_stream_moderate_sndbuf(struct sock *sk) struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp); -/** - * sk_page_frag - return an appropriate page_frag - * @sk: socket - * - * If socket allocation mode allows current thread to sleep, it means its - * safe to use the per task page_frag instead of the per socket one. - */ -static inline struct page_frag *sk_page_frag(struct sock *sk) +static inline struct page *sk_stream_alloc_page(struct sock *sk) { - if (sk->sk_allocation & __GFP_WAIT) - return ¤t->task_frag; + struct page *page = NULL; - return &sk->sk_frag; + page = alloc_pages(sk->sk_allocation, 0); + if (!page) { + sk_enter_memory_pressure(sk); + sk_stream_moderate_sndbuf(sk); + } + return page; } -extern bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag); - /* * Default write policy as shown to user space via poll/select/SIGIO */ @@ -2229,6 +2226,8 @@ extern int net_msg_warn; extern __u32 sysctl_wmem_max; extern __u32 sysctl_rmem_max; +extern void sk_init(void); + extern int sysctl_optmem_max; extern __u32 sysctl_wmem_default; diff --git a/trunk/include/net/tcp.h b/trunk/include/net/tcp.h index 6feeccd83dd7..a8cb00c0c6d9 100644 --- a/trunk/include/net/tcp.h +++ b/trunk/include/net/tcp.h @@ -1125,7 +1125,6 @@ static inline void tcp_openreq_init(struct request_sock *req, req->cookie_ts = 0; tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq; tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; - tcp_rsk(req)->snt_synack = 0; req->mss = rx_opt->mss_clamp; req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0; ireq->tstamp_ok = rx_opt->tstamp_ok; @@ -1138,15 +1137,6 @@ static inline void tcp_openreq_init(struct request_sock *req, ireq->loc_port = tcp_hdr(skb)->dest; } -/* Compute time elapsed between SYNACK and the ACK completing 3WHS */ -static inline void tcp_synack_rtt_meas(struct sock *sk, - struct request_sock *req) -{ - if (tcp_rsk(req)->snt_synack) - tcp_valid_rtt_meas(sk, - tcp_time_stamp - tcp_rsk(req)->snt_synack); -} - extern void tcp_enter_memory_pressure(struct sock *sk); static inline int keepalive_intvl_when(const struct tcp_sock *tp) diff --git a/trunk/include/target/target_core_backend.h b/trunk/include/target/target_core_backend.h index 941c84bf1065..f1405d335a96 100644 --- a/trunk/include/target/target_core_backend.h +++ b/trunk/include/target/target_core_backend.h @@ -23,9 +23,7 @@ struct se_subsystem_api { struct se_device *(*create_virtdevice)(struct se_hba *, struct se_subsystem_dev *, void *); void (*free_device)(void *); - void (*transport_complete)(struct se_cmd *cmd, - struct scatterlist *, - unsigned char *); + int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *); int (*parse_cdb)(struct se_cmd *cmd); ssize_t (*check_configfs_dev_params)(struct se_hba *, diff --git a/trunk/include/target/target_core_base.h b/trunk/include/target/target_core_base.h index 5be89373ceac..015cea01ae39 100644 --- a/trunk/include/target/target_core_base.h +++ b/trunk/include/target/target_core_base.h @@ -121,7 +121,6 @@ #define SE_INQUIRY_BUF 512 #define SE_MODE_PAGE_BUF 512 -#define SE_SENSE_BUF 96 /* struct se_hba->hba_flags */ enum hba_flags_table { diff --git a/trunk/include/trace/events/kmem.h b/trunk/include/trace/events/kmem.h index 08fa27244da7..5f889f16b0c8 100644 --- a/trunk/include/trace/events/kmem.h +++ b/trunk/include/trace/events/kmem.h @@ -214,7 +214,7 @@ TRACE_EVENT(mm_page_alloc, TP_printk("page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s", __entry->page, - __entry->page ? page_to_pfn(__entry->page) : 0, + page_to_pfn(__entry->page), __entry->order, __entry->migratetype, show_gfp_flags(__entry->gfp_flags)) @@ -240,7 +240,7 @@ DECLARE_EVENT_CLASS(mm_page, TP_printk("page=%p pfn=%lu order=%u migratetype=%d percpu_refill=%d", __entry->page, - __entry->page ? page_to_pfn(__entry->page) : 0, + page_to_pfn(__entry->page), __entry->order, __entry->migratetype, __entry->order == 0) diff --git a/trunk/include/xen/grant_table.h b/trunk/include/xen/grant_table.h index f19fff8650e9..11e27c3af3cb 100644 --- a/trunk/include/xen/grant_table.h +++ b/trunk/include/xen/grant_table.h @@ -187,7 +187,6 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, struct gnttab_map_grant_ref *kmap_ops, struct page **pages, unsigned int count); int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, - struct gnttab_map_grant_ref *kunmap_ops, - struct page **pages, unsigned int count); + struct page **pages, unsigned int count, bool clear_pte); #endif /* __ASM_GNTTAB_H__ */ diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index 42f25952edd9..f65345f9e5bb 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -1046,9 +1046,6 @@ void do_exit(long code) if (tsk->splice_pipe) __free_pipe_info(tsk->splice_pipe); - if (tsk->task_frag.page) - put_page(tsk->task_frag.page); - validate_creds_for_do_exit(tsk); preempt_disable(); diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 01565b9ce0f3..2c8857e12855 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -330,7 +330,6 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) tsk->btrace_seq = 0; #endif tsk->splice_pipe = NULL; - tsk->task_frag.page = NULL; account_kernel_stack(ti, 1); diff --git a/trunk/kernel/pid_namespace.c b/trunk/kernel/pid_namespace.c index 478bad2745e3..baa528d7dfbd 100644 --- a/trunk/kernel/pid_namespace.c +++ b/trunk/kernel/pid_namespace.c @@ -234,19 +234,15 @@ static int pid_ns_ctl_handler(struct ctl_table *table, int write, */ tmp.data = ¤t->nsproxy->pid_ns->last_pid; - return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); + return proc_dointvec(&tmp, write, buffer, lenp, ppos); } -extern int pid_max; -static int zero = 0; static struct ctl_table pid_ns_ctl_table[] = { { .procname = "ns_last_pid", .maxlen = sizeof(int), .mode = 0666, /* permissions are checked in the handler */ .proc_handler = pid_ns_ctl_handler, - .extra1 = &zero, - .extra2 = &pid_max, }, { } }; diff --git a/trunk/kernel/sched/core.c b/trunk/kernel/sched/core.c index 649c9f876cb1..a4ea245f3d85 100644 --- a/trunk/kernel/sched/core.c +++ b/trunk/kernel/sched/core.c @@ -6014,6 +6014,11 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu) * SD_SHARE_PKG_RESOURCE set (Last Level Cache Domain) for this * allows us to avoid some pointer chasing select_idle_sibling(). * + * Iterate domains and sched_groups downward, assigning CPUs to be + * select_idle_sibling() hw buddy. Cross-wiring hw makes bouncing + * due to random perturbation self canceling, ie sw buddies pull + * their counterpart to their CPU's hw counterpart. + * * Also keep a unique ID per domain (we use the first cpu number in * the cpumask of the domain), this allows us to quickly tell if * two cpus are in the same cache domain, see cpus_share_cache(). @@ -6027,8 +6032,40 @@ static void update_top_cache_domain(int cpu) int id = cpu; sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES); - if (sd) + if (sd) { + struct sched_domain *tmp = sd; + struct sched_group *sg, *prev; + bool right; + + /* + * Traverse to first CPU in group, and count hops + * to cpu from there, switching direction on each + * hop, never ever pointing the last CPU rightward. + */ + do { + id = cpumask_first(sched_domain_span(tmp)); + prev = sg = tmp->groups; + right = 1; + + while (cpumask_first(sched_group_cpus(sg)) != id) + sg = sg->next; + + while (!cpumask_test_cpu(cpu, sched_group_cpus(sg))) { + prev = sg; + sg = sg->next; + right = !right; + } + + /* A CPU went down, never point back to domain start. */ + if (right && cpumask_first(sched_group_cpus(sg->next)) == id) + right = false; + + sg = right ? sg->next : prev; + tmp->idle_buddy = cpumask_first(sched_group_cpus(sg)); + } while ((tmp = tmp->child)); + id = cpumask_first(sched_domain_span(sd)); + } rcu_assign_pointer(per_cpu(sd_llc, cpu), sd); per_cpu(sd_llc_id, cpu) = id; diff --git a/trunk/kernel/sched/fair.c b/trunk/kernel/sched/fair.c index 96e2b18b6283..42d9df6a5ca4 100644 --- a/trunk/kernel/sched/fair.c +++ b/trunk/kernel/sched/fair.c @@ -2637,8 +2637,6 @@ static int select_idle_sibling(struct task_struct *p, int target) int cpu = smp_processor_id(); int prev_cpu = task_cpu(p); struct sched_domain *sd; - struct sched_group *sg; - int i; /* * If the task is going to be woken-up on this cpu and if it is @@ -2655,29 +2653,17 @@ static int select_idle_sibling(struct task_struct *p, int target) return prev_cpu; /* - * Otherwise, iterate the domains and find an elegible idle cpu. + * Otherwise, check assigned siblings to find an elegible idle cpu. */ sd = rcu_dereference(per_cpu(sd_llc, target)); - for_each_lower_domain(sd) { - sg = sd->groups; - do { - if (!cpumask_intersects(sched_group_cpus(sg), - tsk_cpus_allowed(p))) - goto next; - - for_each_cpu(i, sched_group_cpus(sg)) { - if (!idle_cpu(i)) - goto next; - } - target = cpumask_first_and(sched_group_cpus(sg), - tsk_cpus_allowed(p)); - goto done; -next: - sg = sg->next; - } while (sg != sd->groups); + for_each_lower_domain(sd) { + if (!cpumask_test_cpu(sd->idle_buddy, tsk_cpus_allowed(p))) + continue; + if (idle_cpu(sd->idle_buddy)) + return sd->idle_buddy; } -done: + return target; } diff --git a/trunk/kernel/time/timekeeping.c b/trunk/kernel/time/timekeeping.c index d3b91e75cecd..34e5eac81424 100644 --- a/trunk/kernel/time/timekeeping.c +++ b/trunk/kernel/time/timekeeping.c @@ -303,11 +303,10 @@ void getnstimeofday(struct timespec *ts) seq = read_seqbegin(&tk->lock); ts->tv_sec = tk->xtime_sec; - nsecs = timekeeping_get_ns(tk); + ts->tv_nsec = timekeeping_get_ns(tk); } while (read_seqretry(&tk->lock, seq)); - ts->tv_nsec = 0; timespec_add_ns(ts, nsecs); } EXPORT_SYMBOL(getnstimeofday); @@ -346,7 +345,6 @@ void ktime_get_ts(struct timespec *ts) { struct timekeeper *tk = &timekeeper; struct timespec tomono; - s64 nsec; unsigned int seq; WARN_ON(timekeeping_suspended); @@ -354,14 +352,13 @@ void ktime_get_ts(struct timespec *ts) do { seq = read_seqbegin(&tk->lock); ts->tv_sec = tk->xtime_sec; - nsec = timekeeping_get_ns(tk); + ts->tv_nsec = timekeeping_get_ns(tk); tomono = tk->wall_to_monotonic; } while (read_seqretry(&tk->lock, seq)); - ts->tv_sec += tomono.tv_sec; - ts->tv_nsec = 0; - timespec_add_ns(ts, nsec + tomono.tv_nsec); + set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec, + ts->tv_nsec + tomono.tv_nsec); } EXPORT_SYMBOL_GPL(ktime_get_ts); @@ -1247,7 +1244,6 @@ void get_monotonic_boottime(struct timespec *ts) { struct timekeeper *tk = &timekeeper; struct timespec tomono, sleep; - s64 nsec; unsigned int seq; WARN_ON(timekeeping_suspended); @@ -1255,15 +1251,14 @@ void get_monotonic_boottime(struct timespec *ts) do { seq = read_seqbegin(&tk->lock); ts->tv_sec = tk->xtime_sec; - nsec = timekeeping_get_ns(tk); + ts->tv_nsec = timekeeping_get_ns(tk); tomono = tk->wall_to_monotonic; sleep = tk->total_sleep_time; } while (read_seqretry(&tk->lock, seq)); - ts->tv_sec += tomono.tv_sec + sleep.tv_sec; - ts->tv_nsec = 0; - timespec_add_ns(ts, nsec + tomono.tv_nsec + sleep.tv_nsec); + set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec, + ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec); } EXPORT_SYMBOL_GPL(get_monotonic_boottime); diff --git a/trunk/kernel/workqueue.c b/trunk/kernel/workqueue.c index 3c5a79e2134c..1e1373bcb3e3 100644 --- a/trunk/kernel/workqueue.c +++ b/trunk/kernel/workqueue.c @@ -1349,16 +1349,8 @@ static void busy_worker_rebind_fn(struct work_struct *work) struct worker *worker = container_of(work, struct worker, rebind_work); struct global_cwq *gcwq = worker->pool->gcwq; - worker_maybe_bind_and_lock(worker); - - /* - * %WORKER_REBIND must be cleared even if the above binding failed; - * otherwise, we may confuse the next CPU_UP cycle or oops / get - * stuck by calling idle_worker_rebind() prematurely. If CPU went - * down again inbetween, %WORKER_UNBOUND would be set, so clearing - * %WORKER_REBIND is always safe. - */ - worker_clr_flags(worker, WORKER_REBIND); + if (worker_maybe_bind_and_lock(worker)) + worker_clr_flags(worker, WORKER_REBIND); spin_unlock_irq(&gcwq->lock); } @@ -3576,17 +3568,18 @@ static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb, #ifdef CONFIG_SMP struct work_for_cpu { - struct work_struct work; + struct completion completion; long (*fn)(void *); void *arg; long ret; }; -static void work_for_cpu_fn(struct work_struct *work) +static int do_work_for_cpu(void *_wfc) { - struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work); - + struct work_for_cpu *wfc = _wfc; wfc->ret = wfc->fn(wfc->arg); + complete(&wfc->completion); + return 0; } /** @@ -3601,11 +3594,19 @@ static void work_for_cpu_fn(struct work_struct *work) */ long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) { - struct work_for_cpu wfc = { .fn = fn, .arg = arg }; + struct task_struct *sub_thread; + struct work_for_cpu wfc = { + .completion = COMPLETION_INITIALIZER_ONSTACK(wfc.completion), + .fn = fn, + .arg = arg, + }; - INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn); - schedule_work_on(cpu, &wfc.work); - flush_work(&wfc.work); + sub_thread = kthread_create(do_work_for_cpu, &wfc, "work_for_cpu"); + if (IS_ERR(sub_thread)) + return PTR_ERR(sub_thread); + kthread_bind(sub_thread, cpu); + wake_up_process(sub_thread); + wait_for_completion(&wfc.completion); return wfc.ret; } EXPORT_SYMBOL_GPL(work_on_cpu); diff --git a/trunk/lib/flex_proportions.c b/trunk/lib/flex_proportions.c index ebf3bac460b0..c785554f9523 100644 --- a/trunk/lib/flex_proportions.c +++ b/trunk/lib/flex_proportions.c @@ -62,7 +62,7 @@ void fprop_global_destroy(struct fprop_global *p) */ bool fprop_new_period(struct fprop_global *p, int periods) { - s64 events; + u64 events; unsigned long flags; local_irq_save(flags); diff --git a/trunk/mm/huge_memory.c b/trunk/mm/huge_memory.c index 141dbb695097..57c4b9309015 100644 --- a/trunk/mm/huge_memory.c +++ b/trunk/mm/huge_memory.c @@ -1811,6 +1811,7 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page, src_page = pte_page(pteval); copy_user_highpage(page, src_page, address, vma); VM_BUG_ON(page_mapcount(src_page) != 1); + VM_BUG_ON(page_count(src_page) != 2); release_pte_page(src_page); /* * ptl mostly unnecessary, but preempt has to diff --git a/trunk/mm/memory_hotplug.c b/trunk/mm/memory_hotplug.c index 6a5b90d0cfd7..3ad25f9d1fc1 100644 --- a/trunk/mm/memory_hotplug.c +++ b/trunk/mm/memory_hotplug.c @@ -126,6 +126,9 @@ static void register_page_bootmem_info_section(unsigned long start_pfn) struct mem_section *ms; struct page *page, *memmap; + if (!pfn_valid(start_pfn)) + return; + section_nr = pfn_to_section_nr(start_pfn); ms = __nr_to_section(section_nr); @@ -184,16 +187,9 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat) end_pfn = pfn + pgdat->node_spanned_pages; /* register_section info */ - for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) { - /* - * Some platforms can assign the same pfn to multiple nodes - on - * node0 as well as nodeN. To avoid registering a pfn against - * multiple nodes we check that this pfn does not already - * reside in some other node. - */ - if (pfn_valid(pfn) && (pfn_to_nid(pfn) == node)) - register_page_bootmem_info_section(pfn); - } + for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) + register_page_bootmem_info_section(pfn); + } #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index c13ea7538891..c66fb875104a 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -584,7 +584,7 @@ static inline void __free_one_page(struct page *page, combined_idx = buddy_idx & page_idx; higher_page = page + (combined_idx - page_idx); buddy_idx = __find_buddy_index(combined_idx, order + 1); - higher_buddy = higher_page + (buddy_idx - combined_idx); + higher_buddy = page + (buddy_idx - combined_idx); if (page_is_buddy(higher_page, higher_buddy, order + 1)) { list_add_tail(&page->lru, &zone->free_area[order].free_list[migratetype]); diff --git a/trunk/mm/slab.c b/trunk/mm/slab.c index c6854759bcf1..811af03a14ef 100644 --- a/trunk/mm/slab.c +++ b/trunk/mm/slab.c @@ -983,7 +983,7 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, } /* The caller cannot use PFMEMALLOC objects, find another one */ - for (i = 0; i < ac->avail; i++) { + for (i = 1; i < ac->avail; i++) { /* If a !PFMEMALLOC object is found, swap them */ if (!is_obj_pfmemalloc(ac->entry[i])) { objp = ac->entry[i]; @@ -1000,7 +1000,7 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, l3 = cachep->nodelists[numa_mem_id()]; if (!list_empty(&l3->slabs_free) && force_refill) { struct slab *slabp = virt_to_slab(objp); - ClearPageSlabPfmemalloc(virt_to_head_page(slabp->s_mem)); + ClearPageSlabPfmemalloc(virt_to_page(slabp->s_mem)); clear_obj_pfmemalloc(&objp); recheck_pfmemalloc_active(cachep, ac); return objp; @@ -1032,7 +1032,7 @@ static void *__ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac, { if (unlikely(pfmemalloc_active)) { /* Some pfmemalloc slabs exist, check if this is one */ - struct page *page = virt_to_head_page(objp); + struct page *page = virt_to_page(objp); if (PageSlabPfmemalloc(page)) set_obj_pfmemalloc(&objp); } diff --git a/trunk/mm/slub.c b/trunk/mm/slub.c index 2fdd96f9e998..8f78e2577031 100644 --- a/trunk/mm/slub.c +++ b/trunk/mm/slub.c @@ -1524,13 +1524,12 @@ static inline void *acquire_slab(struct kmem_cache *s, } static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain); -static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags); /* * Try to allocate a partial slab from a specific node. */ -static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n, - struct kmem_cache_cpu *c, gfp_t flags) +static void *get_partial_node(struct kmem_cache *s, + struct kmem_cache_node *n, struct kmem_cache_cpu *c) { struct page *page, *page2; void *object = NULL; @@ -1546,13 +1545,9 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n, spin_lock(&n->list_lock); list_for_each_entry_safe(page, page2, &n->partial, lru) { - void *t; + void *t = acquire_slab(s, n, page, object == NULL); int available; - if (!pfmemalloc_match(page, flags)) - continue; - - t = acquire_slab(s, n, page, object == NULL); if (!t) break; @@ -1619,7 +1614,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags, if (n && cpuset_zone_allowed_hardwall(zone, flags) && n->nr_partial > s->min_partial) { - object = get_partial_node(s, n, c, flags); + object = get_partial_node(s, n, c); if (object) { /* * Return the object even if @@ -1648,7 +1643,7 @@ static void *get_partial(struct kmem_cache *s, gfp_t flags, int node, void *object; int searchnode = (node == NUMA_NO_NODE) ? numa_node_id() : node; - object = get_partial_node(s, get_node(s, searchnode), c, flags); + object = get_partial_node(s, get_node(s, searchnode), c); if (object || node != NUMA_NO_NODE) return object; diff --git a/trunk/mm/vmscan.c b/trunk/mm/vmscan.c index 99b434b674c0..8d01243d9560 100644 --- a/trunk/mm/vmscan.c +++ b/trunk/mm/vmscan.c @@ -3102,7 +3102,6 @@ int kswapd_run(int nid) /* failure at boot is fatal */ BUG_ON(system_state == SYSTEM_BOOTING); printk("Failed to start kswapd on node %d\n",nid); - pgdat->kswapd = NULL; ret = -1; } return ret; diff --git a/trunk/net/batman-adv/bat_iv_ogm.c b/trunk/net/batman-adv/bat_iv_ogm.c index b02b75dae3a8..df79300dcb7b 100644 --- a/trunk/net/batman-adv/bat_iv_ogm.c +++ b/trunk/net/batman-adv/bat_iv_ogm.c @@ -652,7 +652,6 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, struct batadv_neigh_node *router = NULL; struct batadv_orig_node *orig_node_tmp; struct hlist_node *node; - int if_num; uint8_t sum_orig, sum_neigh; uint8_t *neigh_addr; uint8_t tq_avg; @@ -739,14 +738,12 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, if (router && (neigh_node->tq_avg == router->tq_avg)) { orig_node_tmp = router->orig_node; spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); - if_num = router->if_incoming->if_num; - sum_orig = orig_node_tmp->bcast_own_sum[if_num]; + sum_orig = orig_node_tmp->bcast_own_sum[if_incoming->if_num]; spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); orig_node_tmp = neigh_node->orig_node; spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); - if_num = neigh_node->if_incoming->if_num; - sum_neigh = orig_node_tmp->bcast_own_sum[if_num]; + sum_neigh = orig_node_tmp->bcast_own_sum[if_incoming->if_num]; spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); if (sum_orig >= sum_neigh) diff --git a/trunk/net/batman-adv/bitarray.h b/trunk/net/batman-adv/bitarray.h index cebaae7e148b..a081ce1c0514 100644 --- a/trunk/net/batman-adv/bitarray.h +++ b/trunk/net/batman-adv/bitarray.h @@ -20,8 +20,8 @@ #ifndef _NET_BATMAN_ADV_BITARRAY_H_ #define _NET_BATMAN_ADV_BITARRAY_H_ -/* Returns 1 if the corresponding bit in the given seq_bits indicates true - * and curr_seqno is within range of last_seqno. Otherwise returns 0. +/* returns true if the corresponding bit in the given seq_bits indicates true + * and curr_seqno is within range of last_seqno */ static inline int batadv_test_bit(const unsigned long *seq_bits, uint32_t last_seqno, uint32_t curr_seqno) @@ -32,7 +32,7 @@ static inline int batadv_test_bit(const unsigned long *seq_bits, if (diff < 0 || diff >= BATADV_TQ_LOCAL_WINDOW_SIZE) return 0; else - return test_bit(diff, seq_bits) != 0; + return test_bit(diff, seq_bits); } /* turn corresponding bit on, so we can remember that we got the packet */ diff --git a/trunk/net/batman-adv/soft-interface.c b/trunk/net/batman-adv/soft-interface.c index b9a28d2dd3e8..7b683e0bd668 100644 --- a/trunk/net/batman-adv/soft-interface.c +++ b/trunk/net/batman-adv/soft-interface.c @@ -107,21 +107,18 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p) { struct batadv_priv *bat_priv = netdev_priv(dev); struct sockaddr *addr = p; - uint8_t old_addr[ETH_ALEN]; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - memcpy(old_addr, dev->dev_addr, ETH_ALEN); - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - /* only modify transtable if it has been initialized before */ if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) { - batadv_tt_local_remove(bat_priv, old_addr, + batadv_tt_local_remove(bat_priv, dev->dev_addr, "mac address changed", false); batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX); } + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); dev->addr_assign_type &= ~NET_ADDR_RANDOM; return 0; } diff --git a/trunk/net/bluetooth/af_bluetooth.c b/trunk/net/bluetooth/af_bluetooth.c index 9d49ee6d7219..58f9762b339a 100644 --- a/trunk/net/bluetooth/af_bluetooth.c +++ b/trunk/net/bluetooth/af_bluetooth.c @@ -567,6 +567,8 @@ static void bt_seq_stop(struct seq_file *seq, void *v) static int bt_seq_show(struct seq_file *seq, void *v) { + struct sock *sk; + struct bt_sock *bt; struct bt_seq_state *s = seq->private; struct bt_sock_list *l = s->l; bdaddr_t src_baswapped, dst_baswapped; @@ -581,8 +583,8 @@ static int bt_seq_show(struct seq_file *seq, void *v) seq_putc(seq, '\n'); } else { - struct sock *sk = sk_entry(v); - struct bt_sock *bt = bt_sk(sk); + sk = sk_entry(v); + bt = bt_sk(sk); baswap(&src_baswapped, &bt->src); baswap(&dst_baswapped, &bt->dst); @@ -622,7 +624,7 @@ static int bt_seq_open(struct inode *inode, struct file *file) sk_list = PDE(inode)->data; s = __seq_open_private(file, &bt_seq_ops, sizeof(struct bt_seq_state)); - if (!s) + if (s == NULL) return -ENOMEM; s->l = sk_list; @@ -644,7 +646,7 @@ int bt_procfs_init(struct module* module, struct net *net, const char *name, sk_list->fops.release = seq_release_private; pde = proc_net_fops_create(net, name, 0, &sk_list->fops); - if (!pde) + if (pde == NULL) return -ENOMEM; pde->data = sk_list; diff --git a/trunk/net/bluetooth/bnep/sock.c b/trunk/net/bluetooth/bnep/sock.c index e7154a58465f..5b6cc0bf4dec 100644 --- a/trunk/net/bluetooth/bnep/sock.c +++ b/trunk/net/bluetooth/bnep/sock.c @@ -64,7 +64,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long switch (cmd) { case BNEPCONNADD: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&ca, argp, sizeof(ca))) return -EFAULT; @@ -90,7 +90,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long case BNEPCONNDEL: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&cd, argp, sizeof(cd))) return -EFAULT; diff --git a/trunk/net/bluetooth/cmtp/sock.c b/trunk/net/bluetooth/cmtp/sock.c index aacb802d1ee4..d5cacef52748 100644 --- a/trunk/net/bluetooth/cmtp/sock.c +++ b/trunk/net/bluetooth/cmtp/sock.c @@ -78,7 +78,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long switch (cmd) { case CMTPCONNADD: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&ca, argp, sizeof(ca))) return -EFAULT; @@ -103,7 +103,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long case CMTPCONNDEL: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&cd, argp, sizeof(cd))) return -EFAULT; diff --git a/trunk/net/bluetooth/hci_conn.c b/trunk/net/bluetooth/hci_conn.c index b9196a44f759..3c094e78dde9 100644 --- a/trunk/net/bluetooth/hci_conn.c +++ b/trunk/net/bluetooth/hci_conn.c @@ -31,7 +31,7 @@ #include #include -static void hci_le_create_connection(struct hci_conn *conn) +static void hci_le_connect(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct hci_cp_le_create_conn cp; @@ -55,12 +55,12 @@ static void hci_le_create_connection(struct hci_conn *conn) hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); } -static void hci_le_create_connection_cancel(struct hci_conn *conn) +static void hci_le_connect_cancel(struct hci_conn *conn) { hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); } -static void hci_acl_create_connection(struct hci_conn *conn) +void hci_acl_connect(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct inquiry_entry *ie; @@ -104,7 +104,7 @@ static void hci_acl_create_connection(struct hci_conn *conn) hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); } -static void hci_acl_create_connection_cancel(struct hci_conn *conn) +static void hci_acl_connect_cancel(struct hci_conn *conn) { struct hci_cp_create_conn_cancel cp; @@ -130,7 +130,7 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason) hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); } -static void hci_add_sco(struct hci_conn *conn, __u16 handle) +void hci_add_sco(struct hci_conn *conn, __u16 handle) { struct hci_dev *hdev = conn->hdev; struct hci_cp_add_sco cp; @@ -246,9 +246,9 @@ static void hci_conn_timeout(struct work_struct *work) case BT_CONNECT2: if (conn->out) { if (conn->type == ACL_LINK) - hci_acl_create_connection_cancel(conn); + hci_acl_connect_cancel(conn); else if (conn->type == LE_LINK) - hci_le_create_connection_cancel(conn); + hci_le_connect_cancel(conn); } break; case BT_CONFIG: @@ -471,37 +471,40 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) } EXPORT_SYMBOL(hci_get_route); -static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, - u8 dst_type, u8 sec_level, u8 auth_type) +/* Create SCO, ACL or LE connection. + * Device _must_ be locked */ +struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, + __u8 dst_type, __u8 sec_level, __u8 auth_type) { + struct hci_conn *acl; + struct hci_conn *sco; struct hci_conn *le; - le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); - if (!le) { - le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); - if (le) - return ERR_PTR(-EBUSY); + BT_DBG("%s dst %s", hdev->name, batostr(dst)); - le = hci_conn_add(hdev, LE_LINK, dst); - if (!le) - return ERR_PTR(-ENOMEM); + if (type == LE_LINK) { + le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); + if (!le) { + le = hci_conn_hash_lookup_state(hdev, LE_LINK, + BT_CONNECT); + if (le) + return ERR_PTR(-EBUSY); - le->dst_type = bdaddr_to_le(dst_type); - hci_le_create_connection(le); - } + le = hci_conn_add(hdev, LE_LINK, dst); + if (!le) + return ERR_PTR(-ENOMEM); - le->pending_sec_level = sec_level; - le->auth_type = auth_type; + le->dst_type = bdaddr_to_le(dst_type); + hci_le_connect(le); + } - hci_conn_hold(le); + le->pending_sec_level = sec_level; + le->auth_type = auth_type; - return le; -} + hci_conn_hold(le); -static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, - u8 sec_level, u8 auth_type) -{ - struct hci_conn *acl; + return le; + } acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); if (!acl) { @@ -516,20 +519,10 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, acl->sec_level = BT_SECURITY_LOW; acl->pending_sec_level = sec_level; acl->auth_type = auth_type; - hci_acl_create_connection(acl); + hci_acl_connect(acl); } - return acl; -} - -static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, - bdaddr_t *dst, u8 sec_level, u8 auth_type) -{ - struct hci_conn *acl; - struct hci_conn *sco; - - acl = hci_connect_acl(hdev, dst, sec_level, auth_type); - if (IS_ERR(acl)) + if (type == ACL_LINK) return acl; sco = hci_conn_hash_lookup_ba(hdev, type, dst); @@ -563,25 +556,6 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, return sco; } -/* Create SCO, ACL or LE connection. */ -struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, - __u8 dst_type, __u8 sec_level, __u8 auth_type) -{ - BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type); - - switch (type) { - case LE_LINK: - return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); - case ACL_LINK: - return hci_connect_acl(hdev, dst, sec_level, auth_type); - case SCO_LINK: - case ESCO_LINK: - return hci_connect_sco(hdev, type, dst, sec_level, auth_type); - } - - return ERR_PTR(-EINVAL); -} - /* Check link security requirement */ int hci_conn_check_link_mode(struct hci_conn *conn) { @@ -801,7 +775,7 @@ void hci_conn_check_pending(struct hci_dev *hdev) conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); if (conn) - hci_acl_create_connection(conn); + hci_acl_connect(conn); hci_dev_unlock(hdev); } @@ -939,7 +913,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) return chan; } -void hci_chan_del(struct hci_chan *chan) +int hci_chan_del(struct hci_chan *chan) { struct hci_conn *conn = chan->conn; struct hci_dev *hdev = conn->hdev; @@ -952,6 +926,8 @@ void hci_chan_del(struct hci_chan *chan) skb_queue_purge(&chan->data_q); kfree(chan); + + return 0; } void hci_chan_list_flush(struct hci_conn *conn) diff --git a/trunk/net/bluetooth/hci_core.c b/trunk/net/bluetooth/hci_core.c index 8a0ce706aebd..fa974a19d365 100644 --- a/trunk/net/bluetooth/hci_core.c +++ b/trunk/net/bluetooth/hci_core.c @@ -231,9 +231,6 @@ static void amp_init(struct hci_dev *hdev) /* Read Local AMP Info */ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); - - /* Read Data Blk size */ - hci_send_cmd(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); } static void hci_init_req(struct hci_dev *hdev, unsigned long opt) @@ -271,6 +268,7 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) BT_ERR("Unknown device type %d", hdev->dev_type); break; } + } static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt) @@ -737,8 +735,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) cancel_work_sync(&hdev->le_scan); - cancel_delayed_work(&hdev->power_off); - hci_req_cancel(hdev, ENODEV); hci_req_lock(hdev); @@ -1656,7 +1652,6 @@ struct hci_dev *hci_alloc_dev(void) INIT_LIST_HEAD(&hdev->link_keys); INIT_LIST_HEAD(&hdev->long_term_keys); INIT_LIST_HEAD(&hdev->remote_oob_data); - INIT_LIST_HEAD(&hdev->conn_hash.list); INIT_WORK(&hdev->rx_work, hci_rx_work); INIT_WORK(&hdev->cmd_work, hci_cmd_work); @@ -1679,6 +1674,7 @@ struct hci_dev *hci_alloc_dev(void) hci_init_sysfs(hdev); discovery_init(hdev); + hci_conn_hash_init(hdev); return hdev; } diff --git a/trunk/net/bluetooth/hci_event.c b/trunk/net/bluetooth/hci_event.c index 2022b43c7353..4fd2cf3bcd05 100644 --- a/trunk/net/bluetooth/hci_event.c +++ b/trunk/net/bluetooth/hci_event.c @@ -29,7 +29,6 @@ #include #include -#include /* Handle HCI Event packets */ @@ -304,7 +303,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - if (status) { + if (status != 0) { mgmt_write_scan_failed(hdev, param, status); hdev->discov_timeout = 0; goto done; @@ -926,7 +925,7 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) if (test_bit(HCI_MGMT, &hdev->dev_flags)) mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); - if (rp->status) + if (rp->status != 0) goto unlock; cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); @@ -1892,22 +1891,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) } } -static u8 hci_to_mgmt_reason(u8 err) -{ - switch (err) { - case HCI_ERROR_CONNECTION_TIMEOUT: - return MGMT_DEV_DISCONN_TIMEOUT; - case HCI_ERROR_REMOTE_USER_TERM: - case HCI_ERROR_REMOTE_LOW_RESOURCES: - case HCI_ERROR_REMOTE_POWER_OFF: - return MGMT_DEV_DISCONN_REMOTE; - case HCI_ERROR_LOCAL_HOST_TERM: - return MGMT_DEV_DISCONN_LOCAL_HOST; - default: - return MGMT_DEV_DISCONN_UNKNOWN; - } -} - static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_disconn_complete *ev = (void *) skb->data; @@ -1926,15 +1909,12 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && (conn->type == ACL_LINK || conn->type == LE_LINK)) { - if (ev->status) { + if (ev->status != 0) mgmt_disconnect_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); - } else { - u8 reason = hci_to_mgmt_reason(ev->reason); - + else mgmt_device_disconnected(hdev, &conn->dst, conn->type, - conn->dst_type, reason); - } + conn->dst_type); } if (ev->status == 0) { @@ -3279,65 +3259,6 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); } -static void hci_user_passkey_notify_evt(struct hci_dev *hdev, - struct sk_buff *skb) -{ - struct hci_ev_user_passkey_notify *ev = (void *) skb->data; - struct hci_conn *conn; - - BT_DBG("%s", hdev->name); - - conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); - if (!conn) - return; - - conn->passkey_notify = __le32_to_cpu(ev->passkey); - conn->passkey_entered = 0; - - if (test_bit(HCI_MGMT, &hdev->dev_flags)) - mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, - conn->dst_type, conn->passkey_notify, - conn->passkey_entered); -} - -static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) -{ - struct hci_ev_keypress_notify *ev = (void *) skb->data; - struct hci_conn *conn; - - BT_DBG("%s", hdev->name); - - conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); - if (!conn) - return; - - switch (ev->type) { - case HCI_KEYPRESS_STARTED: - conn->passkey_entered = 0; - return; - - case HCI_KEYPRESS_ENTERED: - conn->passkey_entered++; - break; - - case HCI_KEYPRESS_ERASED: - conn->passkey_entered--; - break; - - case HCI_KEYPRESS_CLEARED: - conn->passkey_entered = 0; - break; - - case HCI_KEYPRESS_COMPLETED: - return; - } - - if (test_bit(HCI_MGMT, &hdev->dev_flags)) - mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, - conn->dst_type, conn->passkey_notify, - conn->passkey_entered); -} - static void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { @@ -3357,7 +3278,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, * initiated the authentication. A traditional auth_complete * event gets always produced as initiator and is also mapped to * the mgmt_auth_failed event */ - if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) + if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); @@ -3702,14 +3623,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_user_passkey_request_evt(hdev, skb); break; - case HCI_EV_USER_PASSKEY_NOTIFY: - hci_user_passkey_notify_evt(hdev, skb); - break; - - case HCI_EV_KEYPRESS_NOTIFY: - hci_keypress_notify_evt(hdev, skb); - break; - case HCI_EV_SIMPLE_PAIR_COMPLETE: hci_simple_pair_complete_evt(hdev, skb); break; diff --git a/trunk/net/bluetooth/hci_sock.c b/trunk/net/bluetooth/hci_sock.c index 07f073935811..bb64331db3b7 100644 --- a/trunk/net/bluetooth/hci_sock.c +++ b/trunk/net/bluetooth/hci_sock.c @@ -490,7 +490,7 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, switch (cmd) { case HCISETRAW: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) return -EPERM; @@ -510,12 +510,12 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, case HCIBLOCKADDR: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_sock_blacklist_add(hdev, (void __user *) arg); case HCIUNBLOCKADDR: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_sock_blacklist_del(hdev, (void __user *) arg); default: @@ -546,22 +546,22 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, case HCIDEVUP: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_open(arg); case HCIDEVDOWN: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_close(arg); case HCIDEVRESET: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_reset(arg); case HCIDEVRESTAT: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_reset_stat(arg); case HCISETSCAN: @@ -573,7 +573,7 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, case HCISETACLMTU: case HCISETSCOMTU: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; return hci_dev_cmd(cmd, argp); case HCIINQUIRY: diff --git a/trunk/net/bluetooth/hidp/sock.c b/trunk/net/bluetooth/hidp/sock.c index 82a829d90b0f..eca3889371c4 100644 --- a/trunk/net/bluetooth/hidp/sock.c +++ b/trunk/net/bluetooth/hidp/sock.c @@ -62,7 +62,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long switch (cmd) { case HIDPCONNADD: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&ca, argp, sizeof(ca))) return -EFAULT; @@ -97,7 +97,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long case HIDPCONNDEL: if (!capable(CAP_NET_ADMIN)) - return -EPERM; + return -EACCES; if (copy_from_user(&cd, argp, sizeof(cd))) return -EFAULT; diff --git a/trunk/net/bluetooth/l2cap_core.c b/trunk/net/bluetooth/l2cap_core.c index a91239dcda41..e0abaf3cb6a5 100644 --- a/trunk/net/bluetooth/l2cap_core.c +++ b/trunk/net/bluetooth/l2cap_core.c @@ -406,7 +406,7 @@ struct l2cap_chan *l2cap_chan_create(void) chan->state = BT_OPEN; - kref_init(&chan->kref); + atomic_set(&chan->refcnt, 1); /* This flag is cleared in l2cap_chan_ready() */ set_bit(CONF_NOT_COMPLETE, &chan->conf_state); @@ -416,10 +416,8 @@ struct l2cap_chan *l2cap_chan_create(void) return chan; } -static void l2cap_chan_destroy(struct kref *kref) +static void l2cap_chan_destroy(struct l2cap_chan *chan) { - struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); - BT_DBG("chan %p", chan); write_lock(&chan_list_lock); @@ -431,16 +429,17 @@ static void l2cap_chan_destroy(struct kref *kref) void l2cap_chan_hold(struct l2cap_chan *c) { - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); - kref_get(&c->kref); + atomic_inc(&c->refcnt); } void l2cap_chan_put(struct l2cap_chan *c) { - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); - kref_put(&c->kref, l2cap_chan_destroy); + if (atomic_dec_and_test(&c->refcnt)) + l2cap_chan_destroy(c); } void l2cap_chan_set_defaults(struct l2cap_chan *chan) @@ -1026,7 +1025,7 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c if (!conn) return; - if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) { + if (chan->mode == L2CAP_MODE_ERTM) { __clear_retrans_timer(chan); __clear_monitor_timer(chan); __clear_ack_timer(chan); @@ -1449,7 +1448,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, int err; BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), - dst_type, __le16_to_cpu(psm)); + dst_type, __le16_to_cpu(chan->psm)); hdev = hci_get_route(dst, src); if (!hdev) diff --git a/trunk/net/bluetooth/mgmt.c b/trunk/net/bluetooth/mgmt.c index aa2ea0a8142c..a3329cbd3e4d 100644 --- a/trunk/net/bluetooth/mgmt.c +++ b/trunk/net/bluetooth/mgmt.c @@ -35,7 +35,7 @@ bool enable_hs; #define MGMT_VERSION 1 -#define MGMT_REVISION 2 +#define MGMT_REVISION 1 static const u16 mgmt_commands[] = { MGMT_OP_READ_INDEX_LIST, @@ -99,7 +99,6 @@ static const u16 mgmt_events[] = { MGMT_EV_DEVICE_BLOCKED, MGMT_EV_DEVICE_UNBLOCKED, MGMT_EV_DEVICE_UNPAIRED, - MGMT_EV_PASSKEY_NOTIFY, }; /* @@ -2892,22 +2891,6 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) if (scan) hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); - if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { - u8 ssp = 1; - - hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); - } - - if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { - struct hci_cp_write_le_host_supported cp; - - cp.le = 1; - cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); - - hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, - sizeof(cp), &cp); - } - update_class(hdev); update_name(hdev, hdev->dev_name); update_eir(hdev); @@ -3094,17 +3077,16 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data) } int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type, u8 reason) + u8 link_type, u8 addr_type) { - struct mgmt_ev_device_disconnected ev; + struct mgmt_addr_info ev; struct sock *sk = NULL; int err; mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); - bacpy(&ev.addr.bdaddr, bdaddr); - ev.addr.type = link_to_bdaddr(link_type, addr_type); - ev.reason = reason; + bacpy(&ev.bdaddr, bdaddr); + ev.type = link_to_bdaddr(link_type, addr_type); err = mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk); @@ -3293,22 +3275,6 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, MGMT_OP_USER_PASSKEY_NEG_REPLY); } -int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type, u32 passkey, - u8 entered) -{ - struct mgmt_ev_passkey_notify ev; - - BT_DBG("%s", hdev->name); - - bacpy(&ev.addr.bdaddr, bdaddr); - ev.addr.type = link_to_bdaddr(link_type, addr_type); - ev.passkey = __cpu_to_le32(passkey); - ev.entered = entered; - - return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL); -} - int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status) { diff --git a/trunk/net/bridge/br_fdb.c b/trunk/net/bridge/br_fdb.c index d9576e6de2b8..02861190a3d4 100644 --- a/trunk/net/bridge/br_fdb.c +++ b/trunk/net/bridge/br_fdb.c @@ -608,8 +608,7 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, } /* Add new permanent fdb entry with RTM_NEWNEIGH */ -int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], - struct net_device *dev, +int br_fdb_add(struct ndmsg *ndm, struct net_device *dev, const unsigned char *addr, u16 nlh_flags) { struct net_bridge_port *p; diff --git a/trunk/net/bridge/br_private.h b/trunk/net/bridge/br_private.h index 9b278c4ebee1..11a984b87e62 100644 --- a/trunk/net/bridge/br_private.h +++ b/trunk/net/bridge/br_private.h @@ -364,7 +364,7 @@ extern void br_fdb_update(struct net_bridge *br, extern int br_fdb_delete(struct ndmsg *ndm, struct net_device *dev, const unsigned char *addr); -extern int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], +extern int br_fdb_add(struct ndmsg *nlh, struct net_device *dev, const unsigned char *addr, u16 nlh_flags); diff --git a/trunk/net/ceph/messenger.c b/trunk/net/ceph/messenger.c index 159aa8bef9e7..24c5eea8c45b 100644 --- a/trunk/net/ceph/messenger.c +++ b/trunk/net/ceph/messenger.c @@ -1073,13 +1073,16 @@ static int write_partial_msg_pages(struct ceph_connection *con) BUG_ON(kaddr == NULL); base = kaddr + con->out_msg_pos.page_pos + bio_offset; crc = crc32c(crc, base, len); - kunmap(page); msg->footer.data_crc = cpu_to_le32(crc); con->out_msg_pos.did_page_crc = true; } ret = ceph_tcp_sendpage(con->sock, page, con->out_msg_pos.page_pos + bio_offset, len, 1); + + if (do_datacrc) + kunmap(page); + if (ret <= 0) goto out; diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index ba4bb118a756..707b12425a79 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -2156,8 +2156,7 @@ static bool can_checksum_protocol(netdev_features_t features, __be16 protocol) static netdev_features_t harmonize_features(struct sk_buff *skb, __be16 protocol, netdev_features_t features) { - if (skb->ip_summed != CHECKSUM_NONE && - !can_checksum_protocol(features, protocol)) { + if (!can_checksum_protocol(features, protocol)) { features &= ~NETIF_F_ALL_CSUM; features &= ~NETIF_F_SG; } else if (illegal_highdma(skb->dev, skb)) { @@ -2645,8 +2644,6 @@ EXPORT_SYMBOL(dev_queue_xmit); =======================================================================*/ int netdev_max_backlog __read_mostly = 1000; -EXPORT_SYMBOL(netdev_max_backlog); - int netdev_tstamp_prequeue __read_mostly = 1; int netdev_budget __read_mostly = 300; int weight_p __read_mostly = 64; /* old backlog weight */ @@ -3348,7 +3345,7 @@ static int __netif_receive_skb(struct sk_buff *skb) if (pt_prev) { if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) - goto drop; + ret = -ENOMEM; else ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } else { diff --git a/trunk/net/core/filter.c b/trunk/net/core/filter.c index 3d92ebb7fbcf..fbe3a8d12570 100644 --- a/trunk/net/core/filter.c +++ b/trunk/net/core/filter.c @@ -187,13 +187,6 @@ unsigned int sk_run_filter(const struct sk_buff *skb, case BPF_S_ALU_OR_K: A |= K; continue; - case BPF_S_ANC_ALU_XOR_X: - case BPF_S_ALU_XOR_X: - A ^= X; - continue; - case BPF_S_ALU_XOR_K: - A ^= K; - continue; case BPF_S_ALU_LSH_X: A <<= X; continue; @@ -341,6 +334,9 @@ unsigned int sk_run_filter(const struct sk_buff *skb, case BPF_S_ANC_CPU: A = raw_smp_processor_id(); continue; + case BPF_S_ANC_ALU_XOR_X: + A ^= X; + continue; case BPF_S_ANC_NLATTR: { struct nlattr *nla; @@ -487,8 +483,6 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) [BPF_ALU|BPF_AND|BPF_X] = BPF_S_ALU_AND_X, [BPF_ALU|BPF_OR|BPF_K] = BPF_S_ALU_OR_K, [BPF_ALU|BPF_OR|BPF_X] = BPF_S_ALU_OR_X, - [BPF_ALU|BPF_XOR|BPF_K] = BPF_S_ALU_XOR_K, - [BPF_ALU|BPF_XOR|BPF_X] = BPF_S_ALU_XOR_X, [BPF_ALU|BPF_LSH|BPF_K] = BPF_S_ALU_LSH_K, [BPF_ALU|BPF_LSH|BPF_X] = BPF_S_ALU_LSH_X, [BPF_ALU|BPF_RSH|BPF_K] = BPF_S_ALU_RSH_K, diff --git a/trunk/net/core/rtnetlink.c b/trunk/net/core/rtnetlink.c index 76d4c2c3c89b..92575370d9f0 100644 --- a/trunk/net/core/rtnetlink.c +++ b/trunk/net/core/rtnetlink.c @@ -2090,8 +2090,7 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) && (dev->priv_flags & IFF_BRIDGE_PORT)) { master = dev->master; - err = master->netdev_ops->ndo_fdb_add(ndm, tb, - dev, addr, + err = master->netdev_ops->ndo_fdb_add(ndm, dev, addr, nlh->nlmsg_flags); if (err) goto out; @@ -2101,8 +2100,7 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) /* Embedded bridge, macvlan, and any other device support */ if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_add) { - err = dev->netdev_ops->ndo_fdb_add(ndm, tb, - dev, addr, + err = dev->netdev_ops->ndo_fdb_add(ndm, dev, addr, nlh->nlmsg_flags); if (!err) { diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index cdc28598f4ef..fe00d1208167 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -340,57 +340,43 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) EXPORT_SYMBOL(build_skb); struct netdev_alloc_cache { - struct page_frag frag; - /* we maintain a pagecount bias, so that we dont dirty cache line - * containing page->_count every time we allocate a fragment. - */ - unsigned int pagecnt_bias; + struct page *page; + unsigned int offset; + unsigned int pagecnt_bias; }; static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache); -#define NETDEV_FRAG_PAGE_MAX_ORDER get_order(32768) -#define NETDEV_FRAG_PAGE_MAX_SIZE (PAGE_SIZE << NETDEV_FRAG_PAGE_MAX_ORDER) -#define NETDEV_PAGECNT_MAX_BIAS NETDEV_FRAG_PAGE_MAX_SIZE +#define NETDEV_PAGECNT_BIAS (PAGE_SIZE / SMP_CACHE_BYTES) static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) { struct netdev_alloc_cache *nc; void *data = NULL; - int order; unsigned long flags; local_irq_save(flags); nc = &__get_cpu_var(netdev_alloc_cache); - if (unlikely(!nc->frag.page)) { + if (unlikely(!nc->page)) { refill: - for (order = NETDEV_FRAG_PAGE_MAX_ORDER; ;) { - gfp_t gfp = gfp_mask; - - if (order) - gfp |= __GFP_COMP | __GFP_NOWARN; - nc->frag.page = alloc_pages(gfp, order); - if (likely(nc->frag.page)) - break; - if (--order < 0) - goto end; - } - nc->frag.size = PAGE_SIZE << order; + nc->page = alloc_page(gfp_mask); + if (unlikely(!nc->page)) + goto end; recycle: - atomic_set(&nc->frag.page->_count, NETDEV_PAGECNT_MAX_BIAS); - nc->pagecnt_bias = NETDEV_PAGECNT_MAX_BIAS; - nc->frag.offset = 0; + atomic_set(&nc->page->_count, NETDEV_PAGECNT_BIAS); + nc->pagecnt_bias = NETDEV_PAGECNT_BIAS; + nc->offset = 0; } - if (nc->frag.offset + fragsz > nc->frag.size) { + if (nc->offset + fragsz > PAGE_SIZE) { /* avoid unnecessary locked operations if possible */ - if ((atomic_read(&nc->frag.page->_count) == nc->pagecnt_bias) || - atomic_sub_and_test(nc->pagecnt_bias, &nc->frag.page->_count)) + if ((atomic_read(&nc->page->_count) == nc->pagecnt_bias) || + atomic_sub_and_test(nc->pagecnt_bias, &nc->page->_count)) goto recycle; goto refill; } - data = page_address(nc->frag.page) + nc->frag.offset; - nc->frag.offset += fragsz; + data = page_address(nc->page) + nc->offset; + nc->offset += fragsz; nc->pagecnt_bias--; end: local_irq_restore(flags); @@ -1669,19 +1655,38 @@ static struct page *linear_to_page(struct page *page, unsigned int *len, unsigned int *offset, struct sk_buff *skb, struct sock *sk) { - struct page_frag *pfrag = sk_page_frag(sk); + struct page *p = sk->sk_sndmsg_page; + unsigned int off; - if (!sk_page_frag_refill(sk, pfrag)) - return NULL; + if (!p) { +new_page: + p = sk->sk_sndmsg_page = alloc_pages(sk->sk_allocation, 0); + if (!p) + return NULL; - *len = min_t(unsigned int, *len, pfrag->size - pfrag->offset); + off = sk->sk_sndmsg_off = 0; + /* hold one ref to this page until it's full */ + } else { + unsigned int mlen; + + /* If we are the only user of the page, we can reset offset */ + if (page_count(p) == 1) + sk->sk_sndmsg_off = 0; + off = sk->sk_sndmsg_off; + mlen = PAGE_SIZE - off; + if (mlen < 64 && mlen < *len) { + put_page(p); + goto new_page; + } - memcpy(page_address(pfrag->page) + pfrag->offset, - page_address(page) + *offset, *len); - *offset = pfrag->offset; - pfrag->offset += *len; + *len = min_t(unsigned int, *len, mlen); + } - return pfrag->page; + memcpy(page_address(p) + off, page_address(page) + *offset, *len); + sk->sk_sndmsg_off += *len; + *offset = off; + + return p; } static bool spd_can_coalesce(const struct splice_pipe_desc *spd, @@ -3483,7 +3488,8 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, skb_shinfo(from)->nr_frags > MAX_SKB_FRAGS) return false; - delta = from->truesize - SKB_TRUESIZE(skb_end_offset(from)); + delta = from->truesize - + SKB_TRUESIZE(skb_end_pointer(from) - from->head); } WARN_ON_ONCE(delta < len); @@ -3496,9 +3502,7 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, if (!skb_cloned(from)) skb_shinfo(from)->nr_frags = 0; - /* if the skb is not cloned this does nothing - * since we set nr_frags to 0. - */ + /* if the skb is cloned this does nothing since we set nr_frags to 0 */ for (i = 0; i < skb_shinfo(from)->nr_frags; i++) skb_frag_ref(from, i); diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index 7eac86463eb2..2693f7649222 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -691,8 +691,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, case SO_KEEPALIVE: #ifdef CONFIG_INET - if (sk->sk_protocol == IPPROTO_TCP && - sk->sk_type == SOCK_STREAM) + if (sk->sk_protocol == IPPROTO_TCP) tcp_set_keepalive(sk, valbool); #endif sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); @@ -1465,6 +1464,19 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) } EXPORT_SYMBOL_GPL(sk_setup_caps); +void __init sk_init(void) +{ + if (totalram_pages <= 4096) { + sysctl_wmem_max = 32767; + sysctl_rmem_max = 32767; + sysctl_wmem_default = 32767; + sysctl_rmem_default = 32767; + } else if (totalram_pages >= 131072) { + sysctl_wmem_max = 131071; + sysctl_rmem_max = 131071; + } +} + /* * Simple resource managers for sockets. */ @@ -1732,45 +1744,6 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, } EXPORT_SYMBOL(sock_alloc_send_skb); -/* On 32bit arches, an skb frag is limited to 2^15 */ -#define SKB_FRAG_PAGE_ORDER get_order(32768) - -bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag) -{ - int order; - - if (pfrag->page) { - if (atomic_read(&pfrag->page->_count) == 1) { - pfrag->offset = 0; - return true; - } - if (pfrag->offset < pfrag->size) - return true; - put_page(pfrag->page); - } - - /* We restrict high order allocations to users that can afford to wait */ - order = (sk->sk_allocation & __GFP_WAIT) ? SKB_FRAG_PAGE_ORDER : 0; - - do { - gfp_t gfp = sk->sk_allocation; - - if (order) - gfp |= __GFP_COMP | __GFP_NOWARN; - pfrag->page = alloc_pages(gfp, order); - if (likely(pfrag->page)) { - pfrag->offset = 0; - pfrag->size = PAGE_SIZE << order; - return true; - } - } while (--order >= 0); - - sk_enter_memory_pressure(sk); - sk_stream_moderate_sndbuf(sk); - return false; -} -EXPORT_SYMBOL(sk_page_frag_refill); - static void __lock_sock(struct sock *sk) __releases(&sk->sk_lock.slock) __acquires(&sk->sk_lock.slock) @@ -2200,8 +2173,8 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_error_report = sock_def_error_report; sk->sk_destruct = sock_def_destruct; - sk->sk_frag.page = NULL; - sk->sk_frag.offset = 0; + sk->sk_sndmsg_page = NULL; + sk->sk_sndmsg_off = 0; sk->sk_peek_off = -1; sk->sk_peer_pid = NULL; @@ -2444,12 +2417,6 @@ void sk_common_release(struct sock *sk) xfrm_sk_free_policy(sk); sk_refcnt_debug_release(sk); - - if (sk->sk_frag.page) { - put_page(sk->sk_frag.page); - sk->sk_frag.page = NULL; - } - sock_put(sk); } EXPORT_SYMBOL(sk_common_release); diff --git a/trunk/net/ipv4/devinet.c b/trunk/net/ipv4/devinet.c index 2a6abc163ed2..7b00556e184b 100644 --- a/trunk/net/ipv4/devinet.c +++ b/trunk/net/ipv4/devinet.c @@ -722,7 +722,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) break; case SIOCSIFFLAGS: - ret = -EPERM; + ret = -EACCES; if (!capable(CAP_NET_ADMIN)) goto out; break; @@ -730,7 +730,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) case SIOCSIFBRDADDR: /* Set the broadcast address */ case SIOCSIFDSTADDR: /* Set the destination address */ case SIOCSIFNETMASK: /* Set the netmask for the interface */ - ret = -EPERM; + ret = -EACCES; if (!capable(CAP_NET_ADMIN)) goto out; ret = -EINVAL; diff --git a/trunk/net/ipv4/igmp.c b/trunk/net/ipv4/igmp.c index 736ab70fd179..3479b98a00a7 100644 --- a/trunk/net/ipv4/igmp.c +++ b/trunk/net/ipv4/igmp.c @@ -1904,7 +1904,6 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) rtnl_unlock(); return ret; } -EXPORT_SYMBOL(ip_mc_leave_group); int ip_mc_source(int add, int omode, struct sock *sk, struct ip_mreq_source *mreqs, int ifindex) diff --git a/trunk/net/ipv4/inetpeer.c b/trunk/net/ipv4/inetpeer.c index c7527f6b9ad9..e1e0a4e8fd34 100644 --- a/trunk/net/ipv4/inetpeer.c +++ b/trunk/net/ipv4/inetpeer.c @@ -510,10 +510,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base, secure_ipv6_id(daddr->addr.a6)); p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW; p->rate_tokens = 0; - /* 60*HZ is arbitrary, but chosen enough high so that the first - * calculation of tokens is at its maximum. - */ - p->rate_last = jiffies - 60*HZ; + p->rate_last = 0; INIT_LIST_HEAD(&p->gc_list); /* Link the node. */ diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index 7240f8e2dd45..f233c1da2077 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -120,10 +120,6 @@ Alexey Kuznetsov. */ -static bool log_ecn_error = true; -module_param(log_ecn_error, bool, 0644); -MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); - static struct rtnl_link_ops ipgre_link_ops __read_mostly; static int ipgre_tunnel_init(struct net_device *dev); static void ipgre_tunnel_setup(struct net_device *dev); @@ -208,9 +204,7 @@ static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev, tot->rx_crc_errors = dev->stats.rx_crc_errors; tot->rx_fifo_errors = dev->stats.rx_fifo_errors; tot->rx_length_errors = dev->stats.rx_length_errors; - tot->rx_frame_errors = dev->stats.rx_frame_errors; tot->rx_errors = dev->stats.rx_errors; - tot->tx_fifo_errors = dev->stats.tx_fifo_errors; tot->tx_carrier_errors = dev->stats.tx_carrier_errors; tot->tx_dropped = dev->stats.tx_dropped; @@ -220,25 +214,11 @@ static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev, return tot; } -/* Does key in tunnel parameters match packet */ -static bool ipgre_key_match(const struct ip_tunnel_parm *p, - __be16 flags, __be32 key) -{ - if (p->i_flags & GRE_KEY) { - if (flags & GRE_KEY) - return key == p->i_key; - else - return false; /* key expected, none present */ - } else - return !(flags & GRE_KEY); -} - /* Given src, dst and key, find appropriate for input tunnel. */ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev, __be32 remote, __be32 local, - __be16 flags, __be32 key, - __be16 gre_proto) + __be32 key, __be16 gre_proto) { struct net *net = dev_net(dev); int link = dev->ifindex; @@ -253,12 +233,10 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev, for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) { if (local != t->parms.iph.saddr || remote != t->parms.iph.daddr || + key != t->parms.i_key || !(t->dev->flags & IFF_UP)) continue; - if (!ipgre_key_match(&t->parms, flags, key)) - continue; - if (t->dev->type != ARPHRD_IPGRE && t->dev->type != dev_type) continue; @@ -279,12 +257,10 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev, for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) { if (remote != t->parms.iph.daddr || + key != t->parms.i_key || !(t->dev->flags & IFF_UP)) continue; - if (!ipgre_key_match(&t->parms, flags, key)) - continue; - if (t->dev->type != ARPHRD_IPGRE && t->dev->type != dev_type) continue; @@ -307,12 +283,10 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev, if ((local != t->parms.iph.saddr && (local != t->parms.iph.daddr || !ipv4_is_multicast(local))) || + key != t->parms.i_key || !(t->dev->flags & IFF_UP)) continue; - if (!ipgre_key_match(&t->parms, flags, key)) - continue; - if (t->dev->type != ARPHRD_IPGRE && t->dev->type != dev_type) continue; @@ -515,7 +489,6 @@ static void ipgre_err(struct sk_buff *skb, u32 info) const int code = icmp_hdr(skb)->code; struct ip_tunnel *t; __be16 flags; - __be32 key = 0; flags = p[0]; if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { @@ -532,9 +505,6 @@ static void ipgre_err(struct sk_buff *skb, u32 info) if (skb_headlen(skb) < grehlen) return; - if (flags & GRE_KEY) - key = *(((__be32 *)p) + (grehlen / 4) - 1); - switch (type) { default: case ICMP_PARAMETERPROB: @@ -563,34 +533,49 @@ static void ipgre_err(struct sk_buff *skb, u32 info) break; } + rcu_read_lock(); t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr, - flags, key, p[1]); - + flags & GRE_KEY ? + *(((__be32 *)p) + (grehlen / 4) - 1) : 0, + p[1]); if (t == NULL) - return; + goto out; if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { ipv4_update_pmtu(skb, dev_net(skb->dev), info, t->parms.link, 0, IPPROTO_GRE, 0); - return; + goto out; } if (type == ICMP_REDIRECT) { ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0, IPPROTO_GRE, 0); - return; + goto out; } if (t->parms.iph.daddr == 0 || ipv4_is_multicast(t->parms.iph.daddr)) - return; + goto out; if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) - return; + goto out; if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) t->err_count++; else t->err_count = 1; t->err_time = jiffies; +out: + rcu_read_unlock(); +} + +static inline void ipgre_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb) +{ + if (INET_ECN_is_ce(iph->tos)) { + if (skb->protocol == htons(ETH_P_IP)) { + IP_ECN_set_ce(ip_hdr(skb)); + } else if (skb->protocol == htons(ETH_P_IPV6)) { + IP6_ECN_set_ce(ipv6_hdr(skb)); + } + } } static inline u8 @@ -615,10 +600,9 @@ static int ipgre_rcv(struct sk_buff *skb) struct ip_tunnel *tunnel; int offset = 4; __be16 gre_proto; - int err; if (!pskb_may_pull(skb, 16)) - goto drop; + goto drop_nolock; iph = ip_hdr(skb); h = skb->data; @@ -629,7 +613,7 @@ static int ipgre_rcv(struct sk_buff *skb) - We do not support routing headers. */ if (flags&(GRE_VERSION|GRE_ROUTING)) - goto drop; + goto drop_nolock; if (flags&GRE_CSUM) { switch (skb->ip_summed) { @@ -657,10 +641,10 @@ static int ipgre_rcv(struct sk_buff *skb) gre_proto = *(__be16 *)(h + 2); - tunnel = ipgre_tunnel_lookup(skb->dev, - iph->saddr, iph->daddr, flags, key, - gre_proto); - if (tunnel) { + rcu_read_lock(); + if ((tunnel = ipgre_tunnel_lookup(skb->dev, + iph->saddr, iph->daddr, key, + gre_proto))) { struct pcpu_tstats *tstats; secpath_reset(skb); @@ -719,33 +703,27 @@ static int ipgre_rcv(struct sk_buff *skb) skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); } - __skb_tunnel_rx(skb, tunnel->dev); - - skb_reset_network_header(skb); - err = IP_ECN_decapsulate(iph, skb); - if (unlikely(err)) { - if (log_ecn_error) - net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", - &iph->saddr, iph->tos); - if (err > 1) { - ++tunnel->dev->stats.rx_frame_errors; - ++tunnel->dev->stats.rx_errors; - goto drop; - } - } - tstats = this_cpu_ptr(tunnel->dev->tstats); u64_stats_update_begin(&tstats->syncp); tstats->rx_packets++; tstats->rx_bytes += skb->len; u64_stats_update_end(&tstats->syncp); - gro_cells_receive(&tunnel->gro_cells, skb); + __skb_tunnel_rx(skb, tunnel->dev); + + skb_reset_network_header(skb); + ipgre_ecn_decapsulate(iph, skb); + + netif_rx(skb); + + rcu_read_unlock(); return 0; } icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); drop: + rcu_read_unlock(); +drop_nolock: kfree_skb(skb); return 0; } @@ -1318,9 +1296,6 @@ static const struct net_device_ops ipgre_netdev_ops = { static void ipgre_dev_free(struct net_device *dev) { - struct ip_tunnel *tunnel = netdev_priv(dev); - - gro_cells_destroy(&tunnel->gro_cells); free_percpu(dev->tstats); free_netdev(dev); } @@ -1352,7 +1327,6 @@ static int ipgre_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel; struct iphdr *iph; - int err; tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; @@ -1379,12 +1353,6 @@ static int ipgre_tunnel_init(struct net_device *dev) if (!dev->tstats) return -ENOMEM; - err = gro_cells_init(&tunnel->gro_cells, dev); - if (err) { - free_percpu(dev->tstats); - return err; - } - return 0; } diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index 24a29a39e9a8..a5beab1dc958 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -793,7 +793,6 @@ static int __ip_append_data(struct sock *sk, struct flowi4 *fl4, struct sk_buff_head *queue, struct inet_cork *cork, - struct page_frag *pfrag, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, @@ -988,30 +987,47 @@ static int __ip_append_data(struct sock *sk, } } else { int i = skb_shinfo(skb)->nr_frags; - - err = -ENOMEM; - if (!sk_page_frag_refill(sk, pfrag)) - goto error; - - if (!skb_can_coalesce(skb, i, pfrag->page, - pfrag->offset)) { - err = -EMSGSIZE; - if (i == MAX_SKB_FRAGS) + skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1]; + struct page *page = cork->page; + int off = cork->off; + unsigned int left; + + if (page && (left = PAGE_SIZE - off) > 0) { + if (copy >= left) + copy = left; + if (page != skb_frag_page(frag)) { + if (i == MAX_SKB_FRAGS) { + err = -EMSGSIZE; + goto error; + } + skb_fill_page_desc(skb, i, page, off, 0); + skb_frag_ref(skb, i); + frag = &skb_shinfo(skb)->frags[i]; + } + } else if (i < MAX_SKB_FRAGS) { + if (copy > PAGE_SIZE) + copy = PAGE_SIZE; + page = alloc_pages(sk->sk_allocation, 0); + if (page == NULL) { + err = -ENOMEM; goto error; + } + cork->page = page; + cork->off = 0; - __skb_fill_page_desc(skb, i, pfrag->page, - pfrag->offset, 0); - skb_shinfo(skb)->nr_frags = ++i; - get_page(pfrag->page); + skb_fill_page_desc(skb, i, page, 0, 0); + frag = &skb_shinfo(skb)->frags[i]; + } else { + err = -EMSGSIZE; + goto error; + } + if (getfrag(from, skb_frag_address(frag)+skb_frag_size(frag), + offset, copy, skb->len, skb) < 0) { + err = -EFAULT; + goto error; } - copy = min_t(int, copy, pfrag->size - pfrag->offset); - if (getfrag(from, - page_address(pfrag->page) + pfrag->offset, - offset, copy, skb->len, skb) < 0) - goto error_efault; - - pfrag->offset += copy; - skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); + cork->off += copy; + skb_frag_size_add(frag, copy); skb->len += copy; skb->data_len += copy; skb->truesize += copy; @@ -1023,8 +1039,6 @@ static int __ip_append_data(struct sock *sk, return 0; -error_efault: - err = -EFAULT; error: cork->length -= length; IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); @@ -1065,6 +1079,8 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, cork->dst = &rt->dst; cork->length = 0; cork->tx_flags = ipc->tx_flags; + cork->page = NULL; + cork->off = 0; return 0; } @@ -1101,8 +1117,7 @@ int ip_append_data(struct sock *sk, struct flowi4 *fl4, transhdrlen = 0; } - return __ip_append_data(sk, fl4, &sk->sk_write_queue, &inet->cork.base, - sk_page_frag(sk), getfrag, + return __ip_append_data(sk, fl4, &sk->sk_write_queue, &inet->cork.base, getfrag, from, length, transhdrlen, flags); } @@ -1424,8 +1439,7 @@ struct sk_buff *ip_make_skb(struct sock *sk, if (err) return ERR_PTR(err); - err = __ip_append_data(sk, fl4, &queue, &cork, - ¤t->task_frag, getfrag, + err = __ip_append_data(sk, fl4, &queue, &cork, getfrag, from, length, transhdrlen, flags); if (err) { __ip_flush_pending_frames(sk, &queue, &cork); diff --git a/trunk/net/ipv4/ip_vti.c b/trunk/net/ipv4/ip_vti.c index 978bca4818ae..3511ffba7bd4 100644 --- a/trunk/net/ipv4/ip_vti.c +++ b/trunk/net/ipv4/ip_vti.c @@ -304,6 +304,7 @@ static int vti_err(struct sk_buff *skb, u32 info) err = -ENOENT; + rcu_read_lock(); t = vti_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); if (t == NULL) goto out; @@ -325,6 +326,7 @@ static int vti_err(struct sk_buff *skb, u32 info) t->err_count = 1; t->err_time = jiffies; out: + rcu_read_unlock(); return err; } @@ -334,6 +336,7 @@ static int vti_rcv(struct sk_buff *skb) struct ip_tunnel *tunnel; const struct iphdr *iph = ip_hdr(skb); + rcu_read_lock(); tunnel = vti_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr); if (tunnel != NULL) { struct pcpu_tstats *tstats; @@ -345,8 +348,10 @@ static int vti_rcv(struct sk_buff *skb) u64_stats_update_end(&tstats->syncp); skb->dev = tunnel->dev; + rcu_read_unlock(); return 1; } + rcu_read_unlock(); return -1; } diff --git a/trunk/net/ipv4/ipconfig.c b/trunk/net/ipv4/ipconfig.c index 798358b10717..1c0e7e051044 100644 --- a/trunk/net/ipv4/ipconfig.c +++ b/trunk/net/ipv4/ipconfig.c @@ -582,17 +582,6 @@ static void __init ic_rarp_send_if(struct ic_device *d) } #endif -/* - * Predefine Nameservers - */ -static inline void __init ic_nameservers_predef(void) -{ - int i; - - for (i = 0; i < CONF_NAMESERVERS_MAX; i++) - ic_nameservers[i] = NONE; -} - /* * DHCP/BOOTP support. */ @@ -753,6 +742,17 @@ static void __init ic_bootp_init_ext(u8 *e) } +/* + * Predefine Nameservers + */ +static inline void __init ic_nameservers_predef(void) +{ + int i; + + for (i = 0; i < CONF_NAMESERVERS_MAX; i++) + ic_nameservers[i] = NONE; +} + /* * Initialize the DHCP/BOOTP mechanism. */ diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index e15b45297c09..99af1f0cc658 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -120,10 +120,6 @@ #define HASH_SIZE 16 #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) -static bool log_ecn_error = true; -module_param(log_ecn_error, bool, 0644); -MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); - static int ipip_net_id __read_mostly; struct ipip_net { struct ip_tunnel __rcu *tunnels_r_l[HASH_SIZE]; @@ -369,6 +365,8 @@ static int ipip_err(struct sk_buff *skb, u32 info) } err = -ENOENT; + + rcu_read_lock(); t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); if (t == NULL) goto out; @@ -400,22 +398,34 @@ static int ipip_err(struct sk_buff *skb, u32 info) t->err_count = 1; t->err_time = jiffies; out: - + rcu_read_unlock(); return err; } +static inline void ipip_ecn_decapsulate(const struct iphdr *outer_iph, + struct sk_buff *skb) +{ + struct iphdr *inner_iph = ip_hdr(skb); + + if (INET_ECN_is_ce(outer_iph->tos)) + IP_ECN_set_ce(inner_iph); +} + static int ipip_rcv(struct sk_buff *skb) { struct ip_tunnel *tunnel; const struct iphdr *iph = ip_hdr(skb); - int err; + rcu_read_lock(); tunnel = ipip_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr); if (tunnel != NULL) { struct pcpu_tstats *tstats; - if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) - goto drop; + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { + rcu_read_unlock(); + kfree_skb(skb); + return 0; + } secpath_reset(skb); @@ -424,35 +434,24 @@ static int ipip_rcv(struct sk_buff *skb) skb->protocol = htons(ETH_P_IP); skb->pkt_type = PACKET_HOST; - __skb_tunnel_rx(skb, tunnel->dev); - - err = IP_ECN_decapsulate(iph, skb); - if (unlikely(err)) { - if (log_ecn_error) - net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", - &iph->saddr, iph->tos); - if (err > 1) { - ++tunnel->dev->stats.rx_frame_errors; - ++tunnel->dev->stats.rx_errors; - goto drop; - } - } - tstats = this_cpu_ptr(tunnel->dev->tstats); u64_stats_update_begin(&tstats->syncp); tstats->rx_packets++; tstats->rx_bytes += skb->len; u64_stats_update_end(&tstats->syncp); + __skb_tunnel_rx(skb, tunnel->dev); + + ipip_ecn_decapsulate(iph, skb); + netif_rx(skb); + + rcu_read_unlock(); return 0; } + rcu_read_unlock(); return -1; - -drop: - kfree_skb(skb); - return 0; } /* diff --git a/trunk/net/ipv4/netfilter/Kconfig b/trunk/net/ipv4/netfilter/Kconfig index d8d6f2a5bf12..131e53702e77 100644 --- a/trunk/net/ipv4/netfilter/Kconfig +++ b/trunk/net/ipv4/netfilter/Kconfig @@ -172,20 +172,23 @@ config IP_NF_TARGET_MASQUERADE config IP_NF_TARGET_NETMAP tristate "NETMAP target support" depends on NETFILTER_ADVANCED - select NETFILTER_XT_TARGET_NETMAP - ---help--- - This is a backwards-compat option for the user's convenience - (e.g. when running oldconfig). It selects - CONFIG_NETFILTER_XT_TARGET_NETMAP. + help + NETMAP is an implementation of static 1:1 NAT mapping of network + addresses. It maps the network address part, while keeping the host + address part intact. + + To compile it as a module, choose M here. If unsure, say N. config IP_NF_TARGET_REDIRECT tristate "REDIRECT target support" depends on NETFILTER_ADVANCED - select NETFILTER_XT_TARGET_REDIRECT - ---help--- - This is a backwards-compat option for the user's convenience - (e.g. when running oldconfig). It selects - CONFIG_NETFILTER_XT_TARGET_REDIRECT. + help + REDIRECT is a special case of NAT: all incoming connections are + mapped onto the incoming interface's address, causing the packets to + come to the local machine instead of passing through. This is + useful for transparent proxies. + + To compile it as a module, choose M here. If unsure, say N. endif diff --git a/trunk/net/ipv4/netfilter/Makefile b/trunk/net/ipv4/netfilter/Makefile index 007b128eecc9..b7dd18987237 100644 --- a/trunk/net/ipv4/netfilter/Makefile +++ b/trunk/net/ipv4/netfilter/Makefile @@ -45,6 +45,8 @@ obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o +obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o +obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o diff --git a/trunk/net/ipv4/netfilter/ipt_NETMAP.c b/trunk/net/ipv4/netfilter/ipt_NETMAP.c new file mode 100644 index 000000000000..85028dc0425d --- /dev/null +++ b/trunk/net/ipv4/netfilter/ipt_NETMAP.c @@ -0,0 +1,101 @@ +/* NETMAP - static NAT mapping of IP network addresses (1:1). + * The mapping can be applied to source (POSTROUTING), + * destination (PREROUTING), or both (with separate rules). + */ + +/* (C) 2000-2001 Svenning Soerensen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Svenning Soerensen "); +MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets"); + +static int netmap_tg_check(const struct xt_tgchk_param *par) +{ + const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; + + if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) { + pr_debug("bad MAP_IPS.\n"); + return -EINVAL; + } + if (mr->rangesize != 1) { + pr_debug("bad rangesize %u.\n", mr->rangesize); + return -EINVAL; + } + return 0; +} + +static unsigned int +netmap_tg(struct sk_buff *skb, const struct xt_action_param *par) +{ + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + __be32 new_ip, netmask; + const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; + struct nf_nat_range newrange; + + NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || + par->hooknum == NF_INET_POST_ROUTING || + par->hooknum == NF_INET_LOCAL_OUT || + par->hooknum == NF_INET_LOCAL_IN); + ct = nf_ct_get(skb, &ctinfo); + + netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); + + if (par->hooknum == NF_INET_PRE_ROUTING || + par->hooknum == NF_INET_LOCAL_OUT) + new_ip = ip_hdr(skb)->daddr & ~netmask; + else + new_ip = ip_hdr(skb)->saddr & ~netmask; + new_ip |= mr->range[0].min_ip & netmask; + + memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); + memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); + newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; + newrange.min_addr.ip = new_ip; + newrange.max_addr.ip = new_ip; + newrange.min_proto = mr->range[0].min; + newrange.max_proto = mr->range[0].max; + + /* Hand modified range to generic setup. */ + return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); +} + +static struct xt_target netmap_tg_reg __read_mostly = { + .name = "NETMAP", + .family = NFPROTO_IPV4, + .target = netmap_tg, + .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), + .table = "nat", + .hooks = (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_POST_ROUTING) | + (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_LOCAL_IN), + .checkentry = netmap_tg_check, + .me = THIS_MODULE +}; + +static int __init netmap_tg_init(void) +{ + return xt_register_target(&netmap_tg_reg); +} + +static void __exit netmap_tg_exit(void) +{ + xt_unregister_target(&netmap_tg_reg); +} + +module_init(netmap_tg_init); +module_exit(netmap_tg_exit); diff --git a/trunk/net/ipv4/netfilter/ipt_REDIRECT.c b/trunk/net/ipv4/netfilter/ipt_REDIRECT.c new file mode 100644 index 000000000000..11407d7d2472 --- /dev/null +++ b/trunk/net/ipv4/netfilter/ipt_REDIRECT.c @@ -0,0 +1,113 @@ +/* Redirect. Simple mapping which alters dst to a local IP address. */ +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2006 Netfilter Core Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Netfilter Core Team "); +MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); + +/* FIXME: Take multiple ranges --RR */ +static int redirect_tg_check(const struct xt_tgchk_param *par) +{ + const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; + + if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) { + pr_debug("bad MAP_IPS.\n"); + return -EINVAL; + } + if (mr->rangesize != 1) { + pr_debug("bad rangesize %u.\n", mr->rangesize); + return -EINVAL; + } + return 0; +} + +static unsigned int +redirect_tg(struct sk_buff *skb, const struct xt_action_param *par) +{ + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + __be32 newdst; + const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; + struct nf_nat_range newrange; + + NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || + par->hooknum == NF_INET_LOCAL_OUT); + + ct = nf_ct_get(skb, &ctinfo); + NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); + + /* Local packets: make them go to loopback */ + if (par->hooknum == NF_INET_LOCAL_OUT) + newdst = htonl(0x7F000001); + else { + struct in_device *indev; + struct in_ifaddr *ifa; + + newdst = 0; + + rcu_read_lock(); + indev = __in_dev_get_rcu(skb->dev); + if (indev && (ifa = indev->ifa_list)) + newdst = ifa->ifa_local; + rcu_read_unlock(); + + if (!newdst) + return NF_DROP; + } + + /* Transfer from original range. */ + memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); + memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); + newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; + newrange.min_addr.ip = newdst; + newrange.max_addr.ip = newdst; + newrange.min_proto = mr->range[0].min; + newrange.max_proto = mr->range[0].max; + + /* Hand modified range to generic setup. */ + return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); +} + +static struct xt_target redirect_tg_reg __read_mostly = { + .name = "REDIRECT", + .family = NFPROTO_IPV4, + .target = redirect_tg, + .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), + .table = "nat", + .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), + .checkentry = redirect_tg_check, + .me = THIS_MODULE, +}; + +static int __init redirect_tg_init(void) +{ + return xt_register_target(&redirect_tg_reg); +} + +static void __exit redirect_tg_exit(void) +{ + xt_unregister_target(&redirect_tg_reg); +} + +module_init(redirect_tg_init); +module_exit(redirect_tg_exit); diff --git a/trunk/net/ipv4/raw.c b/trunk/net/ipv4/raw.c index 73d1e4df4bf6..f2425785d40a 100644 --- a/trunk/net/ipv4/raw.c +++ b/trunk/net/ipv4/raw.c @@ -131,20 +131,18 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, * 0 - deliver * 1 - block */ -static int icmp_filter(const struct sock *sk, const struct sk_buff *skb) +static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb) { - struct icmphdr _hdr; - const struct icmphdr *hdr; + int type; - hdr = skb_header_pointer(skb, skb_transport_offset(skb), - sizeof(_hdr), &_hdr); - if (!hdr) + if (!pskb_may_pull(skb, sizeof(struct icmphdr))) return 1; - if (hdr->type < 32) { + type = icmp_hdr(skb)->type; + if (type < 32) { __u32 data = raw_sk(sk)->filter.data; - return ((1U << hdr->type) & data) != 0; + return ((1 << type) & data) != 0; } /* Do not block unknown ICMP types */ diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index ff622069fcef..940f4f4cb201 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -202,6 +202,11 @@ EXPORT_SYMBOL(ip_tos2prio); static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); #define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field) +static inline int rt_genid(struct net *net) +{ + return atomic_read(&net->ipv4.rt_genid); +} + #ifdef CONFIG_PROC_FS static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos) { @@ -444,7 +449,7 @@ static inline bool rt_is_expired(const struct rtable *rth) void rt_cache_flush(struct net *net) { - rt_genid_bump(net); + atomic_inc(&net->ipv4.rt_genid); } static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, @@ -2501,7 +2506,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = { static __net_init int rt_genid_init(struct net *net) { - atomic_set(&net->rt_genid, 0); + atomic_set(&net->ipv4.rt_genid, 0); get_random_bytes(&net->ipv4.dev_addr_genid, sizeof(net->ipv4.dev_addr_genid)); return 0; diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index f32c02e2a543..7b1e940393cf 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -1150,43 +1150,78 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (err) goto do_fault; } else { - bool merge = true; + bool merge = false; int i = skb_shinfo(skb)->nr_frags; - struct page_frag *pfrag = sk_page_frag(sk); - - if (!sk_page_frag_refill(sk, pfrag)) - goto wait_for_memory; - - if (!skb_can_coalesce(skb, i, pfrag->page, - pfrag->offset)) { - if (i == MAX_SKB_FRAGS || !sg) { - tcp_mark_push(tp, skb); - goto new_segment; + struct page *page = sk->sk_sndmsg_page; + int off; + + if (page && page_count(page) == 1) + sk->sk_sndmsg_off = 0; + + off = sk->sk_sndmsg_off; + + if (skb_can_coalesce(skb, i, page, off) && + off != PAGE_SIZE) { + /* We can extend the last page + * fragment. */ + merge = true; + } else if (i == MAX_SKB_FRAGS || !sg) { + /* Need to add new fragment and cannot + * do this because interface is non-SG, + * or because all the page slots are + * busy. */ + tcp_mark_push(tp, skb); + goto new_segment; + } else if (page) { + if (off == PAGE_SIZE) { + put_page(page); + sk->sk_sndmsg_page = page = NULL; + off = 0; } - merge = false; - } + } else + off = 0; - copy = min_t(int, copy, pfrag->size - pfrag->offset); + if (copy > PAGE_SIZE - off) + copy = PAGE_SIZE - off; if (!sk_wmem_schedule(sk, copy)) goto wait_for_memory; + if (!page) { + /* Allocate new cache page. */ + if (!(page = sk_stream_alloc_page(sk))) + goto wait_for_memory; + } + + /* Time to copy data. We are close to + * the end! */ err = skb_copy_to_page_nocache(sk, from, skb, - pfrag->page, - pfrag->offset, - copy); - if (err) + page, off, copy); + if (err) { + /* If this page was new, give it to the + * socket so it does not get leaked. + */ + if (!sk->sk_sndmsg_page) { + sk->sk_sndmsg_page = page; + sk->sk_sndmsg_off = 0; + } goto do_error; + } /* Update the skb. */ if (merge) { skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); } else { - skb_fill_page_desc(skb, i, pfrag->page, - pfrag->offset, copy); - get_page(pfrag->page); + skb_fill_page_desc(skb, i, page, off, copy); + if (sk->sk_sndmsg_page) { + get_page(page); + } else if (off + copy < PAGE_SIZE) { + get_page(page); + sk->sk_sndmsg_page = page; + } } - pfrag->offset += copy; + + sk->sk_sndmsg_off = off + copy; } if (!copied) @@ -1738,14 +1773,8 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } #ifdef CONFIG_NET_DMA - if (tp->ucopy.dma_chan) { - if (tp->rcv_wnd == 0 && - !skb_queue_empty(&sk->sk_async_wait_queue)) { - tcp_service_net_dma(sk, true); - tcp_cleanup_rbuf(sk, copied); - } else - dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); - } + if (tp->ucopy.dma_chan) + dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); #endif if (copied >= target) { /* Do not sleep, just process backlog. */ @@ -2326,17 +2355,10 @@ static int tcp_repair_options_est(struct tcp_sock *tp, tp->rx_opt.mss_clamp = opt.opt_val; break; case TCPOPT_WINDOW: - { - u16 snd_wscale = opt.opt_val & 0xFFFF; - u16 rcv_wscale = opt.opt_val >> 16; + if (opt.opt_val > 14) + return -EFBIG; - if (snd_wscale > 14 || rcv_wscale > 14) - return -EFBIG; - - tp->rx_opt.snd_wscale = snd_wscale; - tp->rx_opt.rcv_wscale = rcv_wscale; - tp->rx_opt.wscale_ok = 1; - } + tp->rx_opt.snd_wscale = opt.opt_val; break; case TCPOPT_SACK_PERM: if (opt.opt_val != 0) diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index 432c36649db3..e2bec815ff23 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -4634,7 +4634,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) if (eaten > 0) kfree_skb_partial(skb, fragstolen); - if (!sock_flag(sk, SOCK_DEAD)) + else if (!sock_flag(sk, SOCK_DEAD)) sk->sk_data_ready(sk, 0); return; } @@ -5529,7 +5529,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, #endif if (eaten) kfree_skb_partial(skb, fragstolen); - sk->sk_data_ready(sk, 0); + else + sk->sk_data_ready(sk, 0); return 0; } } @@ -5968,8 +5969,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (tcp_check_req(sk, skb, req, NULL, true) == NULL) goto discard; - } - if (!tcp_validate_incoming(sk, skb, th, 0)) + } else if (!tcp_validate_incoming(sk, skb, th, 0)) return 0; /* step 5: check the ACK field */ @@ -5983,9 +5983,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, * need req so release it. */ if (req) { - tcp_synack_rtt_meas(sk, req); - tp->total_retrans = req->retrans; - reqsk_fastopen_remove(sk, req, false); } else { /* Make sure socket is routed, for diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index 75735c9a6a9d..e64abed249cc 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -868,8 +868,6 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, ireq->rmt_addr, ireq->opt); err = net_xmit_eval(err); - if (!tcp_rsk(req)->snt_synack && !err) - tcp_rsk(req)->snt_synack = tcp_time_stamp; } return err; @@ -925,7 +923,8 @@ EXPORT_SYMBOL(tcp_syn_flood_action); /* * Save and compile IPv4 options into the request_sock if needed. */ -static struct ip_options_rcu *tcp_v4_save_options(struct sk_buff *skb) +static struct ip_options_rcu *tcp_v4_save_options(struct sock *sk, + struct sk_buff *skb) { const struct ip_options *opt = &(IPCB(skb)->opt); struct ip_options_rcu *dopt = NULL; @@ -1383,7 +1382,6 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; const struct inet_request_sock *ireq = inet_rsk(req); struct sock *child; - int err; req->retrans = 0; req->sk = NULL; @@ -1395,11 +1393,8 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, kfree_skb(skb_synack); return -1; } - err = ip_build_and_send_pkt(skb_synack, sk, ireq->loc_addr, - ireq->rmt_addr, ireq->opt); - err = net_xmit_eval(err); - if (!err) - tcp_rsk(req)->snt_synack = tcp_time_stamp; + ip_build_and_send_pkt(skb_synack, sk, ireq->loc_addr, + ireq->rmt_addr, ireq->opt); /* XXX (TFO) - is it ok to ignore error and continue? */ spin_lock(&queue->fastopenq->lock); @@ -1567,7 +1562,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ireq->loc_addr = daddr; ireq->rmt_addr = saddr; ireq->no_srccheck = inet_sk(sk)->transparent; - ireq->opt = tcp_v4_save_options(skb); + ireq->opt = tcp_v4_save_options(sk, skb); if (security_inet_conn_request(sk, skb, req)) goto drop_and_free; @@ -1617,6 +1612,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) isn = tcp_v4_init_sequence(skb); } tcp_rsk(req)->snt_isn = isn; + tcp_rsk(req)->snt_synack = tcp_time_stamp; if (dst == NULL) { dst = inet_csk_route_req(sk, &fl4, req); @@ -1654,7 +1650,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (err || want_cookie) goto drop_and_free; - tcp_rsk(req)->snt_synack = tcp_time_stamp; tcp_rsk(req)->listener = NULL; /* Add the request_sock to the SYN table */ inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); @@ -1738,7 +1733,9 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newtp->advmss = tcp_sk(sk)->rx_opt.user_mss; tcp_initialize_rcv_mss(newsk); - tcp_synack_rtt_meas(newsk, req); + if (tcp_rsk(req)->snt_synack) + tcp_valid_rtt_meas(newsk, + tcp_time_stamp - tcp_rsk(req)->snt_synack); newtp->total_retrans = req->retrans; #ifdef CONFIG_TCP_MD5SIG @@ -2199,6 +2196,14 @@ void tcp_v4_destroy_sock(struct sock *sk) if (inet_csk(sk)->icsk_bind_hash) inet_put_port(sk); + /* + * If sendmsg cached page exists, toss it. + */ + if (sk->sk_sndmsg_page) { + __free_page(sk->sk_sndmsg_page); + sk->sk_sndmsg_page = NULL; + } + /* TCP Cookie Transactions */ if (tp->cookie_values != NULL) { kref_put(&tp->cookie_values->kref, @@ -2803,8 +2808,6 @@ void tcp4_proc_exit(void) struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) { const struct iphdr *iph = skb_gro_network_header(skb); - __wsum wsum; - __sum16 sum; switch (skb->ip_summed) { case CHECKSUM_COMPLETE: @@ -2813,22 +2816,11 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) skb->ip_summed = CHECKSUM_UNNECESSARY; break; } -flush: - NAPI_GRO_CB(skb)->flush = 1; - return NULL; + /* fall through */ case CHECKSUM_NONE: - wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr, - skb_gro_len(skb), IPPROTO_TCP, 0); - sum = csum_fold(skb_checksum(skb, - skb_gro_offset(skb), - skb_gro_len(skb), - wsum)); - if (sum) - goto flush; - - skb->ip_summed = CHECKSUM_UNNECESSARY; - break; + NAPI_GRO_CB(skb)->flush = 1; + return NULL; } return tcp_gro_receive(head, skb); diff --git a/trunk/net/ipv4/tcp_minisocks.c b/trunk/net/ipv4/tcp_minisocks.c index 27536ba16c9d..5792577b5bc5 100644 --- a/trunk/net/ipv4/tcp_minisocks.c +++ b/trunk/net/ipv4/tcp_minisocks.c @@ -692,12 +692,6 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, if (!(flg & TCP_FLAG_ACK)) return NULL; - /* Got ACK for our SYNACK, so update baseline for SYNACK RTT sample. */ - if (tmp_opt.saw_tstamp && tmp_opt.rcv_tsecr) - tcp_rsk(req)->snt_synack = tmp_opt.rcv_tsecr; - else if (req->retrans) /* don't take RTT sample if retrans && ~TS */ - tcp_rsk(req)->snt_synack = 0; - /* For Fast Open no more processing is needed (sk is the * child socket). */ @@ -711,6 +705,10 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP); return NULL; } + if (tmp_opt.saw_tstamp && tmp_opt.rcv_tsecr) + tcp_rsk(req)->snt_synack = tmp_opt.rcv_tsecr; + else if (req->retrans) /* don't take RTT sample if retrans && ~TS */ + tcp_rsk(req)->snt_synack = 0; /* OK, ACK is valid, create big socket and * feed this segment to it. It will repeat all diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 480e68422efb..719a828fb67f 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -788,16 +788,10 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) struct in6_addr prefix; struct rt6_info *rt; struct net *net = dev_net(ifp->idev->dev); - struct flowi6 fl6 = {}; - ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); - fl6.flowi6_oif = ifp->idev->dev->ifindex; - fl6.daddr = prefix; - rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, - RT6_LOOKUP_F_IFACE); + rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); - if (rt != net->ipv6.ip6_null_entry && - addrconf_is_prefix_route(rt)) { + if (rt && addrconf_is_prefix_route(rt)) { if (onlink == 0) { ip6_del_rt(rt); rt = NULL; diff --git a/trunk/net/ipv6/inet6_connection_sock.c b/trunk/net/ipv6/inet6_connection_sock.c index c4f934176cab..0251a6005be8 100644 --- a/trunk/net/ipv6/inet6_connection_sock.c +++ b/trunk/net/ipv6/inet6_connection_sock.c @@ -175,12 +175,33 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, const struct in6_addr *saddr) { __ip6_dst_store(sk, dst, daddr, saddr); + +#ifdef CONFIG_XFRM + { + struct rt6_info *rt = (struct rt6_info *)dst; + rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid); + } +#endif } static inline struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) { - return __sk_dst_check(sk, cookie); + struct dst_entry *dst; + + dst = __sk_dst_check(sk, cookie); + +#ifdef CONFIG_XFRM + if (dst) { + struct rt6_info *rt = (struct rt6_info *)dst; + if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) { + __sk_dst_reset(sk); + dst = NULL; + } + } +#endif + + return dst; } static struct dst_entry *inet6_csk_route_socket(struct sock *sk, diff --git a/trunk/net/ipv6/ip6_fib.c b/trunk/net/ipv6/ip6_fib.c index 24995a93ef8c..13690d650c3e 100644 --- a/trunk/net/ipv6/ip6_fib.c +++ b/trunk/net/ipv6/ip6_fib.c @@ -514,7 +514,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, ln = node_alloc(); if (!ln) - return ERR_PTR(-ENOMEM); + return NULL; ln->fn_bit = plen; ln->parent = pn; @@ -561,7 +561,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, node_free(in); if (ln) node_free(ln); - return ERR_PTR(-ENOMEM); + return NULL; } /* @@ -611,7 +611,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, ln = node_alloc(); if (!ln) - return ERR_PTR(-ENOMEM); + return NULL; ln->fn_bit = plen; @@ -777,9 +777,12 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) if (IS_ERR(fn)) { err = PTR_ERR(fn); - goto out; + fn = NULL; } + if (!fn) + goto out; + pn = fn; #ifdef CONFIG_IPV6_SUBTREES @@ -816,13 +819,12 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) offsetof(struct rt6_info, rt6i_src), allow_create, replace_required); - if (IS_ERR(sn)) { + if (!sn) { /* If it is failed, discard just allocated root, and then (in st_failure) stale node in main tree. */ node_free(sfn); - err = PTR_ERR(sn); goto st_failure; } @@ -837,8 +839,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) if (IS_ERR(sn)) { err = PTR_ERR(sn); - goto st_failure; + sn = NULL; } + if (!sn) + goto st_failure; } if (!fn->leaf) { diff --git a/trunk/net/ipv6/ip6_gre.c b/trunk/net/ipv6/ip6_gre.c index 0185679c5f53..424d11a4e7ff 100644 --- a/trunk/net/ipv6/ip6_gre.c +++ b/trunk/net/ipv6/ip6_gre.c @@ -56,10 +56,6 @@ #include -static bool log_ecn_error = true; -module_param(log_ecn_error, bool, 0644); -MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); - #define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK) #define IPV6_TCLASS_SHIFT 20 @@ -153,9 +149,7 @@ static struct rtnl_link_stats64 *ip6gre_get_stats64(struct net_device *dev, tot->rx_crc_errors = dev->stats.rx_crc_errors; tot->rx_fifo_errors = dev->stats.rx_fifo_errors; tot->rx_length_errors = dev->stats.rx_length_errors; - tot->rx_frame_errors = dev->stats.rx_frame_errors; tot->rx_errors = dev->stats.rx_errors; - tot->tx_fifo_errors = dev->stats.tx_fifo_errors; tot->tx_carrier_errors = dev->stats.tx_carrier_errors; tot->tx_dropped = dev->stats.tx_dropped; @@ -443,12 +437,14 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ipv6h = (const struct ipv6hdr *)skb->data; p = (__be16 *)(skb->data + offset); + rcu_read_lock(); + t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, flags & GRE_KEY ? *(((__be32 *)p) + (grehlen / 4) - 1) : 0, p[1]); if (t == NULL) - return; + goto out; switch (type) { __u32 teli; @@ -493,6 +489,30 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, else t->err_count = 1; t->err_time = jiffies; +out: + rcu_read_unlock(); +} + +static inline void ip6gre_ecn_decapsulate_ipv4(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, struct sk_buff *skb) +{ + __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; + + if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) + ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield); + + if (INET_ECN_is_ce(dsfield)) + IP_ECN_set_ce(ip_hdr(skb)); +} + +static inline void ip6gre_ecn_decapsulate_ipv6(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, struct sk_buff *skb) +{ + if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) + ipv6_copy_dscp(ipv6_get_dsfield(ipv6h), ipv6_hdr(skb)); + + if (INET_ECN_is_ce(ipv6_get_dsfield(ipv6h))) + IP6_ECN_set_ce(ipv6_hdr(skb)); } static int ip6gre_rcv(struct sk_buff *skb) @@ -506,10 +526,9 @@ static int ip6gre_rcv(struct sk_buff *skb) struct ip6_tnl *tunnel; int offset = 4; __be16 gre_proto; - int err; if (!pskb_may_pull(skb, sizeof(struct in6_addr))) - goto drop; + goto drop_nolock; ipv6h = ipv6_hdr(skb); h = skb->data; @@ -520,7 +539,7 @@ static int ip6gre_rcv(struct sk_buff *skb) - We do not support routing headers. */ if (flags&(GRE_VERSION|GRE_ROUTING)) - goto drop; + goto drop_nolock; if (flags&GRE_CSUM) { switch (skb->ip_summed) { @@ -548,6 +567,7 @@ static int ip6gre_rcv(struct sk_buff *skb) gre_proto = *(__be16 *)(h + 2); + rcu_read_lock(); tunnel = ip6gre_tunnel_lookup(skb->dev, &ipv6h->saddr, &ipv6h->daddr, key, gre_proto); @@ -610,36 +630,30 @@ static int ip6gre_rcv(struct sk_buff *skb) skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); } - __skb_tunnel_rx(skb, tunnel->dev); - - skb_reset_network_header(skb); - - err = IP6_ECN_decapsulate(ipv6h, skb); - if (unlikely(err)) { - if (log_ecn_error) - net_info_ratelimited("non-ECT from %pI6 with dsfield=%#x\n", - &ipv6h->saddr, - ipv6_get_dsfield(ipv6h)); - if (err > 1) { - ++tunnel->dev->stats.rx_frame_errors; - ++tunnel->dev->stats.rx_errors; - goto drop; - } - } - tstats = this_cpu_ptr(tunnel->dev->tstats); u64_stats_update_begin(&tstats->syncp); tstats->rx_packets++; tstats->rx_bytes += skb->len; u64_stats_update_end(&tstats->syncp); + __skb_tunnel_rx(skb, tunnel->dev); + + skb_reset_network_header(skb); + if (skb->protocol == htons(ETH_P_IP)) + ip6gre_ecn_decapsulate_ipv4(tunnel, ipv6h, skb); + else if (skb->protocol == htons(ETH_P_IPV6)) + ip6gre_ecn_decapsulate_ipv6(tunnel, ipv6h, skb); + netif_rx(skb); + rcu_read_unlock(); return 0; } icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); drop: + rcu_read_unlock(); +drop_nolock: kfree_skb(skb); return 0; } @@ -1279,8 +1293,16 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, return -t->hlen; } +static int ip6gre_header_parse(const struct sk_buff *skb, unsigned char *haddr) +{ + const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb_mac_header(skb); + memcpy(haddr, &ipv6h->saddr, sizeof(struct in6_addr)); + return sizeof(struct in6_addr); +} + static const struct header_ops ip6gre_header_ops = { .create = ip6gre_header, + .parse = ip6gre_header_parse, }; static const struct net_device_ops ip6gre_netdev_ops = { diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index aece3e792f84..3dd4a37488d5 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -1279,6 +1279,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, if (dst_allfrag(rt->dst.path)) cork->flags |= IPCORK_ALLFRAG; cork->length = 0; + sk->sk_sndmsg_page = NULL; + sk->sk_sndmsg_off = 0; exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; length += exthdrlen; transhdrlen += exthdrlen; @@ -1502,31 +1504,48 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, } } else { int i = skb_shinfo(skb)->nr_frags; - struct page_frag *pfrag = sk_page_frag(sk); - - err = -ENOMEM; - if (!sk_page_frag_refill(sk, pfrag)) - goto error; - - if (!skb_can_coalesce(skb, i, pfrag->page, - pfrag->offset)) { - err = -EMSGSIZE; - if (i == MAX_SKB_FRAGS) + skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1]; + struct page *page = sk->sk_sndmsg_page; + int off = sk->sk_sndmsg_off; + unsigned int left; + + if (page && (left = PAGE_SIZE - off) > 0) { + if (copy >= left) + copy = left; + if (page != skb_frag_page(frag)) { + if (i == MAX_SKB_FRAGS) { + err = -EMSGSIZE; + goto error; + } + skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0); + skb_frag_ref(skb, i); + frag = &skb_shinfo(skb)->frags[i]; + } + } else if(i < MAX_SKB_FRAGS) { + if (copy > PAGE_SIZE) + copy = PAGE_SIZE; + page = alloc_pages(sk->sk_allocation, 0); + if (page == NULL) { + err = -ENOMEM; goto error; + } + sk->sk_sndmsg_page = page; + sk->sk_sndmsg_off = 0; - __skb_fill_page_desc(skb, i, pfrag->page, - pfrag->offset, 0); - skb_shinfo(skb)->nr_frags = ++i; - get_page(pfrag->page); + skb_fill_page_desc(skb, i, page, 0, 0); + frag = &skb_shinfo(skb)->frags[i]; + } else { + err = -EMSGSIZE; + goto error; } - copy = min_t(int, copy, pfrag->size - pfrag->offset); if (getfrag(from, - page_address(pfrag->page) + pfrag->offset, - offset, copy, skb->len, skb) < 0) - goto error_efault; - - pfrag->offset += copy; - skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); + skb_frag_address(frag) + skb_frag_size(frag), + offset, copy, skb->len, skb) < 0) { + err = -EFAULT; + goto error; + } + sk->sk_sndmsg_off += copy; + skb_frag_size_add(frag, copy); skb->len += copy; skb->data_len += copy; skb->truesize += copy; @@ -1535,11 +1554,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, offset += copy; length -= copy; } - return 0; - -error_efault: - err = -EFAULT; error: cork->length -= length; IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); diff --git a/trunk/net/ipv6/mip6.c b/trunk/net/ipv6/mip6.c index 0f9bdc5ee9f3..5b087c31d87b 100644 --- a/trunk/net/ipv6/mip6.c +++ b/trunk/net/ipv6/mip6.c @@ -86,30 +86,28 @@ static int mip6_mh_len(int type) static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) { - struct ip6_mh _hdr; - const struct ip6_mh *mh; + struct ip6_mh *mh; - mh = skb_header_pointer(skb, skb_transport_offset(skb), - sizeof(_hdr), &_hdr); - if (!mh) + if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || + !pskb_may_pull(skb, (skb_transport_offset(skb) + + ((skb_transport_header(skb)[1] + 1) << 3)))) return -1; - if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len) - return -1; + mh = (struct ip6_mh *)skb_transport_header(skb); if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); - mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) + - skb_network_header_len(skb)); + mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - + skb_network_header(skb))); return -1; } if (mh->ip6mh_proto != IPPROTO_NONE) { LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", mh->ip6mh_proto); - mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) + - skb_network_header_len(skb)); + mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - + skb_network_header(skb))); return -1; } diff --git a/trunk/net/ipv6/netfilter/Kconfig b/trunk/net/ipv6/netfilter/Kconfig index c72532a60d88..3b73254d7bf1 100644 --- a/trunk/net/ipv6/netfilter/Kconfig +++ b/trunk/net/ipv6/netfilter/Kconfig @@ -25,6 +25,18 @@ config NF_CONNTRACK_IPV6 To compile it as a module, choose M here. If unsure, say N. +config NF_NAT_IPV6 + tristate "IPv6 NAT" + depends on NF_CONNTRACK_IPV6 + depends on NETFILTER_ADVANCED + select NF_NAT + help + The IPv6 NAT option allows masquerading, port forwarding and other + forms of full Network Address Port Translation. It is controlled by + the `nat' table in ip6tables, see the man page for ip6tables(8). + + To compile it as a module, choose M here. If unsure, say N. + config IP6_NF_IPTABLES tristate "IP6 tables support (required for filtering)" depends on INET && IPV6 @@ -132,6 +144,48 @@ config IP6_NF_TARGET_HL (e.g. when running oldconfig). It selects CONFIG_NETFILTER_XT_TARGET_HL. +config IP6_NF_TARGET_MASQUERADE + tristate "MASQUERADE target support" + depends on NF_NAT_IPV6 + help + Masquerading is a special case of NAT: all outgoing connections are + changed to seem to come from a particular interface's address, and + if the interface goes down, those connections are lost. This is + only useful for dialup accounts with dynamic IP address (ie. your IP + address will be different on next dialup). + + To compile it as a module, choose M here. If unsure, say N. + +config IP6_NF_TARGET_NETMAP + tristate "NETMAP target support" + depends on NF_NAT_IPV6 + help + NETMAP is an implementation of static 1:1 NAT mapping of network + addresses. It maps the network address part, while keeping the host + address part intact. + + To compile it as a module, choose M here. If unsure, say N. + +config IP6_NF_TARGET_REDIRECT + tristate "REDIRECT target support" + depends on NF_NAT_IPV6 + help + REDIRECT is a special case of NAT: all incoming connections are + mapped onto the incoming interface's address, causing the packets to + come to the local machine instead of passing through. This is + useful for transparent proxies. + + To compile it as a module, choose M here. If unsure, say N. + +config IP6_NF_TARGET_NPT + tristate "NPT (Network Prefix translation) target support" + depends on NETFILTER_ADVANCED + help + This option adds the `SNPT' and `DNPT' target, which perform + stateless IPv6-to-IPv6 Network Prefix Translation per RFC 6296. + + To compile it as a module, choose M here. If unsure, say N. + config IP6_NF_FILTER tristate "Packet filtering" default m if NETFILTER_ADVANCED=n @@ -181,44 +235,9 @@ config IP6_NF_SECURITY help This option adds a `security' table to iptables, for use with Mandatory Access Control (MAC) policy. - + If unsure, say N. -config NF_NAT_IPV6 - tristate "IPv6 NAT" - depends on NF_CONNTRACK_IPV6 - depends on NETFILTER_ADVANCED - select NF_NAT - help - The IPv6 NAT option allows masquerading, port forwarding and other - forms of full Network Address Port Translation. It is controlled by - the `nat' table in ip6tables, see the man page for ip6tables(8). - - To compile it as a module, choose M here. If unsure, say N. - -if NF_NAT_IPV6 - -config IP6_NF_TARGET_MASQUERADE - tristate "MASQUERADE target support" - help - Masquerading is a special case of NAT: all outgoing connections are - changed to seem to come from a particular interface's address, and - if the interface goes down, those connections are lost. This is - only useful for dialup accounts with dynamic IP address (ie. your IP - address will be different on next dialup). - - To compile it as a module, choose M here. If unsure, say N. - -config IP6_NF_TARGET_NPT - tristate "NPT (Network Prefix translation) target support" - help - This option adds the `SNPT' and `DNPT' target, which perform - stateless IPv6-to-IPv6 Network Prefix Translation per RFC 6296. - - To compile it as a module, choose M here. If unsure, say N. - -endif # NF_NAT_IPV6 - endif # IP6_NF_IPTABLES endmenu diff --git a/trunk/net/ipv6/netfilter/Makefile b/trunk/net/ipv6/netfilter/Makefile index 2d11fcc2cf3c..5752132ca159 100644 --- a/trunk/net/ipv6/netfilter/Makefile +++ b/trunk/net/ipv6/netfilter/Makefile @@ -35,5 +35,7 @@ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o # targets obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o +obj-$(CONFIG_IP6_NF_TARGET_NETMAP) += ip6t_NETMAP.o obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o +obj-$(CONFIG_IP6_NF_TARGET_REDIRECT) += ip6t_REDIRECT.o obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o diff --git a/trunk/net/ipv6/netfilter/ip6t_NETMAP.c b/trunk/net/ipv6/netfilter/ip6t_NETMAP.c new file mode 100644 index 000000000000..4f3bf360e50f --- /dev/null +++ b/trunk/net/ipv6/netfilter/ip6t_NETMAP.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 + * NAT funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include + +static unsigned int +netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par) +{ + const struct nf_nat_range *range = par->targinfo; + struct nf_nat_range newrange; + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + union nf_inet_addr new_addr, netmask; + unsigned int i; + + ct = nf_ct_get(skb, &ctinfo); + for (i = 0; i < ARRAY_SIZE(range->min_addr.ip6); i++) + netmask.ip6[i] = ~(range->min_addr.ip6[i] ^ + range->max_addr.ip6[i]); + + if (par->hooknum == NF_INET_PRE_ROUTING || + par->hooknum == NF_INET_LOCAL_OUT) + new_addr.in6 = ipv6_hdr(skb)->daddr; + else + new_addr.in6 = ipv6_hdr(skb)->saddr; + + for (i = 0; i < ARRAY_SIZE(new_addr.ip6); i++) { + new_addr.ip6[i] &= ~netmask.ip6[i]; + new_addr.ip6[i] |= range->min_addr.ip6[i] & + netmask.ip6[i]; + } + + newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; + newrange.min_addr = new_addr; + newrange.max_addr = new_addr; + newrange.min_proto = range->min_proto; + newrange.max_proto = range->max_proto; + + return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); +} + +static int netmap_tg6_checkentry(const struct xt_tgchk_param *par) +{ + const struct nf_nat_range *range = par->targinfo; + + if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) + return -EINVAL; + return 0; +} + +static struct xt_target netmap_tg6_reg __read_mostly = { + .name = "NETMAP", + .family = NFPROTO_IPV6, + .target = netmap_tg6, + .targetsize = sizeof(struct nf_nat_range), + .table = "nat", + .hooks = (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_POST_ROUTING) | + (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_LOCAL_IN), + .checkentry = netmap_tg6_checkentry, + .me = THIS_MODULE, +}; + +static int __init netmap_tg6_init(void) +{ + return xt_register_target(&netmap_tg6_reg); +} + +static void netmap_tg6_exit(void) +{ + xt_unregister_target(&netmap_tg6_reg); +} + +module_init(netmap_tg6_init); +module_exit(netmap_tg6_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv6 subnets"); +MODULE_AUTHOR("Patrick McHardy "); diff --git a/trunk/net/ipv6/netfilter/ip6t_REDIRECT.c b/trunk/net/ipv6/netfilter/ip6t_REDIRECT.c new file mode 100644 index 000000000000..60497a3c6004 --- /dev/null +++ b/trunk/net/ipv6/netfilter/ip6t_REDIRECT.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2011 Patrick McHardy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 + * NAT funded by Astaro. + */ + +#include +#include +#include +#include +#include +#include +#include + +static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; + +static unsigned int +redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) +{ + const struct nf_nat_range *range = par->targinfo; + struct nf_nat_range newrange; + struct in6_addr newdst; + enum ip_conntrack_info ctinfo; + struct nf_conn *ct; + + ct = nf_ct_get(skb, &ctinfo); + if (par->hooknum == NF_INET_LOCAL_OUT) + newdst = loopback_addr; + else { + struct inet6_dev *idev; + struct inet6_ifaddr *ifa; + bool addr = false; + + rcu_read_lock(); + idev = __in6_dev_get(skb->dev); + if (idev != NULL) { + list_for_each_entry(ifa, &idev->addr_list, if_list) { + newdst = ifa->addr; + addr = true; + break; + } + } + rcu_read_unlock(); + + if (!addr) + return NF_DROP; + } + + newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; + newrange.min_addr.in6 = newdst; + newrange.max_addr.in6 = newdst; + newrange.min_proto = range->min_proto; + newrange.max_proto = range->max_proto; + + return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); +} + +static int redirect_tg6_checkentry(const struct xt_tgchk_param *par) +{ + const struct nf_nat_range *range = par->targinfo; + + if (range->flags & NF_NAT_RANGE_MAP_IPS) + return -EINVAL; + return 0; +} + +static struct xt_target redirect_tg6_reg __read_mostly = { + .name = "REDIRECT", + .family = NFPROTO_IPV6, + .checkentry = redirect_tg6_checkentry, + .target = redirect_tg6, + .targetsize = sizeof(struct nf_nat_range), + .table = "nat", + .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), + .me = THIS_MODULE, +}; + +static int __init redirect_tg6_init(void) +{ + return xt_register_target(&redirect_tg6_reg); +} + +static void __exit redirect_tg6_exit(void) +{ + xt_unregister_target(&redirect_tg6_reg); +} + +module_init(redirect_tg6_init); +module_exit(redirect_tg6_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy "); +MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); diff --git a/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c b/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c index 18bd9bbbd1c6..1af12fde08df 100644 --- a/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -106,7 +106,7 @@ static int __net_init nf_ct_frag6_sysctl_register(struct net *net) if (hdr == NULL) goto err_reg; - net->nf_frag.sysctl.frags_hdr = hdr; + net->ipv6.sysctl.frags_hdr = hdr; return 0; err_reg: diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index d8e95c77db99..7af88ef01657 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -107,20 +107,21 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, * 0 - deliver * 1 - block */ -static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb) +static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) { - struct icmp6hdr *_hdr; - const struct icmp6hdr *hdr; + struct icmp6hdr *icmph; + struct raw6_sock *rp = raw6_sk(sk); + + if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) { + __u32 *data = &rp->filter.data[0]; + int bit_nr; - hdr = skb_header_pointer(skb, skb_transport_offset(skb), - sizeof(_hdr), &_hdr); - if (hdr) { - const __u32 *data = &raw6_sk(sk)->filter.data[0]; - unsigned int type = hdr->icmp6_type; + icmph = (struct icmp6hdr *) skb->data; + bit_nr = icmph->icmp6_type; - return (data[type >> 5] & (1U << (type & 31))) != 0; + return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0; } - return 1; + return 0; } #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index d1ddbc6ddac5..0607ee3a0eac 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -226,7 +226,7 @@ static const struct rt6_info ip6_null_entry_template = { .dst = { .__refcnt = ATOMIC_INIT(1), .__use = 1, - .obsolete = DST_OBSOLETE_FORCE_CHK, + .obsolete = -1, .error = -ENETUNREACH, .input = ip6_pkt_discard, .output = ip6_pkt_discard_out, @@ -246,7 +246,7 @@ static const struct rt6_info ip6_prohibit_entry_template = { .dst = { .__refcnt = ATOMIC_INIT(1), .__use = 1, - .obsolete = DST_OBSOLETE_FORCE_CHK, + .obsolete = -1, .error = -EACCES, .input = ip6_pkt_prohibit, .output = ip6_pkt_prohibit_out, @@ -261,7 +261,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = { .dst = { .__refcnt = ATOMIC_INIT(1), .__use = 1, - .obsolete = DST_OBSOLETE_FORCE_CHK, + .obsolete = -1, .error = -EINVAL, .input = dst_discard, .output = dst_discard, @@ -281,14 +281,13 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net, struct fib6_table *table) { struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, - 0, DST_OBSOLETE_FORCE_CHK, flags); + 0, DST_OBSOLETE_NONE, flags); if (rt) { struct dst_entry *dst = &rt->dst; memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); - rt->rt6i_genid = rt_genid(net); } return rt; } @@ -1023,13 +1022,6 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) rt = (struct rt6_info *) dst; - /* All IPV6 dsts are created with ->obsolete set to the value - * DST_OBSOLETE_FORCE_CHK which forces validation calls down - * into this function always. - */ - if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) - return NULL; - if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { if (rt->rt6i_peer_genid != rt6_peer_genid()) { if (!rt6_has_peer(rt)) @@ -1396,6 +1388,8 @@ int ip6_route_add(struct fib6_config *cfg) goto out; } + rt->dst.obsolete = -1; + if (cfg->fc_flags & RTF_EXPIRES) rt6_set_expires(rt, jiffies + clock_t_to_jiffies(cfg->fc_expires)); @@ -2090,6 +2084,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, rt->dst.input = ip6_input; rt->dst.output = ip6_output; rt->rt6i_idev = idev; + rt->dst.obsolete = -1; rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; if (anycast) diff --git a/trunk/net/ipv6/sit.c b/trunk/net/ipv6/sit.c index 3ed54ffd8d50..3bd1bfc01f85 100644 --- a/trunk/net/ipv6/sit.c +++ b/trunk/net/ipv6/sit.c @@ -545,6 +545,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) err = -ENOENT; + rcu_read_lock(); t = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, iph->daddr, @@ -578,6 +579,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) t->err_count = 1; t->err_time = jiffies; out: + rcu_read_unlock(); return err; } @@ -597,6 +599,7 @@ static int ipip6_rcv(struct sk_buff *skb) iph = ip_hdr(skb); + rcu_read_lock(); tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, iph->saddr, iph->daddr); if (tunnel != NULL) { @@ -612,6 +615,7 @@ static int ipip6_rcv(struct sk_buff *skb) if ((tunnel->dev->priv_flags & IFF_ISATAP) && !isatap_chksrc(skb, iph, tunnel)) { tunnel->dev->stats.rx_errors++; + rcu_read_unlock(); kfree_skb(skb); return 0; } @@ -626,10 +630,12 @@ static int ipip6_rcv(struct sk_buff *skb) netif_rx(skb); + rcu_read_unlock(); return 0; } /* no tunnel matched, let upstream know, ipsec may handle it */ + rcu_read_unlock(); return 1; out: kfree_skb(skb); diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index 49c890386ce9..f3bfb8bbfdec 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -763,8 +763,6 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) { const struct ipv6hdr *iph = skb_gro_network_header(skb); - __wsum wsum; - __sum16 sum; switch (skb->ip_summed) { case CHECKSUM_COMPLETE: @@ -773,23 +771,11 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, skb->ip_summed = CHECKSUM_UNNECESSARY; break; } -flush: - NAPI_GRO_CB(skb)->flush = 1; - return NULL; + /* fall through */ case CHECKSUM_NONE: - wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr, - skb_gro_len(skb), - IPPROTO_TCP, 0)); - sum = csum_fold(skb_checksum(skb, - skb_gro_offset(skb), - skb_gro_len(skb), - wsum)); - if (sum) - goto flush; - - skb->ip_summed = CHECKSUM_UNNECESSARY; - break; + NAPI_GRO_CB(skb)->flush = 1; + return NULL; } return tcp_gro_receive(head, skb); @@ -1183,6 +1169,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) } have_isn: tcp_rsk(req)->snt_isn = isn; + tcp_rsk(req)->snt_synack = tcp_time_stamp; if (security_inet_conn_request(sk, skb, req)) goto drop_and_release; @@ -1193,7 +1180,6 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) want_cookie) goto drop_and_free; - tcp_rsk(req)->snt_synack = tcp_time_stamp; tcp_rsk(req)->listener = NULL; inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); return 0; @@ -1362,7 +1348,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newtp->advmss = tcp_sk(sk)->rx_opt.user_mss; tcp_initialize_rcv_mss(newsk); - tcp_synack_rtt_meas(newsk, req); + if (tcp_rsk(req)->snt_synack) + tcp_valid_rtt_meas(newsk, + tcp_time_stamp - tcp_rsk(req)->snt_synack); newtp->total_retrans = req->retrans; newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; diff --git a/trunk/net/key/af_key.c b/trunk/net/key/af_key.c index 08897a3c7ec7..2ca7d7f6861c 100644 --- a/trunk/net/key/af_key.c +++ b/trunk/net/key/af_key.c @@ -1923,9 +1923,6 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol) int len = pol->sadb_x_policy_len*8 - sizeof(struct sadb_x_policy); struct sadb_x_ipsecrequest *rq = (void*)(pol+1); - if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy)) - return -EINVAL; - while (len >= sizeof(struct sadb_x_ipsecrequest)) { if ((err = parse_ipsecrequest(xp, rq)) < 0) return err; diff --git a/trunk/net/l2tp/l2tp_netlink.c b/trunk/net/l2tp/l2tp_netlink.c index 6c4cc12c7414..6ec3f67ad3f1 100644 --- a/trunk/net/l2tp/l2tp_netlink.c +++ b/trunk/net/l2tp/l2tp_netlink.c @@ -80,8 +80,8 @@ static int l2tp_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &l2tp_nl_family, 0, L2TP_CMD_NOOP); - if (!hdr) { - ret = -EMSGSIZE; + if (IS_ERR(hdr)) { + ret = PTR_ERR(hdr); goto err_out; } @@ -250,8 +250,8 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags, L2TP_CMD_TUNNEL_GET); - if (!hdr) - return -EMSGSIZE; + if (IS_ERR(hdr)) + return PTR_ERR(hdr); if (nla_put_u8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version) || nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) || @@ -617,8 +617,8 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl sk = tunnel->sock; hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags, L2TP_CMD_SESSION_GET); - if (!hdr) - return -EMSGSIZE; + if (IS_ERR(hdr)) + return PTR_ERR(hdr); if (nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) || nla_put_u32(skb, L2TP_ATTR_SESSION_ID, session->session_id) || diff --git a/trunk/net/mac80211/agg-tx.c b/trunk/net/mac80211/agg-tx.c index 3195a6307f50..d0deb3edae21 100644 --- a/trunk/net/mac80211/agg-tx.c +++ b/trunk/net/mac80211/agg-tx.c @@ -869,7 +869,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, } else { ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, - false); + true); } out: diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 05f3a313db88..03fe6d1cff42 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -20,8 +20,7 @@ #include "rate.h" #include "mesh.h" -static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, - const char *name, +static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params) @@ -171,38 +170,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, } } - switch (sdata->vif.type) { - case NL80211_IFTYPE_STATION: - if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) - key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; - break; - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_AP_VLAN: - /* Keys without a station are used for TX only */ - if (key->sta && test_sta_flag(key->sta, WLAN_STA_MFP)) - key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; - break; - case NL80211_IFTYPE_ADHOC: - /* no MFP (yet) */ - break; - case NL80211_IFTYPE_MESH_POINT: -#ifdef CONFIG_MAC80211_MESH - if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) - key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; - break; -#endif - case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_P2P_DEVICE: - case NL80211_IFTYPE_UNSPECIFIED: - case NUM_NL80211_IFTYPES: - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - /* shouldn't happen */ - WARN_ON_ONCE(1); - break; - } - err = ieee80211_key_link(key, sdata, sta); if (err) ieee80211_key_free(sdata->local, key); @@ -2071,7 +2038,9 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, */ if (!sdata->u.mgd.associated || sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { + mutex_lock(&sdata->local->iflist_mtx); ieee80211_recalc_smps(sdata->local); + mutex_unlock(&sdata->local->iflist_mtx); return 0; } diff --git a/trunk/net/mac80211/chan.c b/trunk/net/mac80211/chan.c index 0bfc914ddd15..f0f87e5a1d35 100644 --- a/trunk/net/mac80211/chan.c +++ b/trunk/net/mac80211/chan.c @@ -68,14 +68,16 @@ ieee80211_get_channel_mode(struct ieee80211_local *local, return mode; } -static enum nl80211_channel_type -ieee80211_get_superchan(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) +bool ieee80211_set_channel_type(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + enum nl80211_channel_type chantype) { - enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT; struct ieee80211_sub_if_data *tmp; + enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT; + bool result; mutex_lock(&local->iflist_mtx); + list_for_each_entry(tmp, &local->interfaces, list) { if (tmp == sdata) continue; @@ -101,70 +103,39 @@ ieee80211_get_superchan(struct ieee80211_local *local, break; } } - mutex_unlock(&local->iflist_mtx); - return superchan; -} - -static bool -ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, - enum nl80211_channel_type chantype2, - enum nl80211_channel_type *compat) -{ - /* - * start out with chantype1 being the result, - * overwriting later if needed - */ - if (compat) - *compat = chantype1; - - switch (chantype1) { + switch (superchan) { case NL80211_CHAN_NO_HT: - if (compat) - *compat = chantype2; - break; case NL80211_CHAN_HT20: /* * allow any change that doesn't go to no-HT * (if it already is no-HT no change is needed) */ - if (chantype2 == NL80211_CHAN_NO_HT) + if (chantype == NL80211_CHAN_NO_HT) break; - if (compat) - *compat = chantype2; + superchan = chantype; break; case NL80211_CHAN_HT40PLUS: case NL80211_CHAN_HT40MINUS: /* allow smaller bandwidth and same */ - if (chantype2 == NL80211_CHAN_NO_HT) + if (chantype == NL80211_CHAN_NO_HT) break; - if (chantype2 == NL80211_CHAN_HT20) + if (chantype == NL80211_CHAN_HT20) break; - if (chantype2 == chantype1) + if (superchan == chantype) break; - return false; + result = false; + goto out; } - return true; -} - -bool ieee80211_set_channel_type(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - enum nl80211_channel_type chantype) -{ - enum nl80211_channel_type superchan; - enum nl80211_channel_type compatchan; - - superchan = ieee80211_get_superchan(local, sdata); - if (!ieee80211_channel_types_are_compatible(superchan, chantype, - &compatchan)) - return false; - - local->_oper_channel_type = compatchan; + local->_oper_channel_type = superchan; if (sdata) sdata->vif.bss_conf.channel_type = chantype; - return true; + result = true; + out: + mutex_unlock(&local->iflist_mtx); + return result; } diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c index 466f4b45dd94..97173f8144d4 100644 --- a/trunk/net/mac80211/debugfs.c +++ b/trunk/net/mac80211/debugfs.c @@ -70,7 +70,6 @@ DEBUGFS_READONLY_FILE(wep_iv, "%#08x", DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); -#ifdef CONFIG_PM static ssize_t reset_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { @@ -89,7 +88,6 @@ static const struct file_operations reset_ops = { .open = simple_open, .llseek = noop_llseek, }; -#endif static ssize_t hwflags_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -247,9 +245,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(total_ps_buffered); DEBUGFS_ADD(wep_iv); DEBUGFS_ADD(queues); -#ifdef CONFIG_PM DEBUGFS_ADD_MODE(reset, 0200); -#endif DEBUGFS_ADD(hwflags); DEBUGFS_ADD(user_power); DEBUGFS_ADD(power); diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index 5f3620f0bc0a..a9d93285dba7 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -278,7 +278,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, if (auth && !sdata->u.ibss.auth_frame_registrations) { ibss_dbg(sdata, "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", - sdata->vif.addr, addr, sdata->u.ibss.bssid); + sdata->vif.addr, sdata->u.ibss.bssid, addr); ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0, addr, sdata->u.ibss.bssid, NULL, 0, 0); } @@ -332,27 +332,11 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, return ieee80211_ibss_finish_sta(sta, auth); } -static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, - size_t len) -{ - u16 reason = le16_to_cpu(mgmt->u.deauth.reason_code); - - if (len < IEEE80211_DEAUTH_FRAME_LEN) - return; - - ibss_dbg(sdata, "RX DeAuth SA=%pM DA=%pM BSSID=%pM (reason: %d)\n", - mgmt->sa, mgmt->da, mgmt->bssid, reason); - sta_info_destroy_addr(sdata, mgmt->sa); -} - static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { u16 auth_alg, auth_transaction; - struct sta_info *sta; - u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; lockdep_assert_held(&sdata->u.ibss.mtx); @@ -368,21 +352,9 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); sta_info_destroy_addr(sdata, mgmt->sa); - sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); + ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); rcu_read_unlock(); - /* - * if we have any problem in allocating the new station, we reply with a - * DEAUTH frame to tell the other end that we had a problem - */ - if (!sta) { - ieee80211_send_deauth_disassoc(sdata, sdata->u.ibss.bssid, - IEEE80211_STYPE_DEAUTH, - WLAN_REASON_UNSPECIFIED, true, - deauth_frame_buf); - return; - } - /* * IEEE 802.11 standard does not require authentication in IBSS * networks and most implementations do not seem to use it. @@ -930,9 +902,6 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, case IEEE80211_STYPE_AUTH: ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len); break; - case IEEE80211_STYPE_DEAUTH: - ieee80211_rx_mgmt_deauth_ibss(sdata, mgmt, skb->len); - break; } mgmt_out: diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 8c804550465b..204bfedba306 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -68,8 +68,6 @@ struct ieee80211_local; #define IEEE80211_DEFAULT_MAX_SP_LEN \ IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL -#define IEEE80211_DEAUTH_FRAME_LEN (24 /* hdr */ + 2 /* reason */) - struct ieee80211_fragment_entry { unsigned long first_frag_time; unsigned int seq; @@ -413,7 +411,6 @@ struct ieee80211_if_managed { struct work_struct monitor_work; struct work_struct chswitch_work; struct work_struct beacon_connection_loss_work; - struct work_struct csa_connection_drop_work; unsigned long beacon_timeout; unsigned long probe_timeout; @@ -973,6 +970,7 @@ struct ieee80211_local { int scan_channel_idx; int scan_ies_len; + struct ieee80211_sched_scan_ies sched_scan_ies; struct work_struct sched_scan_stopped_work; struct ieee80211_sub_if_data __rcu *sched_scan_sdata; @@ -1059,7 +1057,7 @@ struct ieee80211_local { bool disable_dynamic_ps; int user_power_level; /* in dBm */ - int ap_power_level; /* in dBm */ + int power_constr_level; /* in dBm */ enum ieee80211_smps_mode smps_mode; @@ -1167,6 +1165,7 @@ struct ieee802_11_elems { u8 prep_len; u8 perr_len; u8 country_elem_len; + u8 pwr_constr_elem_len; u8 quiet_elem_len; u8 num_of_quiet_elem; /* can be more the one */ u8 timeout_int_len; @@ -1368,6 +1367,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, int ieee80211_reconfig(struct ieee80211_local *local); void ieee80211_stop_device(struct ieee80211_local *local); +#ifdef CONFIG_PM int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); @@ -1381,6 +1381,18 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) return ieee80211_reconfig(hw_to_local(hw)); } +#else +static inline int __ieee80211_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + return 0; +} + +static inline int __ieee80211_resume(struct ieee80211_hw *hw) +{ + return 0; +} +#endif /* utility functions/constants */ extern void *mac80211_wiphy_privid; /* for wiphy privid */ @@ -1447,9 +1459,6 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, u8 *extra, size_t extra_len, const u8 *bssid, const u8 *da, const u8 *key, u8 key_len, u8 key_idx); -void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, - const u8 *bssid, u16 stype, u16 reason, - bool send_frame, u8 *frame_buf); int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, const u8 *ie, size_t ie_len, enum ieee80211_band band, u32 rate_mask, diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index 6f8a73c64fb3..d747da541747 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -793,20 +793,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, flush_work(&sdata->work); /* * When we get here, the interface is marked down. - * Call rcu_barrier() to wait both for the RX path + * Call synchronize_rcu() to wait for the RX path * should it be using the interface and enqueuing - * frames at this very time on another CPU, and - * for the sta free call_rcu callbacks. + * frames at this very time on another CPU. */ - rcu_barrier(); - - /* - * free_sta_rcu() enqueues a work for the actual - * sta cleanup, so we need to flush it while - * sdata is still valid. - */ - flush_workqueue(local->workqueue); - + synchronize_rcu(); skb_queue_purge(&sdata->skb_queue); /* diff --git a/trunk/net/mac80211/key.c b/trunk/net/mac80211/key.c index d27e61aaa71b..7ae678ba5d67 100644 --- a/trunk/net/mac80211/key.c +++ b/trunk/net/mac80211/key.c @@ -402,7 +402,7 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) * Synchronize so the TX path can no longer be using * this key before we free/remove it. */ - synchronize_net(); + synchronize_rcu(); if (key->local) ieee80211_key_disable_hw_accel(key); diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index c80c4490351c..bd7529363193 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -150,11 +150,13 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) if (test_bit(SCAN_SW_SCANNING, &local->scanning) || test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || - test_bit(SCAN_HW_SCANNING, &local->scanning) || - !local->ap_power_level) + test_bit(SCAN_HW_SCANNING, &local->scanning)) power = chan->max_power; else - power = min(chan->max_power, local->ap_power_level); + power = local->power_constr_level ? + min(chan->max_power, + (chan->max_reg_power - local->power_constr_level)) : + chan->max_power; if (local->user_power_level >= 0) power = min(power, local->user_power_level); @@ -364,7 +366,9 @@ static void ieee80211_recalc_smps_work(struct work_struct *work) struct ieee80211_local *local = container_of(work, struct ieee80211_local, recalc_smps); + mutex_lock(&local->iflist_mtx); ieee80211_recalc_smps(local); + mutex_unlock(&local->iflist_mtx); } #ifdef CONFIG_INET diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c index 3ab34d816897..9d7ad366ef09 100644 --- a/trunk/net/mac80211/mesh_plink.c +++ b/trunk/net/mac80211/mesh_plink.c @@ -537,8 +537,7 @@ int mesh_plink_open(struct sta_info *sta) spin_lock_bh(&sta->lock); get_random_bytes(&llid, 2); sta->llid = llid; - if (sta->plink_state != NL80211_PLINK_LISTEN && - sta->plink_state != NL80211_PLINK_BLOCKED) { + if (sta->plink_state != NL80211_PLINK_LISTEN) { spin_unlock_bh(&sta->lock); return -EBUSY; } diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index e714ed8bb198..5d77650d4363 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -88,6 +88,8 @@ MODULE_PARM_DESC(probe_wait_ms, #define TMR_RUNNING_TIMER 0 #define TMR_RUNNING_CHANSW 1 +#define DEAUTH_DISASSOC_LEN (24 /* hdr */ + 2 /* reason */) + /* * All cfg80211 functions have to be called outside a locked * section so that they can acquire a lock themselves... This @@ -572,6 +574,46 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ieee80211_tx_skb(sdata, skb); } +static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, + const u8 *bssid, u16 stype, + u16 reason, bool send_frame, + u8 *frame_buf) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt = (void *)frame_buf; + + /* build frame */ + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); + mgmt->duration = 0; /* initialize only */ + mgmt->seq_ctrl = 0; /* initialize only */ + memcpy(mgmt->da, bssid, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); + memcpy(mgmt->bssid, bssid, ETH_ALEN); + /* u.deauth.reason_code == u.disassoc.reason_code */ + mgmt->u.deauth.reason_code = cpu_to_le16(reason); + + if (send_frame) { + skb = dev_alloc_skb(local->hw.extra_tx_headroom + + DEAUTH_DISASSOC_LEN); + if (!skb) + return; + + skb_reserve(skb, local->hw.extra_tx_headroom); + + /* copy in frame */ + memcpy(skb_put(skb, DEAUTH_DISASSOC_LEN), + mgmt, DEAUTH_DISASSOC_LEN); + + if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) + IEEE80211_SKB_CB(skb)->flags |= + IEEE80211_TX_INTFL_DONT_ENCRYPT; + + ieee80211_tx_skb(sdata, skb); + } +} + void ieee80211_send_pspoll(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata) { @@ -688,13 +730,16 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) trace_api_chswitch_done(sdata, success); if (!success) { - sdata_info(sdata, - "driver channel switch failed, disconnecting\n"); - ieee80211_queue_work(&sdata->local->hw, - &ifmgd->csa_connection_drop_work); - } else { - ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); + /* + * If the channel switch was not successful, stay + * around on the old channel. We currently lack + * good handling of this situation, possibly we + * should just drop the association. + */ + sdata->local->csa_channel = sdata->local->oper_channel; } + + ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); } EXPORT_SYMBOL(ieee80211_chswitch_done); @@ -739,14 +784,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, return; new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); - if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) { - sdata_info(sdata, - "AP %pM switches to unsupported channel (%d MHz), disconnecting\n", - ifmgd->associated->bssid, new_freq); - ieee80211_queue_work(&sdata->local->hw, - &ifmgd->csa_connection_drop_work); + if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) return; - } sdata->local->csa_channel = new_ch; @@ -779,71 +818,23 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, } static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, - struct ieee80211_channel *channel, - const u8 *country_ie, u8 country_ie_len, - const u8 *pwr_constr_elem) + u16 capab_info, u8 *pwr_constr_elem, + u8 pwr_constr_elem_len) { - struct ieee80211_country_ie_triplet *triplet; - int chan = ieee80211_frequency_to_channel(channel->center_freq); - int i, chan_pwr, chan_increment, new_ap_level; - bool have_chan_pwr = false; + struct ieee80211_conf *conf = &sdata->local->hw.conf; - /* Invalid IE */ - if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) + if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT)) return; - triplet = (void *)(country_ie + 3); - country_ie_len -= 3; - - switch (channel->band) { - default: - WARN_ON_ONCE(1); - /* fall through */ - case IEEE80211_BAND_2GHZ: - case IEEE80211_BAND_60GHZ: - chan_increment = 1; - break; - case IEEE80211_BAND_5GHZ: - chan_increment = 4; - break; - } - - /* find channel */ - while (country_ie_len >= 3) { - u8 first_channel = triplet->chans.first_channel; - - if (first_channel >= IEEE80211_COUNTRY_EXTENSION_ID) - goto next; - - for (i = 0; i < triplet->chans.num_channels; i++) { - if (first_channel + i * chan_increment == chan) { - have_chan_pwr = true; - chan_pwr = triplet->chans.max_power; - break; - } - } - if (have_chan_pwr) - break; - - next: - triplet++; - country_ie_len -= 3; - } - - if (!have_chan_pwr) - return; - - new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); - - if (sdata->local->ap_power_level == new_ap_level) + /* Power constraint IE length should be 1 octet */ + if (pwr_constr_elem_len != 1) return; - sdata_info(sdata, - "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", - new_ap_level, chan_pwr, *pwr_constr_elem, - sdata->u.mgd.bssid); - sdata->local->ap_power_level = new_ap_level; - ieee80211_hw_config(sdata->local, 0); + if ((*pwr_constr_elem <= conf->channel->max_reg_power) && + (*pwr_constr_elem != sdata->local->power_constr_level)) { + sdata->local->power_constr_level = *pwr_constr_elem; + ieee80211_hw_config(sdata->local, 0); + } } void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) @@ -1348,9 +1339,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->iflist_mtx); ieee80211_recalc_ps(local, -1); + ieee80211_recalc_smps(local); mutex_unlock(&local->iflist_mtx); - ieee80211_recalc_smps(local); ieee80211_recalc_ps_vif(sdata); netif_tx_start_all_queues(sdata->dev); @@ -1399,7 +1390,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, sta = sta_info_get(sdata, ifmgd->bssid); if (sta) { set_sta_flag(sta, WLAN_STA_BLOCK_BA); - ieee80211_sta_tear_down_BA_sessions(sta, false); + ieee80211_sta_tear_down_BA_sessions(sta, tx); } mutex_unlock(&local->sta_mtx); @@ -1447,7 +1438,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); - local->ap_power_level = 0; + local->power_constr_level = 0; del_timer_sync(&local->dynamic_ps_timer); cancel_work_sync(&local->dynamic_ps_enable_work); @@ -1701,12 +1692,11 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_ap_probereq_get); -static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata, - bool transmit_frame) +static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; - u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; + u8 frame_buf[DEAUTH_DISASSOC_LEN]; mutex_lock(&ifmgd->mtx); if (!ifmgd->associated) { @@ -1714,17 +1704,19 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata, return; } + sdata_info(sdata, "Connection to AP %pM lost\n", + ifmgd->associated->bssid); + ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, - transmit_frame, frame_buf); - ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; + false, frame_buf); mutex_unlock(&ifmgd->mtx); /* * must be outside lock due to cfg80211, * but that's not a problem. */ - cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); + cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); mutex_lock(&local->mtx); ieee80211_recalc_idle(local); @@ -1747,24 +1739,10 @@ static void ieee80211_beacon_connection_loss_work(struct work_struct *work) rcu_read_unlock(); } - if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) { - sdata_info(sdata, "Connection to AP %pM lost\n", - ifmgd->bssid); - __ieee80211_disconnect(sdata, false); - } else { + if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) + __ieee80211_connection_loss(sdata); + else ieee80211_mgd_probe_ap(sdata, true); - } -} - -static void ieee80211_csa_connection_drop_work(struct work_struct *work) -{ - struct ieee80211_sub_if_data *sdata = - container_of(work, struct ieee80211_sub_if_data, - u.mgd.csa_connection_drop_work); - - ieee80211_wake_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CSA); - __ieee80211_disconnect(sdata, true); } void ieee80211_beacon_loss(struct ieee80211_vif *vif) @@ -2552,13 +2530,15 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, bssid, true); } - if (elems.country_elem && elems.pwr_constr_elem && - mgmt->u.probe_resp.capab_info & - cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) - ieee80211_handle_pwr_constr(sdata, local->oper_channel, - elems.country_elem, - elems.country_elem_len, - elems.pwr_constr_elem); + /* Note: country IE parsing is done for us by cfg80211 */ + if (elems.country_elem) { + /* TODO: IBSS also needs this */ + if (elems.pwr_constr_elem) + ieee80211_handle_pwr_constr(sdata, + le16_to_cpu(mgmt->u.probe_resp.capab_info), + elems.pwr_constr_elem, + elems.pwr_constr_elem_len); + } ieee80211_bss_info_change_notify(sdata, changed); } @@ -2655,7 +2635,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; + u8 frame_buf[DEAUTH_DISASSOC_LEN]; ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, false, frame_buf); @@ -2665,7 +2645,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, * must be outside lock due to cfg80211, * but that's not a problem. */ - cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); + cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); mutex_lock(&local->mtx); ieee80211_recalc_idle(local); @@ -2949,7 +2929,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) cancel_work_sync(&ifmgd->monitor_work); cancel_work_sync(&ifmgd->beacon_connection_loss_work); - cancel_work_sync(&ifmgd->csa_connection_drop_work); if (del_timer_sync(&ifmgd->timer)) set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); @@ -3006,8 +2985,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); INIT_WORK(&ifmgd->beacon_connection_loss_work, ieee80211_beacon_connection_loss_work); - INIT_WORK(&ifmgd->csa_connection_drop_work, - ieee80211_csa_connection_drop_work); INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); setup_timer(&ifmgd->timer, ieee80211_sta_timer, (unsigned long) sdata); @@ -3548,7 +3525,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, struct cfg80211_deauth_request *req) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; + u8 frame_buf[DEAUTH_DISASSOC_LEN]; mutex_lock(&ifmgd->mtx); @@ -3576,8 +3553,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, mutex_unlock(&ifmgd->mtx); - __cfg80211_send_deauth(sdata->dev, frame_buf, - IEEE80211_DEAUTH_FRAME_LEN); + __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); mutex_lock(&sdata->local->mtx); ieee80211_recalc_idle(sdata->local); @@ -3591,7 +3567,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 bssid[ETH_ALEN]; - u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; + u8 frame_buf[DEAUTH_DISASSOC_LEN]; mutex_lock(&ifmgd->mtx); @@ -3616,8 +3592,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, frame_buf); mutex_unlock(&ifmgd->mtx); - __cfg80211_send_disassoc(sdata->dev, frame_buf, - IEEE80211_DEAUTH_FRAME_LEN); + __cfg80211_send_disassoc(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); mutex_lock(&sdata->local->mtx); ieee80211_recalc_idle(sdata->local); diff --git a/trunk/net/mac80211/offchannel.c b/trunk/net/mac80211/offchannel.c index 83608ac16780..507121dad082 100644 --- a/trunk/net/mac80211/offchannel.c +++ b/trunk/net/mac80211/offchannel.c @@ -233,7 +233,8 @@ static void ieee80211_hw_roc_start(struct work_struct *work) u32 dur = dep->duration; dep->duration = dur - roc->duration; roc->duration = dur; - list_move(&dep->list, &roc->list); + list_del(&dep->list); + list_add(&dep->list, &roc->list); } } out_unlock: diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index c4cdbde24fd3..740e414d44f4 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -407,7 +407,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, enum ieee80211_band band = local->hw.conf.channel->band; sdata = rcu_dereference_protected(local->scan_sdata, - lockdep_is_held(&local->mtx)); + lockdep_is_held(&local->mtx));; for (i = 0; i < local->scan_req->n_ssids; i++) ieee80211_send_probe_req( @@ -917,7 +917,6 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, struct cfg80211_sched_scan_request *req) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sched_scan_ies sched_scan_ies; int ret, i; mutex_lock(&local->mtx); @@ -936,28 +935,33 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, if (!local->hw.wiphy->bands[i]) continue; - sched_scan_ies.ie[i] = kzalloc(2 + IEEE80211_MAX_SSID_LEN + - local->scan_ies_len + - req->ie_len, - GFP_KERNEL); - if (!sched_scan_ies.ie[i]) { + local->sched_scan_ies.ie[i] = kzalloc(2 + + IEEE80211_MAX_SSID_LEN + + local->scan_ies_len + + req->ie_len, + GFP_KERNEL); + if (!local->sched_scan_ies.ie[i]) { ret = -ENOMEM; goto out_free; } - sched_scan_ies.len[i] = - ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], + local->sched_scan_ies.len[i] = + ieee80211_build_preq_ies(local, + local->sched_scan_ies.ie[i], req->ie, req->ie_len, i, (u32) -1, 0); } - ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); - if (ret == 0) + ret = drv_sched_scan_start(local, sdata, req, + &local->sched_scan_ies); + if (ret == 0) { rcu_assign_pointer(local->sched_scan_sdata, sdata); + goto out; + } out_free: while (i > 0) - kfree(sched_scan_ies.ie[--i]); + kfree(local->sched_scan_ies.ie[--i]); out: mutex_unlock(&local->mtx); return ret; @@ -966,7 +970,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; - int ret = 0; + int ret = 0, i; mutex_lock(&local->mtx); @@ -975,9 +979,12 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) goto out; } - if (rcu_access_pointer(local->sched_scan_sdata)) - drv_sched_scan_stop(local, sdata); + if (rcu_access_pointer(local->sched_scan_sdata)) { + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + kfree(local->sched_scan_ies.ie[i]); + drv_sched_scan_stop(local, sdata); + } out: mutex_unlock(&local->mtx); @@ -999,6 +1006,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) struct ieee80211_local *local = container_of(work, struct ieee80211_local, sched_scan_stopped_work); + int i; mutex_lock(&local->mtx); @@ -1007,6 +1015,9 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) return; } + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + kfree(local->sched_scan_ies.ie[i]); + rcu_assign_pointer(local->sched_scan_sdata, NULL); mutex_unlock(&local->mtx); diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index 797dd36a220d..06fa75ceb025 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -91,70 +91,6 @@ static int sta_info_hash_del(struct ieee80211_local *local, return -ENOENT; } -static void free_sta_work(struct work_struct *wk) -{ - struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk); - int ac, i; - struct tid_ampdu_tx *tid_tx; - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct ieee80211_local *local = sdata->local; - - /* - * At this point, when being called as call_rcu callback, - * neither mac80211 nor the driver can reference this - * sta struct any more except by still existing timers - * associated with this station that we clean up below. - */ - - if (test_sta_flag(sta, WLAN_STA_PS_STA)) { - BUG_ON(!sdata->bss); - - clear_sta_flag(sta, WLAN_STA_PS_STA); - - atomic_dec(&sdata->bss->num_sta_ps); - sta_info_recalc_tim(sta); - } - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->tx_filtered[ac]); - } - -#ifdef CONFIG_MAC80211_MESH - if (ieee80211_vif_is_mesh(&sdata->vif)) { - mesh_accept_plinks_update(sdata); - mesh_plink_deactivate(sta); - del_timer_sync(&sta->plink_timer); - } -#endif - - cancel_work_sync(&sta->drv_unblock_wk); - - /* - * Destroy aggregation state here. It would be nice to wait for the - * driver to finish aggregation stop and then clean up, but for now - * drivers have to handle aggregation stop being requested, followed - * directly by station destruction. - */ - for (i = 0; i < STA_TID_NUM; i++) { - tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); - if (!tid_tx) - continue; - __skb_queue_purge(&tid_tx->pending); - kfree(tid_tx); - } - - sta_info_free(local, sta); -} - -static void free_sta_rcu(struct rcu_head *h) -{ - struct sta_info *sta = container_of(h, struct sta_info, rcu_head); - - ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk); -} - /* protected by RCU */ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, const u8 *addr) @@ -305,7 +241,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, spin_lock_init(&sta->lock); INIT_WORK(&sta->drv_unblock_wk, sta_unblock); - INIT_WORK(&sta->free_sta_wk, free_sta_work); INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); mutex_init(&sta->ampdu_mlme.mtx); @@ -719,7 +654,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta) { struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; - int ret, i; + int ret, i, ac; + struct tid_ampdu_tx *tid_tx; might_sleep(); @@ -738,7 +674,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) * will be sufficient. */ set_sta_flag(sta, WLAN_STA_BLOCK_BA); - ieee80211_sta_tear_down_BA_sessions(sta, false); + ieee80211_sta_tear_down_BA_sessions(sta, true); ret = sta_info_hash_del(local, sta); if (ret) @@ -775,14 +711,65 @@ int __must_check __sta_info_destroy(struct sta_info *sta) WARN_ON_ONCE(ret != 0); } + /* + * At this point, after we wait for an RCU grace period, + * neither mac80211 nor the driver can reference this + * sta struct any more except by still existing timers + * associated with this station that we clean up below. + */ + synchronize_rcu(); + + if (test_sta_flag(sta, WLAN_STA_PS_STA)) { + BUG_ON(!sdata->bss); + + clear_sta_flag(sta, WLAN_STA_PS_STA); + + atomic_dec(&sdata->bss->num_sta_ps); + sta_info_recalc_tim(sta); + } + + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); + __skb_queue_purge(&sta->ps_tx_buf[ac]); + __skb_queue_purge(&sta->tx_filtered[ac]); + } + +#ifdef CONFIG_MAC80211_MESH + if (ieee80211_vif_is_mesh(&sdata->vif)) + mesh_accept_plinks_update(sdata); +#endif + sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr); + cancel_work_sync(&sta->drv_unblock_wk); + cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL); rate_control_remove_sta_debugfs(sta); ieee80211_sta_debugfs_remove(sta); - call_rcu(&sta->rcu_head, free_sta_rcu); +#ifdef CONFIG_MAC80211_MESH + if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { + mesh_plink_deactivate(sta); + del_timer_sync(&sta->plink_timer); + } +#endif + + /* + * Destroy aggregation state here. It would be nice to wait for the + * driver to finish aggregation stop and then clean up, but for now + * drivers have to handle aggregation stop being requested, followed + * directly by station destruction. + */ + for (i = 0; i < STA_TID_NUM; i++) { + tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); + if (!tid_tx) + continue; + __skb_queue_purge(&tid_tx->pending); + kfree(tid_tx); + } + + sta_info_free(local, sta); return 0; } diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index c88f161f8118..a470e1123a55 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -287,7 +287,6 @@ struct sta_ampdu_mlme { struct sta_info { /* General information, mostly static */ struct list_head list; - struct rcu_head rcu_head; struct sta_info __rcu *hnext; struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; @@ -298,7 +297,6 @@ struct sta_info { spinlock_t lock; struct work_struct drv_unblock_wk; - struct work_struct free_sta_wk; u16 listen_interval; diff --git a/trunk/net/mac80211/status.c b/trunk/net/mac80211/status.c index 2ce89732d0f2..b0801b7d572d 100644 --- a/trunk/net/mac80211/status.c +++ b/trunk/net/mac80211/status.c @@ -517,41 +517,29 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { u64 cookie = (unsigned long)skb; - bool found = false; - acked = info->flags & IEEE80211_TX_STAT_ACK; - rcu_read_lock(); - - list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (!sdata->dev) - continue; - - if (skb->dev != sdata->dev) - continue; - - found = true; - break; - } - - if (!skb->dev) { - sdata = rcu_dereference(local->p2p_sdata); - if (sdata) - found = true; - } - - if (!found) - skb->dev = NULL; - else if (ieee80211_is_nullfunc(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control)) { - cfg80211_probe_status(sdata->dev, hdr->addr1, + if (ieee80211_is_nullfunc(hdr->frame_control) || + ieee80211_is_qos_nullfunc(hdr->frame_control)) { + cfg80211_probe_status(skb->dev, hdr->addr1, cookie, acked, GFP_ATOMIC); + } else if (skb->dev) { + cfg80211_mgmt_tx_status( + skb->dev->ieee80211_ptr, cookie, skb->data, + skb->len, acked, GFP_ATOMIC); } else { - cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data, - skb->len, acked, GFP_ATOMIC); - } + struct ieee80211_sub_if_data *p2p_sdata; - rcu_read_unlock(); + rcu_read_lock(); + + p2p_sdata = rcu_dereference(local->p2p_sdata); + if (p2p_sdata) { + cfg80211_mgmt_tx_status( + &p2p_sdata->wdev, cookie, skb->data, + skb->len, acked, GFP_ATOMIC); + } + rcu_read_unlock(); + } } if (unlikely(info->ack_frame_id)) { diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index e0e0d1d0e830..29eb4e678235 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -580,7 +580,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) tx->key = NULL; else skip_hw = (tx->key->conf.flags & - IEEE80211_KEY_FLAG_SW_MGMT_TX) && + IEEE80211_KEY_FLAG_SW_MGMT) && ieee80211_is_mgmt(hdr->frame_control); break; case WLAN_CIPHER_SUITE_AES_CMAC: diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 22ca35054dd0..471fb0516c99 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -792,11 +792,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, elems->country_elem_len = elen; break; case WLAN_EID_PWR_CONSTRAINT: - if (elen != 1) { - elem_parse_failed = true; - break; - } elems->pwr_constr_elem = pos; + elems->pwr_constr_elem_len = elen; break; case WLAN_EID_TIMEOUT_INTERVAL: elems->timeout_int = pos; @@ -1007,45 +1004,6 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb(sdata, skb); } -void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, - const u8 *bssid, u16 stype, u16 reason, - bool send_frame, u8 *frame_buf) -{ - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt = (void *)frame_buf; - - /* build frame */ - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); - mgmt->duration = 0; /* initialize only */ - mgmt->seq_ctrl = 0; /* initialize only */ - memcpy(mgmt->da, bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); - memcpy(mgmt->bssid, bssid, ETH_ALEN); - /* u.deauth.reason_code == u.disassoc.reason_code */ - mgmt->u.deauth.reason_code = cpu_to_le16(reason); - - if (send_frame) { - skb = dev_alloc_skb(local->hw.extra_tx_headroom + - IEEE80211_DEAUTH_FRAME_LEN); - if (!skb) - return; - - skb_reserve(skb, local->hw.extra_tx_headroom); - - /* copy in frame */ - memcpy(skb_put(skb, IEEE80211_DEAUTH_FRAME_LEN), - mgmt, IEEE80211_DEAUTH_FRAME_LEN); - - if (sdata->vif.type != NL80211_IFTYPE_STATION || - !(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) - IEEE80211_SKB_CB(skb)->flags |= - IEEE80211_TX_INTFL_DONT_ENCRYPT; - - ieee80211_tx_skb(sdata, skb); - } -} - int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, const u8 *ie, size_t ie_len, enum ieee80211_band band, u32 rate_mask, @@ -1606,13 +1564,14 @@ static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, return 0; } +/* must hold iflist_mtx */ void ieee80211_recalc_smps(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; int count = 0; - mutex_lock(&local->iflist_mtx); + lockdep_assert_held(&local->iflist_mtx); /* * This function could be improved to handle multiple @@ -1641,14 +1600,12 @@ void ieee80211_recalc_smps(struct ieee80211_local *local) } if (smps_mode == local->smps_mode) - goto unlock; + return; set: local->smps_mode = smps_mode; /* changed flag is auto-detected for this */ ieee80211_hw_config(local, 0); - unlock: - mutex_unlock(&local->iflist_mtx); } static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) diff --git a/trunk/net/netfilter/Kconfig b/trunk/net/netfilter/Kconfig index fefa514b9917..3f4b3b4a7762 100644 --- a/trunk/net/netfilter/Kconfig +++ b/trunk/net/netfilter/Kconfig @@ -648,16 +648,6 @@ config NETFILTER_XT_TARGET_MARK (e.g. when running oldconfig). It selects CONFIG_NETFILTER_XT_MARK (combined mark/MARK module). -config NETFILTER_XT_TARGET_NETMAP - tristate '"NETMAP" target support' - depends on NF_NAT - ---help--- - NETMAP is an implementation of static 1:1 NAT mapping of network - addresses. It maps the network address part, while keeping the host - address part intact. - - To compile it as a module, choose M here. If unsure, say N. - config NETFILTER_XT_TARGET_NFLOG tristate '"NFLOG" target support' default m if NETFILTER_ADVANCED=n @@ -690,17 +680,6 @@ config NETFILTER_XT_TARGET_RATEEST To compile it as a module, choose M here. If unsure, say N. -config NETFILTER_XT_TARGET_REDIRECT - tristate "REDIRECT target support" - depends on NF_NAT - ---help--- - REDIRECT is a special case of NAT: all incoming connections are - mapped onto the incoming interface's address, causing the packets to - come to the local machine instead of passing through. This is - useful for transparent proxies. - - To compile it as a module, choose M here. If unsure, say N. - config NETFILTER_XT_TARGET_TEE tristate '"TEE" - packet cloning to alternate destination' depends on NETFILTER_ADVANCED diff --git a/trunk/net/netfilter/Makefile b/trunk/net/netfilter/Makefile index 32596978df1d..0baa3f104fcb 100644 --- a/trunk/net/netfilter/Makefile +++ b/trunk/net/netfilter/Makefile @@ -83,11 +83,9 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o -obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o -obj-$(CONFIG_NETFILTER_XT_TARGET_REDIRECT) += xt_REDIRECT.o obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o diff --git a/trunk/net/netfilter/ipset/ip_set_bitmap_ip.c b/trunk/net/netfilter/ipset/ip_set_bitmap_ip.c index 4a92fd47bd4c..7e1b061aeeba 100644 --- a/trunk/net/netfilter/ipset/ip_set_bitmap_ip.c +++ b/trunk/net/netfilter/ipset/ip_set_bitmap_ip.c @@ -27,12 +27,9 @@ #define IP_SET_BITMAP_TIMEOUT #include -#define REVISION_MIN 0 -#define REVISION_MAX 0 - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("bitmap:ip type of IP sets"); MODULE_ALIAS("ip_set_bitmap:ip"); /* Type structure */ @@ -287,7 +284,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], } else if (tb[IPSET_ATTR_CIDR]) { u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); - if (!cidr || cidr > 32) + if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); } else @@ -457,8 +454,7 @@ static int bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { struct bitmap_ip *map; - u32 first_ip, last_ip, hosts; - u64 elements; + u32 first_ip, last_ip, hosts, elements; u8 netmask = 32; int ret; @@ -501,7 +497,7 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) if (netmask == 32) { hosts = 1; - elements = (u64)last_ip - first_ip + 1; + elements = last_ip - first_ip + 1; } else { u8 mask_bits; u32 mask; @@ -519,8 +515,7 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) if (elements > IPSET_BITMAP_MAX_RANGE + 1) return -IPSET_ERR_BITMAP_RANGE_SIZE; - pr_debug("hosts %u, elements %llu\n", - hosts, (unsigned long long)elements); + pr_debug("hosts %u, elements %u\n", hosts, elements); map = kzalloc(sizeof(*map), GFP_KERNEL); if (!map) @@ -559,8 +554,8 @@ static struct ip_set_type bitmap_ip_type __read_mostly = { .features = IPSET_TYPE_IP, .dimension = IPSET_DIM_ONE, .family = NFPROTO_IPV4, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + .revision_max = 0, .create = bitmap_ip_create, .create_policy = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, diff --git a/trunk/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/trunk/net/netfilter/ipset/ip_set_bitmap_ipmac.c index 0f92dc24cb89..d7eaf10edb6d 100644 --- a/trunk/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/trunk/net/netfilter/ipset/ip_set_bitmap_ipmac.c @@ -26,12 +26,9 @@ #include #include -#define REVISION_MIN 0 -#define REVISION_MAX 0 - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets"); MODULE_ALIAS("ip_set_bitmap:ip,mac"); enum { @@ -323,11 +320,11 @@ bitmap_ipmac_tlist(const struct ip_set *set, (elem->match == MAC_FILLED && nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, elem->ether))) - goto nla_put_failure; + goto nla_put_failure; timeout = elem->match == MAC_UNSET ? elem->timeout : ip_set_timeout_get(elem->timeout); if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout))) - goto nla_put_failure; + goto nla_put_failure; ipset_nest_end(skb, nested); } ipset_nest_end(skb, atd); @@ -560,8 +557,7 @@ static int bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - u32 first_ip, last_ip; - u64 elements; + u32 first_ip, last_ip, elements; struct bitmap_ipmac *map; int ret; @@ -592,7 +588,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], } else return -IPSET_ERR_PROTOCOL; - elements = (u64)last_ip - first_ip + 1; + elements = last_ip - first_ip + 1; if (elements > IPSET_BITMAP_MAX_RANGE + 1) return -IPSET_ERR_BITMAP_RANGE_SIZE; @@ -633,8 +629,8 @@ static struct ip_set_type bitmap_ipmac_type = { .features = IPSET_TYPE_IP | IPSET_TYPE_MAC, .dimension = IPSET_DIM_TWO, .family = NFPROTO_IPV4, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + .revision_max = 0, .create = bitmap_ipmac_create, .create_policy = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, diff --git a/trunk/net/netfilter/ipset/ip_set_bitmap_port.c b/trunk/net/netfilter/ipset/ip_set_bitmap_port.c index e6b2db76f4c3..b9f1fce7053b 100644 --- a/trunk/net/netfilter/ipset/ip_set_bitmap_port.c +++ b/trunk/net/netfilter/ipset/ip_set_bitmap_port.c @@ -22,12 +22,9 @@ #define IP_SET_BITMAP_TIMEOUT #include -#define REVISION_MIN 0 -#define REVISION_MAX 0 - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("bitmap:port type of IP sets"); MODULE_ALIAS("ip_set_bitmap:port"); /* Type structure */ @@ -490,8 +487,8 @@ static struct ip_set_type bitmap_port_type = { .features = IPSET_TYPE_PORT, .dimension = IPSET_DIM_ONE, .family = NFPROTO_UNSPEC, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + .revision_max = 0, .create = bitmap_port_create, .create_policy = { [IPSET_ATTR_PORT] = { .type = NLA_U16 }, diff --git a/trunk/net/netfilter/ipset/ip_set_core.c b/trunk/net/netfilter/ipset/ip_set_core.c index 778465f217fa..ad39ef406851 100644 --- a/trunk/net/netfilter/ipset/ip_set_core.c +++ b/trunk/net/netfilter/ipset/ip_set_core.c @@ -69,8 +69,7 @@ find_set_type(const char *name, u8 family, u8 revision) list_for_each_entry_rcu(type, &ip_set_type_list, list) if (STREQ(type->name, name) && - (type->family == family || - type->family == NFPROTO_UNSPEC) && + (type->family == family || type->family == NFPROTO_UNSPEC) && revision >= type->revision_min && revision <= type->revision_max) return type; @@ -150,8 +149,7 @@ __find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max, rcu_read_lock(); list_for_each_entry_rcu(type, &ip_set_type_list, list) if (STREQ(type->name, name) && - (type->family == family || - type->family == NFPROTO_UNSPEC)) { + (type->family == family || type->family == NFPROTO_UNSPEC)) { found = true; if (type->revision_min < *min) *min = type->revision_min; @@ -370,12 +368,6 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, set->variant->kadt(set, skb, par, IPSET_ADD, opt); write_unlock_bh(&set->lock); ret = 1; - } else { - /* --return-nomatch: invert matched element */ - if ((opt->flags & IPSET_RETURN_NOMATCH) && - (set->type->features & IPSET_TYPE_NOMATCH) && - (ret > 0 || ret == -ENOTEMPTY)) - ret = -ret; } /* Convert error codes to nomatch */ @@ -729,8 +721,7 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb, * by the nfnl mutex. Find the first free index in ip_set_list * and check clashing. */ - ret = find_free_id(set->name, &index, &clash); - if (ret != 0) { + if ((ret = find_free_id(set->name, &index, &clash)) != 0) { /* If this is the same set and requested, ignore error */ if (ret == -EEXIST && (flags & IPSET_FLAG_EXIST) && diff --git a/trunk/net/netfilter/ipset/ip_set_hash_ip.c b/trunk/net/netfilter/ipset/ip_set_hash_ip.c index ec3dba5dcd62..a68dbd4f1e4e 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_ip.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_ip.c @@ -24,12 +24,9 @@ #include #include -#define REVISION_MIN 0 -#define REVISION_MAX 0 - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("hash:ip", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("hash:ip type of IP sets"); MODULE_ALIAS("ip_set_hash:ip"); /* Type specific function prefix */ @@ -117,7 +114,7 @@ hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data) static inline void hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d) { - h->next.ip = d->ip; + h->next.ip = ntohl(d->ip); } static int @@ -182,7 +179,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], } else if (tb[IPSET_ATTR_CIDR]) { u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); - if (!cidr || cidr > 32) + if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); } else @@ -191,7 +188,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); if (retried) - ip = ntohl(h->next.ip); + ip = h->next.ip; for (; !before(ip_to, ip); ip += hosts) { nip = htonl(ip); if (nip == 0) @@ -455,8 +452,8 @@ static struct ip_set_type hash_ip_type __read_mostly = { .features = IPSET_TYPE_IP, .dimension = IPSET_DIM_ONE, .family = NFPROTO_UNSPEC, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + .revision_max = 0, .create = hash_ip_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/trunk/net/netfilter/ipset/ip_set_hash_ipport.c b/trunk/net/netfilter/ipset/ip_set_hash_ipport.c index 0171f7502fa5..92722bb82eea 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_ipport.c @@ -25,12 +25,9 @@ #include #include -#define REVISION_MIN 0 -#define REVISION_MAX 1 /* SCTP and UDPLITE support added */ - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("hash:ip,port", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("hash:ip,port type of IP sets"); MODULE_ALIAS("ip_set_hash:ip,port"); /* Type specific function prefix */ @@ -133,8 +130,8 @@ static inline void hash_ipport4_data_next(struct ip_set_hash *h, const struct hash_ipport4_elem *d) { - h->next.ip = d->ip; - h->next.port = d->port; + h->next.ip = ntohl(d->ip); + h->next.port = ntohs(d->port); } static int @@ -220,7 +217,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], } else if (tb[IPSET_ATTR_CIDR]) { u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); - if (!cidr || cidr > 32) + if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); } else @@ -234,10 +231,9 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], } if (retried) - ip = ntohl(h->next.ip); + ip = h->next.ip; for (; !before(ip_to, ip); ip++) { - p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) - : port; + p = retried && ip == h->next.ip ? h->next.port : port; for (; p <= port_to; p++) { data.ip = htonl(ip); data.port = htons(p); @@ -353,7 +349,7 @@ static inline void hash_ipport6_data_next(struct ip_set_hash *h, const struct hash_ipport6_elem *d) { - h->next.port = d->port; + h->next.port = ntohs(d->port); } static int @@ -435,7 +431,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], swap(port, port_to); if (retried) - port = ntohs(h->next.port); + port = h->next.port; for (; port <= port_to; port++) { data.port = htons(port); ret = adtfn(set, &data, timeout, flags); @@ -526,8 +522,8 @@ static struct ip_set_type hash_ipport_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, .dimension = IPSET_DIM_TWO, .family = NFPROTO_UNSPEC, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + .revision_max = 1, /* SCTP and UDPLITE support added */ .create = hash_ipport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/trunk/net/netfilter/ipset/ip_set_hash_ipportip.c b/trunk/net/netfilter/ipset/ip_set_hash_ipportip.c index 6344ef551ec8..0637ce096def 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_ipportip.c @@ -25,12 +25,9 @@ #include #include -#define REVISION_MIN 0 -#define REVISION_MAX 1 /* SCTP and UDPLITE support added */ - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("hash:ip,port,ip", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets"); MODULE_ALIAS("ip_set_hash:ip,port,ip"); /* Type specific function prefix */ @@ -136,8 +133,8 @@ static inline void hash_ipportip4_data_next(struct ip_set_hash *h, const struct hash_ipportip4_elem *d) { - h->next.ip = d->ip; - h->next.port = d->port; + h->next.ip = ntohl(d->ip); + h->next.port = ntohs(d->port); } static int @@ -228,7 +225,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], } else if (tb[IPSET_ATTR_CIDR]) { u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); - if (!cidr || cidr > 32) + if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); } else @@ -242,10 +239,9 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], } if (retried) - ip = ntohl(h->next.ip); + ip = h->next.ip; for (; !before(ip_to, ip); ip++) { - p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) - : port; + p = retried && ip == h->next.ip ? h->next.port : port; for (; p <= port_to; p++) { data.ip = htonl(ip); data.port = htons(p); @@ -366,7 +362,7 @@ static inline void hash_ipportip6_data_next(struct ip_set_hash *h, const struct hash_ipportip6_elem *d) { - h->next.port = d->port; + h->next.port = ntohs(d->port); } static int @@ -453,7 +449,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], swap(port, port_to); if (retried) - port = ntohs(h->next.port); + port = h->next.port; for (; port <= port_to; port++) { data.port = htons(port); ret = adtfn(set, &data, timeout, flags); @@ -544,8 +540,8 @@ static struct ip_set_type hash_ipportip_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, .dimension = IPSET_DIM_THREE, .family = NFPROTO_UNSPEC, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + .revision_max = 1, /* SCTP and UDPLITE support added */ .create = hash_ipportip_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/trunk/net/netfilter/ipset/ip_set_hash_ipportnet.c b/trunk/net/netfilter/ipset/ip_set_hash_ipportnet.c index cb71f9a774e7..1ce21ca976e1 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -25,14 +25,9 @@ #include #include -#define REVISION_MIN 0 -/* 1 SCTP and UDPLITE support added */ -/* 2 Range as input support for IPv4 added */ -#define REVISION_MAX 3 /* nomatch flag support added */ - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("hash:ip,port,net", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("hash:ip,port,net type of IP sets"); MODULE_ALIAS("ip_set_hash:ip,port,net"); /* Type specific function prefix */ @@ -104,10 +99,10 @@ hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags) dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); } -static inline int +static inline bool hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem) { - return elem->nomatch ? -ENOTEMPTY : 1; + return !elem->nomatch; } static inline void @@ -178,9 +173,9 @@ static inline void hash_ipportnet4_data_next(struct ip_set_hash *h, const struct hash_ipportnet4_elem *d) { - h->next.ip = d->ip; - h->next.port = d->port; - h->next.ip2 = d->ip2; + h->next.ip = ntohl(d->ip); + h->next.port = ntohs(d->port); + h->next.ip2 = ntohl(d->ip2); } static int @@ -295,7 +290,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], } else if (tb[IPSET_ATTR_CIDR]) { u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); - if (!cidr || cidr > 32) + if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); } @@ -319,17 +314,14 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], } if (retried) - ip = ntohl(h->next.ip); + ip = h->next.ip; for (; !before(ip_to, ip); ip++) { data.ip = htonl(ip); - p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) - : port; + p = retried && ip == h->next.ip ? h->next.port : port; for (; p <= port_to; p++) { data.port = htons(p); - ip2 = retried - && ip == ntohl(h->next.ip) - && p == ntohs(h->next.port) - ? ntohl(h->next.ip2) : ip2_from; + ip2 = retried && ip == h->next.ip && p == h->next.port + ? h->next.ip2 : ip2_from; while (!after(ip2, ip2_to)) { data.ip2 = htonl(ip2); ip2_last = ip_set_range_to_cidr(ip2, ip2_to, @@ -411,10 +403,10 @@ hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags) dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); } -static inline int +static inline bool hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem) { - return elem->nomatch ? -ENOTEMPTY : 1; + return !elem->nomatch; } static inline void @@ -494,7 +486,7 @@ static inline void hash_ipportnet6_data_next(struct ip_set_hash *h, const struct hash_ipportnet6_elem *d) { - h->next.port = d->port; + h->next.port = ntohs(d->port); } static int @@ -606,7 +598,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], swap(port, port_to); if (retried) - port = ntohs(h->next.port); + port = h->next.port; for (; port <= port_to; port++) { data.port = htons(port); ret = adtfn(set, &data, timeout, flags); @@ -697,12 +689,13 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags) static struct ip_set_type hash_ipportnet_type __read_mostly = { .name = "hash:ip,port,net", .protocol = IPSET_PROTOCOL, - .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2 | - IPSET_TYPE_NOMATCH, + .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, .dimension = IPSET_DIM_THREE, .family = NFPROTO_UNSPEC, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + /* 1 SCTP and UDPLITE support added */ + /* 2 Range as input support for IPv4 added */ + .revision_max = 3, /* nomatch flag support added */ .create = hash_ipportnet_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/trunk/net/netfilter/ipset/ip_set_hash_net.c b/trunk/net/netfilter/ipset/ip_set_hash_net.c index 29e94b981f3f..c57a6a09906d 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_net.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_net.c @@ -23,13 +23,9 @@ #include #include -#define REVISION_MIN 0 -/* 1 Range as input support for IPv4 added */ -#define REVISION_MAX 2 /* nomatch flag support added */ - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("hash:net", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("hash:net type of IP sets"); MODULE_ALIAS("ip_set_hash:net"); /* Type specific function prefix */ @@ -90,10 +86,10 @@ hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags) dst->nomatch = flags & IPSET_FLAG_NOMATCH; } -static inline int +static inline bool hash_net4_data_match(const struct hash_net4_elem *elem) { - return elem->nomatch ? -ENOTEMPTY : 1; + return !elem->nomatch; } static inline void @@ -156,7 +152,7 @@ static inline void hash_net4_data_next(struct ip_set_hash *h, const struct hash_net4_elem *d) { - h->next.ip = d->ip; + h->next.ip = ntohl(d->ip); } static int @@ -239,7 +235,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], return -IPSET_ERR_HASH_RANGE; } if (retried) - ip = ntohl(h->next.ip); + ip = h->next.ip; while (!after(ip, ip_to)) { data.ip = htonl(ip); last = ip_set_range_to_cidr(ip, ip_to, &data.cidr); @@ -311,10 +307,10 @@ hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags) dst->nomatch = flags & IPSET_FLAG_NOMATCH; } -static inline int +static inline bool hash_net6_data_match(const struct hash_net6_elem *elem) { - return elem->nomatch ? -ENOTEMPTY : 1; + return !elem->nomatch; } static inline void @@ -536,11 +532,12 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags) static struct ip_set_type hash_net_type __read_mostly = { .name = "hash:net", .protocol = IPSET_PROTOCOL, - .features = IPSET_TYPE_IP | IPSET_TYPE_NOMATCH, + .features = IPSET_TYPE_IP, .dimension = IPSET_DIM_ONE, .family = NFPROTO_UNSPEC, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + /* = 1 Range as input support for IPv4 added */ + .revision_max = 2, /* nomatch flag support added */ .create = hash_net_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/trunk/net/netfilter/ipset/ip_set_hash_netiface.c b/trunk/net/netfilter/ipset/ip_set_hash_netiface.c index b9a63381e349..d5d3607ae7bc 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_netiface.c @@ -24,13 +24,9 @@ #include #include -#define REVISION_MIN 0 -/* 1 nomatch flag support added */ -#define REVISION_MAX 2 /* /0 support added */ - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("hash:net,iface", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("hash:net,iface type of IP sets"); MODULE_ALIAS("ip_set_hash:net,iface"); /* Interface name rbtree */ @@ -144,7 +140,7 @@ struct hash_netiface4_elem_hashed { u8 physdev; u8 cidr; u8 nomatch; - u8 elem; + u8 padding; }; #define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed) @@ -155,7 +151,7 @@ struct hash_netiface4_elem { u8 physdev; u8 cidr; u8 nomatch; - u8 elem; + u8 padding; const char *iface; }; @@ -165,7 +161,7 @@ struct hash_netiface4_telem { u8 physdev; u8 cidr; u8 nomatch; - u8 elem; + u8 padding; const char *iface; unsigned long timeout; }; @@ -185,14 +181,18 @@ hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1, static inline bool hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem) { - return elem->elem == 0; + return elem->cidr == 0; } static inline void hash_netiface4_data_copy(struct hash_netiface4_elem *dst, const struct hash_netiface4_elem *src) { - memcpy(dst, src, sizeof(*dst)); + dst->ip = src->ip; + dst->cidr = src->cidr; + dst->physdev = src->physdev; + dst->iface = src->iface; + dst->nomatch = src->nomatch; } static inline void @@ -201,10 +201,10 @@ hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags) dst->nomatch = flags & IPSET_FLAG_NOMATCH; } -static inline int +static inline bool hash_netiface4_data_match(const struct hash_netiface4_elem *elem) { - return elem->nomatch ? -ENOTEMPTY : 1; + return !elem->nomatch; } static inline void @@ -217,7 +217,7 @@ hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr) static inline void hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem) { - elem->elem = 0; + elem->cidr = 0; } static bool @@ -277,7 +277,7 @@ static inline void hash_netiface4_data_next(struct ip_set_hash *h, const struct hash_netiface4_elem *d) { - h->next.ip = d->ip; + h->next.ip = ntohl(d->ip); } static int @@ -288,8 +288,7 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb, struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netiface4_elem data = { - .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK, - .elem = 1, + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK }; int ret; @@ -340,7 +339,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], { struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_netiface4_elem data = { .cidr = HOST_MASK, .elem = 1 }; + struct hash_netiface4_elem data = { .cidr = HOST_MASK }; u32 ip = 0, ip_to, last; u32 timeout = h->timeout; char iface[IFNAMSIZ]; @@ -361,7 +360,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_CIDR]) { data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); - if (data.cidr > HOST_MASK) + if (!data.cidr || data.cidr > HOST_MASK) return -IPSET_ERR_INVALID_CIDR; } @@ -390,6 +389,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH)) flags |= (cadt_flags << 16); } + if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { data.ip = htonl(ip & ip_set_hostmask(data.cidr)); ret = adtfn(set, &data, timeout, flags); @@ -409,7 +409,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], } if (retried) - ip = ntohl(h->next.ip); + ip = h->next.ip; while (!after(ip, ip_to)) { data.ip = htonl(ip); last = ip_set_range_to_cidr(ip, ip_to, &data.cidr); @@ -442,7 +442,7 @@ struct hash_netiface6_elem_hashed { u8 physdev; u8 cidr; u8 nomatch; - u8 elem; + u8 padding; }; #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed) @@ -452,7 +452,7 @@ struct hash_netiface6_elem { u8 physdev; u8 cidr; u8 nomatch; - u8 elem; + u8 padding; const char *iface; }; @@ -461,7 +461,7 @@ struct hash_netiface6_telem { u8 physdev; u8 cidr; u8 nomatch; - u8 elem; + u8 padding; const char *iface; unsigned long timeout; }; @@ -481,7 +481,7 @@ hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, static inline bool hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem) { - return elem->elem == 0; + return elem->cidr == 0; } static inline void @@ -497,16 +497,16 @@ hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags) dst->nomatch = flags & IPSET_FLAG_NOMATCH; } -static inline int +static inline bool hash_netiface6_data_match(const struct hash_netiface6_elem *elem) { - return elem->nomatch ? -ENOTEMPTY : 1; + return !elem->nomatch; } static inline void hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem) { - elem->elem = 0; + elem->cidr = 0; } static inline void @@ -590,8 +590,7 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb, struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netiface6_elem data = { - .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK, - .elem = 1, + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK }; int ret; @@ -638,7 +637,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], { struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_netiface6_elem data = { .cidr = HOST_MASK, .elem = 1 }; + struct hash_netiface6_elem data = { .cidr = HOST_MASK }; u32 timeout = h->timeout; char iface[IFNAMSIZ]; int ret; @@ -660,7 +659,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_CIDR]) data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); - if (data.cidr > HOST_MASK) + if (!data.cidr || data.cidr > HOST_MASK) return -IPSET_ERR_INVALID_CIDR; ip6_netmask(&data.ip, data.cidr); @@ -774,12 +773,11 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags) static struct ip_set_type hash_netiface_type __read_mostly = { .name = "hash:net,iface", .protocol = IPSET_PROTOCOL, - .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE | - IPSET_TYPE_NOMATCH, + .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE, .dimension = IPSET_DIM_TWO, .family = NFPROTO_UNSPEC, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + .revision_max = 1, /* nomatch flag support added */ .create = hash_netiface_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/trunk/net/netfilter/ipset/ip_set_hash_netport.c b/trunk/net/netfilter/ipset/ip_set_hash_netport.c index 7ef700de596c..fc3143a2d41b 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_netport.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_netport.c @@ -24,14 +24,9 @@ #include #include -#define REVISION_MIN 0 -/* 1 SCTP and UDPLITE support added */ -/* 2 Range as input support for IPv4 added */ -#define REVISION_MAX 3 /* nomatch flag support added */ - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("hash:net,port", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("hash:net,port type of IP sets"); MODULE_ALIAS("ip_set_hash:net,port"); /* Type specific function prefix */ @@ -104,10 +99,10 @@ hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags) dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); } -static inline int +static inline bool hash_netport4_data_match(const struct hash_netport4_elem *elem) { - return elem->nomatch ? -ENOTEMPTY : 1; + return !elem->nomatch; } static inline void @@ -176,8 +171,8 @@ static inline void hash_netport4_data_next(struct ip_set_hash *h, const struct hash_netport4_elem *d) { - h->next.ip = d->ip; - h->next.port = d->port; + h->next.ip = ntohl(d->ip); + h->next.port = ntohs(d->port); } static int @@ -294,13 +289,12 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], } if (retried) - ip = ntohl(h->next.ip); + ip = h->next.ip; while (!after(ip, ip_to)) { data.ip = htonl(ip); last = ip_set_range_to_cidr(ip, ip_to, &cidr); data.cidr = cidr - 1; - p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) - : port; + p = retried && ip == h->next.ip ? h->next.port : port; for (; p <= port_to; p++) { data.port = htons(p); ret = adtfn(set, &data, timeout, flags); @@ -375,10 +369,10 @@ hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags) dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); } -static inline int +static inline bool hash_netport6_data_match(const struct hash_netport6_elem *elem) { - return elem->nomatch ? -ENOTEMPTY : 1; + return !elem->nomatch; } static inline void @@ -456,7 +450,7 @@ static inline void hash_netport6_data_next(struct ip_set_hash *h, const struct hash_netport6_elem *d) { - h->next.port = d->port; + h->next.port = ntohs(d->port); } static int @@ -560,7 +554,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], swap(port, port_to); if (retried) - port = ntohs(h->next.port); + port = h->next.port; for (; port <= port_to; port++) { data.port = htons(port); ret = adtfn(set, &data, timeout, flags); @@ -650,11 +644,13 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) static struct ip_set_type hash_netport_type __read_mostly = { .name = "hash:net,port", .protocol = IPSET_PROTOCOL, - .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_NOMATCH, + .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, .dimension = IPSET_DIM_TWO, .family = NFPROTO_UNSPEC, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + /* 1 SCTP and UDPLITE support added */ + /* 2, Range as input support for IPv4 added */ + .revision_max = 3, /* nomatch flag support added */ .create = hash_netport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/trunk/net/netfilter/ipset/ip_set_list_set.c b/trunk/net/netfilter/ipset/ip_set_list_set.c index 8371c2bac2e4..6cb1225765f9 100644 --- a/trunk/net/netfilter/ipset/ip_set_list_set.c +++ b/trunk/net/netfilter/ipset/ip_set_list_set.c @@ -16,12 +16,9 @@ #include #include -#define REVISION_MIN 0 -#define REVISION_MAX 0 - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); -IP_SET_MODULE_DESC("list:set", REVISION_MIN, REVISION_MAX); +MODULE_DESCRIPTION("list:set type of IP sets"); MODULE_ALIAS("ip_set_list:set"); /* Member elements without and with timeout */ @@ -582,8 +579,8 @@ static struct ip_set_type list_set_type __read_mostly = { .features = IPSET_TYPE_NAME | IPSET_DUMP_LAST, .dimension = IPSET_DIM_ONE, .family = NFPROTO_UNSPEC, - .revision_min = REVISION_MIN, - .revision_max = REVISION_MAX, + .revision_min = 0, + .revision_max = 0, .create = list_set_create, .create_policy = { [IPSET_ATTR_SIZE] = { .type = NLA_U32 }, diff --git a/trunk/net/netfilter/nf_conntrack_core.c b/trunk/net/netfilter/nf_conntrack_core.c index 0f241be28f9e..dcb27910ab3c 100644 --- a/trunk/net/netfilter/nf_conntrack_core.c +++ b/trunk/net/netfilter/nf_conntrack_core.c @@ -1224,8 +1224,6 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), spin_lock_bh(&nf_conntrack_lock); for (; *bucket < net->ct.htable_size; (*bucket)++) { hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { - if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) - continue; ct = nf_ct_tuplehash_to_ctrack(h); if (iter(ct, data)) goto found; diff --git a/trunk/net/netfilter/nf_conntrack_ftp.c b/trunk/net/netfilter/nf_conntrack_ftp.c index 1ce3befb7c8a..f8cc26ad4456 100644 --- a/trunk/net/netfilter/nf_conntrack_ftp.c +++ b/trunk/net/netfilter/nf_conntrack_ftp.c @@ -396,12 +396,6 @@ static int help(struct sk_buff *skb, /* Look up to see if we're just after a \n. */ if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) { - /* We're picking up this, clear flags and let it continue */ - if (unlikely(ct_ftp_info->flags[dir] & NF_CT_FTP_SEQ_PICKUP)) { - ct_ftp_info->flags[dir] ^= NF_CT_FTP_SEQ_PICKUP; - goto skip_nl_seq; - } - /* Now if this ends in \n, update ftp info. */ pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n", ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)", @@ -412,7 +406,6 @@ static int help(struct sk_buff *skb, goto out_update_nl; } -skip_nl_seq: /* Initialize IP/IPv6 addr to expected address (it's not mentioned in EPSV responses) */ cmd.l3num = nf_ct_l3num(ct); @@ -519,19 +512,6 @@ static int help(struct sk_buff *skb, return ret; } -static int nf_ct_ftp_from_nlattr(struct nlattr *attr, struct nf_conn *ct) -{ - struct nf_ct_ftp_master *ftp = nfct_help_data(ct); - - /* This conntrack has been injected from user-space, always pick up - * sequence tracking. Otherwise, the first FTP command after the - * failover breaks. - */ - ftp->flags[IP_CT_DIR_ORIGINAL] |= NF_CT_FTP_SEQ_PICKUP; - ftp->flags[IP_CT_DIR_REPLY] |= NF_CT_FTP_SEQ_PICKUP; - return 0; -} - static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly; static const struct nf_conntrack_expect_policy ftp_exp_policy = { @@ -581,7 +561,6 @@ static int __init nf_conntrack_ftp_init(void) ftp[i][j].expect_policy = &ftp_exp_policy; ftp[i][j].me = THIS_MODULE; ftp[i][j].help = help; - ftp[i][j].from_nlattr = nf_ct_ftp_from_nlattr; if (ports[i] == FTP_PORT) sprintf(ftp[i][j].name, "ftp"); else diff --git a/trunk/net/netfilter/nf_conntrack_netlink.c b/trunk/net/netfilter/nf_conntrack_netlink.c index 7bbfb3deea30..2dcd080b8c4f 100644 --- a/trunk/net/netfilter/nf_conntrack_netlink.c +++ b/trunk/net/netfilter/nf_conntrack_netlink.c @@ -1238,7 +1238,7 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) if (help) { if (help->helper == helper) { /* update private helper data if allowed. */ - if (helper->from_nlattr) + if (helper->from_nlattr && helpinfo) helper->from_nlattr(helpinfo, ct); return 0; } else @@ -1467,7 +1467,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, goto err2; } /* set private helper data if allowed. */ - if (helper->from_nlattr) + if (helper->from_nlattr && helpinfo) helper->from_nlattr(helpinfo, ct); /* not in hash table yet so not strictly necessary */ diff --git a/trunk/net/netfilter/nf_nat_core.c b/trunk/net/netfilter/nf_nat_core.c index 5f2f9109f461..1816ad381485 100644 --- a/trunk/net/netfilter/nf_nat_core.c +++ b/trunk/net/netfilter/nf_nat_core.c @@ -201,8 +201,10 @@ find_appropriate_src(struct net *net, u16 zone, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); result->dst = tuple->dst; - if (in_range(l3proto, l4proto, result, range)) + if (in_range(l3proto, l4proto, result, range)) { + rcu_read_unlock(); return 1; + } } } return 0; @@ -479,8 +481,6 @@ static int nf_nat_proto_clean(struct nf_conn *i, void *data) if (!nat) return 0; - if (!(i->status & IPS_SRC_NAT_DONE)) - return 0; if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) || (clean->l4proto && nf_ct_protonum(i) != clean->l4proto)) return 0; diff --git a/trunk/net/netfilter/nfnetlink_cthelper.c b/trunk/net/netfilter/nfnetlink_cthelper.c index 945950a8b1f1..3678073360a3 100644 --- a/trunk/net/netfilter/nfnetlink_cthelper.c +++ b/trunk/net/netfilter/nfnetlink_cthelper.c @@ -85,9 +85,6 @@ nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct) { const struct nf_conn_help *help = nfct_help(ct); - if (attr == NULL) - return -EINVAL; - if (help->helper->data_len == 0) return -EINVAL; diff --git a/trunk/net/netfilter/nfnetlink_queue_core.c b/trunk/net/netfilter/nfnetlink_queue_core.c index e12d44e75b21..43de3a03ee76 100644 --- a/trunk/net/netfilter/nfnetlink_queue_core.c +++ b/trunk/net/netfilter/nfnetlink_queue_core.c @@ -225,7 +225,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, { sk_buff_data_t old_tail; size_t size; - size_t data_len = 0, cap_len = 0; + size_t data_len = 0; struct sk_buff *skb; struct nlattr *nla; struct nfqnl_msg_packet_hdr *pmsg; @@ -247,8 +247,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, #endif + nla_total_size(sizeof(u_int32_t)) /* mark */ + nla_total_size(sizeof(struct nfqnl_msg_packet_hw)) - + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp) - + nla_total_size(sizeof(u_int32_t))); /* cap_len */ + + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); outdev = entry->outdev; @@ -267,7 +266,6 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, data_len = entskb->len; size += nla_total_size(data_len); - cap_len = entskb->len; break; } @@ -404,9 +402,6 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0) goto nla_put_failure; - if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) - goto nla_put_failure; - nlh->nlmsg_len = skb->tail - old_tail; return skb; @@ -531,13 +526,9 @@ nfqnl_set_mode(struct nfqnl_instance *queue, case NFQNL_COPY_PACKET: queue->copy_mode = mode; - /* We're using struct nlattr which has 16bit nla_len. Note that - * nla_len includes the header length. Thus, the maximum packet - * length that we support is 65531 bytes. We send truncated - * packets if the specified length is larger than that. - */ - if (range > 0xffff - NLA_HDRLEN) - queue->copy_range = 0xffff - NLA_HDRLEN; + /* we're using struct nlattr which has 16bit nla_len */ + if (range > 0xffff) + queue->copy_range = 0xffff; else queue->copy_range = range; break; diff --git a/trunk/net/netfilter/xt_NETMAP.c b/trunk/net/netfilter/xt_NETMAP.c deleted file mode 100644 index b253e07cb1c5..000000000000 --- a/trunk/net/netfilter/xt_NETMAP.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * (C) 2000-2001 Svenning Soerensen - * Copyright (c) 2011 Patrick McHardy - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned int -netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par) -{ - const struct nf_nat_range *range = par->targinfo; - struct nf_nat_range newrange; - struct nf_conn *ct; - enum ip_conntrack_info ctinfo; - union nf_inet_addr new_addr, netmask; - unsigned int i; - - ct = nf_ct_get(skb, &ctinfo); - for (i = 0; i < ARRAY_SIZE(range->min_addr.ip6); i++) - netmask.ip6[i] = ~(range->min_addr.ip6[i] ^ - range->max_addr.ip6[i]); - - if (par->hooknum == NF_INET_PRE_ROUTING || - par->hooknum == NF_INET_LOCAL_OUT) - new_addr.in6 = ipv6_hdr(skb)->daddr; - else - new_addr.in6 = ipv6_hdr(skb)->saddr; - - for (i = 0; i < ARRAY_SIZE(new_addr.ip6); i++) { - new_addr.ip6[i] &= ~netmask.ip6[i]; - new_addr.ip6[i] |= range->min_addr.ip6[i] & - netmask.ip6[i]; - } - - newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; - newrange.min_addr = new_addr; - newrange.max_addr = new_addr; - newrange.min_proto = range->min_proto; - newrange.max_proto = range->max_proto; - - return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); -} - -static int netmap_tg6_checkentry(const struct xt_tgchk_param *par) -{ - const struct nf_nat_range *range = par->targinfo; - - if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) - return -EINVAL; - return 0; -} - -static unsigned int -netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par) -{ - struct nf_conn *ct; - enum ip_conntrack_info ctinfo; - __be32 new_ip, netmask; - const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; - struct nf_nat_range newrange; - - NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || - par->hooknum == NF_INET_POST_ROUTING || - par->hooknum == NF_INET_LOCAL_OUT || - par->hooknum == NF_INET_LOCAL_IN); - ct = nf_ct_get(skb, &ctinfo); - - netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); - - if (par->hooknum == NF_INET_PRE_ROUTING || - par->hooknum == NF_INET_LOCAL_OUT) - new_ip = ip_hdr(skb)->daddr & ~netmask; - else - new_ip = ip_hdr(skb)->saddr & ~netmask; - new_ip |= mr->range[0].min_ip & netmask; - - memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); - memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); - newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; - newrange.min_addr.ip = new_ip; - newrange.max_addr.ip = new_ip; - newrange.min_proto = mr->range[0].min; - newrange.max_proto = mr->range[0].max; - - /* Hand modified range to generic setup. */ - return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); -} - -static int netmap_tg4_check(const struct xt_tgchk_param *par) -{ - const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; - - if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) { - pr_debug("bad MAP_IPS.\n"); - return -EINVAL; - } - if (mr->rangesize != 1) { - pr_debug("bad rangesize %u.\n", mr->rangesize); - return -EINVAL; - } - return 0; -} - -static struct xt_target netmap_tg_reg[] __read_mostly = { - { - .name = "NETMAP", - .family = NFPROTO_IPV6, - .revision = 0, - .target = netmap_tg6, - .targetsize = sizeof(struct nf_nat_range), - .table = "nat", - .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_POST_ROUTING) | - (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_LOCAL_IN), - .checkentry = netmap_tg6_checkentry, - .me = THIS_MODULE, - }, - { - .name = "NETMAP", - .family = NFPROTO_IPV4, - .revision = 0, - .target = netmap_tg4, - .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), - .table = "nat", - .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_POST_ROUTING) | - (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_LOCAL_IN), - .checkentry = netmap_tg4_check, - .me = THIS_MODULE, - }, -}; - -static int __init netmap_tg_init(void) -{ - return xt_register_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg)); -} - -static void netmap_tg_exit(void) -{ - xt_unregister_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg)); -} - -module_init(netmap_tg_init); -module_exit(netmap_tg_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of subnets"); -MODULE_AUTHOR("Patrick McHardy "); -MODULE_ALIAS("ip6t_NETMAP"); -MODULE_ALIAS("ipt_NETMAP"); diff --git a/trunk/net/netfilter/xt_REDIRECT.c b/trunk/net/netfilter/xt_REDIRECT.c deleted file mode 100644 index 22a10309297c..000000000000 --- a/trunk/net/netfilter/xt_REDIRECT.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2006 Netfilter Core Team - * Copyright (c) 2011 Patrick McHardy - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 - * NAT funded by Astaro. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; - -static unsigned int -redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) -{ - const struct nf_nat_range *range = par->targinfo; - struct nf_nat_range newrange; - struct in6_addr newdst; - enum ip_conntrack_info ctinfo; - struct nf_conn *ct; - - ct = nf_ct_get(skb, &ctinfo); - if (par->hooknum == NF_INET_LOCAL_OUT) - newdst = loopback_addr; - else { - struct inet6_dev *idev; - struct inet6_ifaddr *ifa; - bool addr = false; - - rcu_read_lock(); - idev = __in6_dev_get(skb->dev); - if (idev != NULL) { - list_for_each_entry(ifa, &idev->addr_list, if_list) { - newdst = ifa->addr; - addr = true; - break; - } - } - rcu_read_unlock(); - - if (!addr) - return NF_DROP; - } - - newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; - newrange.min_addr.in6 = newdst; - newrange.max_addr.in6 = newdst; - newrange.min_proto = range->min_proto; - newrange.max_proto = range->max_proto; - - return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); -} - -static int redirect_tg6_checkentry(const struct xt_tgchk_param *par) -{ - const struct nf_nat_range *range = par->targinfo; - - if (range->flags & NF_NAT_RANGE_MAP_IPS) - return -EINVAL; - return 0; -} - -/* FIXME: Take multiple ranges --RR */ -static int redirect_tg4_check(const struct xt_tgchk_param *par) -{ - const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; - - if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) { - pr_debug("bad MAP_IPS.\n"); - return -EINVAL; - } - if (mr->rangesize != 1) { - pr_debug("bad rangesize %u.\n", mr->rangesize); - return -EINVAL; - } - return 0; -} - -static unsigned int -redirect_tg4(struct sk_buff *skb, const struct xt_action_param *par) -{ - struct nf_conn *ct; - enum ip_conntrack_info ctinfo; - __be32 newdst; - const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; - struct nf_nat_range newrange; - - NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || - par->hooknum == NF_INET_LOCAL_OUT); - - ct = nf_ct_get(skb, &ctinfo); - NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); - - /* Local packets: make them go to loopback */ - if (par->hooknum == NF_INET_LOCAL_OUT) - newdst = htonl(0x7F000001); - else { - struct in_device *indev; - struct in_ifaddr *ifa; - - newdst = 0; - - rcu_read_lock(); - indev = __in_dev_get_rcu(skb->dev); - if (indev && (ifa = indev->ifa_list)) - newdst = ifa->ifa_local; - rcu_read_unlock(); - - if (!newdst) - return NF_DROP; - } - - /* Transfer from original range. */ - memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); - memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); - newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; - newrange.min_addr.ip = newdst; - newrange.max_addr.ip = newdst; - newrange.min_proto = mr->range[0].min; - newrange.max_proto = mr->range[0].max; - - /* Hand modified range to generic setup. */ - return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); -} - -static struct xt_target redirect_tg_reg[] __read_mostly = { - { - .name = "REDIRECT", - .family = NFPROTO_IPV6, - .revision = 0, - .table = "nat", - .checkentry = redirect_tg6_checkentry, - .target = redirect_tg6, - .targetsize = sizeof(struct nf_nat_range), - .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_LOCAL_OUT), - .me = THIS_MODULE, - }, - { - .name = "REDIRECT", - .family = NFPROTO_IPV4, - .revision = 0, - .table = "nat", - .target = redirect_tg4, - .checkentry = redirect_tg4_check, - .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), - .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_LOCAL_OUT), - .me = THIS_MODULE, - }, -}; - -static int __init redirect_tg_init(void) -{ - return xt_register_targets(redirect_tg_reg, - ARRAY_SIZE(redirect_tg_reg)); -} - -static void __exit redirect_tg_exit(void) -{ - xt_unregister_targets(redirect_tg_reg, ARRAY_SIZE(redirect_tg_reg)); -} - -module_init(redirect_tg_init); -module_exit(redirect_tg_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Patrick McHardy "); -MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); -MODULE_ALIAS("ip6t_REDIRECT"); -MODULE_ALIAS("ipt_REDIRECT"); diff --git a/trunk/net/netfilter/xt_limit.c b/trunk/net/netfilter/xt_limit.c index a4c1e4528cac..5c22ce8ab309 100644 --- a/trunk/net/netfilter/xt_limit.c +++ b/trunk/net/netfilter/xt_limit.c @@ -117,11 +117,11 @@ static int limit_mt_check(const struct xt_mtchk_param *par) /* For SMP, we only want to use one set of state. */ r->master = priv; - /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * - 128. */ - priv->prev = jiffies; - priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ if (r->cost == 0) { + /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * + 128. */ + priv->prev = jiffies; + priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ r->credit_cap = priv->credit; /* Credits full. */ r->cost = user2credits(r->avg); } diff --git a/trunk/net/netfilter/xt_set.c b/trunk/net/netfilter/xt_set.c index 865a9e54f3ad..c6f7db720d84 100644 --- a/trunk/net/netfilter/xt_set.c +++ b/trunk/net/netfilter/xt_set.c @@ -356,27 +356,6 @@ static struct xt_match set_matches[] __read_mostly = { .destroy = set_match_v1_destroy, .me = THIS_MODULE }, - /* --return-nomatch flag support */ - { - .name = "set", - .family = NFPROTO_IPV4, - .revision = 2, - .match = set_match_v1, - .matchsize = sizeof(struct xt_set_info_match_v1), - .checkentry = set_match_v1_checkentry, - .destroy = set_match_v1_destroy, - .me = THIS_MODULE - }, - { - .name = "set", - .family = NFPROTO_IPV6, - .revision = 2, - .match = set_match_v1, - .matchsize = sizeof(struct xt_set_info_match_v1), - .checkentry = set_match_v1_checkentry, - .destroy = set_match_v1_destroy, - .me = THIS_MODULE - }, }; static struct xt_target set_targets[] __read_mostly = { @@ -410,7 +389,6 @@ static struct xt_target set_targets[] __read_mostly = { .destroy = set_target_v1_destroy, .me = THIS_MODULE }, - /* --timeout and --exist flags support */ { .name = "SET", .revision = 2, diff --git a/trunk/net/netfilter/xt_time.c b/trunk/net/netfilter/xt_time.c index 0ae55a36f492..c48975ff8ea2 100644 --- a/trunk/net/netfilter/xt_time.c +++ b/trunk/net/netfilter/xt_time.c @@ -42,7 +42,6 @@ static const u_int16_t days_since_leapyear[] = { */ enum { DSE_FIRST = 2039, - SECONDS_PER_DAY = 86400, }; static const u_int16_t days_since_epoch[] = { /* 2039 - 2030 */ @@ -79,7 +78,7 @@ static inline unsigned int localtime_1(struct xtm *r, time_t time) unsigned int v, w; /* Each day has 86400s, so finding the hour/minute is actually easy. */ - v = time % SECONDS_PER_DAY; + v = time % 86400; r->second = v % 60; w = v / 60; r->minute = w % 60; @@ -200,18 +199,6 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par) if (packet_time < info->daytime_start && packet_time > info->daytime_stop) return false; - - /** if user asked to ignore 'next day', then e.g. - * '1 PM Wed, August 1st' should be treated - * like 'Tue 1 PM July 31st'. - * - * This also causes - * 'Monday, "23:00 to 01:00", to match for 2 hours, starting - * Monday 23:00 to Tuesday 01:00. - */ - if ((info->flags & XT_TIME_CONTIGUOUS) && - packet_time <= info->daytime_stop) - stamp -= SECONDS_PER_DAY; } localtime_2(¤t_time, stamp); @@ -240,15 +227,6 @@ static int time_mt_check(const struct xt_mtchk_param *par) return -EDOM; } - if (info->flags & ~XT_TIME_ALL_FLAGS) { - pr_info("unknown flags 0x%x\n", info->flags & ~XT_TIME_ALL_FLAGS); - return -EINVAL; - } - - if ((info->flags & XT_TIME_CONTIGUOUS) && - info->daytime_start < info->daytime_stop) - return -EINVAL; - return 0; } diff --git a/trunk/net/netrom/af_netrom.c b/trunk/net/netrom/af_netrom.c index 7261eb81974f..1b9024ee963c 100644 --- a/trunk/net/netrom/af_netrom.c +++ b/trunk/net/netrom/af_netrom.c @@ -601,7 +601,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (!capable(CAP_NET_BIND_SERVICE)) { dev_put(dev); release_sock(sk); - return -EPERM; + return -EACCES; } nr->user_addr = addr->fsa_digipeater[0]; nr->source_addr = addr->fsa_ax25.sax25_call; diff --git a/trunk/net/nfc/core.c b/trunk/net/nfc/core.c index c9eacc1f145f..ff749794bc5b 100644 --- a/trunk/net/nfc/core.c +++ b/trunk/net/nfc/core.c @@ -679,7 +679,7 @@ static void nfc_release(struct device *d) if (dev->ops->check_presence) { del_timer_sync(&dev->check_pres_timer); - cancel_work_sync(&dev->check_pres_work); + destroy_workqueue(dev->check_pres_wq); } nfc_genl_data_exit(&dev->genl_data); @@ -715,7 +715,7 @@ static void nfc_check_pres_timeout(unsigned long data) { struct nfc_dev *dev = (struct nfc_dev *)data; - queue_work(system_nrt_wq, &dev->check_pres_work); + queue_work(dev->check_pres_wq, &dev->check_pres_work); } struct class nfc_class = { @@ -784,11 +784,20 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, dev->targets_generation = 1; if (ops->check_presence) { + char name[32]; init_timer(&dev->check_pres_timer); dev->check_pres_timer.data = (unsigned long)dev; dev->check_pres_timer.function = nfc_check_pres_timeout; INIT_WORK(&dev->check_pres_work, nfc_check_pres_work); + snprintf(name, sizeof(name), "nfc%d_check_pres_wq", dev->idx); + dev->check_pres_wq = alloc_workqueue(name, WQ_NON_REENTRANT | + WQ_UNBOUND | + WQ_MEM_RECLAIM, 1); + if (dev->check_pres_wq == NULL) { + kfree(dev); + return NULL; + } } return dev; diff --git a/trunk/net/nfc/hci/Makefile b/trunk/net/nfc/hci/Makefile index c5dbb6891b24..f9c44b2fb065 100644 --- a/trunk/net/nfc/hci/Makefile +++ b/trunk/net/nfc/hci/Makefile @@ -4,5 +4,5 @@ obj-$(CONFIG_NFC_HCI) += hci.o -hci-y := core.o hcp.o command.o llc.o llc_nop.o -hci-$(CONFIG_NFC_SHDLC) += llc_shdlc.o +hci-y := core.o hcp.o command.o +hci-$(CONFIG_NFC_SHDLC) += shdlc.o diff --git a/trunk/net/nfc/hci/command.c b/trunk/net/nfc/hci/command.c index 71c6a7086b8f..46362ef979db 100644 --- a/trunk/net/nfc/hci/command.c +++ b/trunk/net/nfc/hci/command.c @@ -28,29 +28,10 @@ #include "hci.h" -static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, - const u8 *param, size_t param_len, - data_exchange_cb_t cb, void *cb_context) +static void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, int err, + struct sk_buff *skb, void *cb_data) { - pr_debug("exec cmd async through pipe=%d, cmd=%d, plen=%zd\n", pipe, - cmd, param_len); - - /* TODO: Define hci cmd execution delay. Should it be the same - * for all commands? - */ - return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_COMMAND, cmd, - param, param_len, cb, cb_context, 3000); -} - -/* - * HCI command execution completion callback. - * err will be a standard linux error (may be converted from HCI response) - * skb contains the response data and must be disposed, or may be NULL if - * an error occured - */ -static void nfc_hci_execute_cb(void *context, struct sk_buff *skb, int err) -{ - struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)context; + struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)cb_data; pr_debug("HCI Cmd completed with result=%d\n", err); @@ -74,8 +55,7 @@ static int nfc_hci_execute_cmd(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, hcp_ew.exec_complete = false; hcp_ew.result_skb = NULL; - pr_debug("exec cmd sync through pipe=%d, cmd=%d, plen=%zd\n", pipe, - cmd, param_len); + pr_debug("through pipe=%d, cmd=%d, plen=%zd\n", pipe, cmd, param_len); /* TODO: Define hci cmd execution delay. Should it be the same * for all commands? @@ -153,23 +133,6 @@ int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, } EXPORT_SYMBOL(nfc_hci_send_cmd); -int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, - const u8 *param, size_t param_len, - data_exchange_cb_t cb, void *cb_context) -{ - u8 pipe; - - pr_debug("\n"); - - pipe = hdev->gate2pipe[gate]; - if (pipe == NFC_HCI_INVALID_PIPE) - return -EADDRNOTAVAIL; - - return nfc_hci_execute_cmd_async(hdev, pipe, cmd, param, param_len, - cb, cb_context); -} -EXPORT_SYMBOL(nfc_hci_send_cmd_async); - int nfc_hci_set_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, const u8 *param, size_t param_len) { diff --git a/trunk/net/nfc/hci/core.c b/trunk/net/nfc/hci/core.c index d378d93de62e..1ac7b3fac6c9 100644 --- a/trunk/net/nfc/hci/core.c +++ b/trunk/net/nfc/hci/core.c @@ -26,7 +26,6 @@ #include #include -#include #include "hci.h" @@ -58,11 +57,12 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) if (hdev->cmd_pending_msg) { if (timer_pending(&hdev->cmd_timer) == 0) { if (hdev->cmd_pending_msg->cb) - hdev->cmd_pending_msg->cb(hdev-> - cmd_pending_msg-> - cb_context, + hdev->cmd_pending_msg->cb(hdev, + -ETIME, NULL, - -ETIME); + hdev-> + cmd_pending_msg-> + cb_context); kfree(hdev->cmd_pending_msg); hdev->cmd_pending_msg = NULL; } else @@ -78,12 +78,12 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) pr_debug("msg_tx_queue has a cmd to send\n"); while ((skb = skb_dequeue(&msg->msg_frags)) != NULL) { - r = nfc_llc_xmit_from_hci(hdev->llc, skb); + r = hdev->ops->xmit(hdev, skb); if (r < 0) { kfree_skb(skb); skb_queue_purge(&msg->msg_frags); if (msg->cb) - msg->cb(msg->cb_context, NULL, r); + msg->cb(hdev, r, NULL, msg->cb_context); kfree(msg); break; } @@ -133,15 +133,15 @@ static void __nfc_hci_cmd_completion(struct nfc_hci_dev *hdev, int err, del_timer_sync(&hdev->cmd_timer); if (hdev->cmd_pending_msg->cb) - hdev->cmd_pending_msg->cb(hdev->cmd_pending_msg->cb_context, - skb, err); + hdev->cmd_pending_msg->cb(hdev, err, skb, + hdev->cmd_pending_msg->cb_context); else kfree_skb(skb); kfree(hdev->cmd_pending_msg); hdev->cmd_pending_msg = NULL; - queue_work(system_nrt_wq, &hdev->msg_tx_work); + queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); } void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, @@ -326,7 +326,7 @@ static void nfc_hci_cmd_timeout(unsigned long data) { struct nfc_hci_dev *hdev = (struct nfc_hci_dev *)data; - queue_work(system_nrt_wq, &hdev->msg_tx_work); + queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); } static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count, @@ -398,7 +398,8 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev) nfc_hci_disconnect_all_gates(hdev); exit: - kfree_skb(skb); + if (skb) + kfree_skb(skb); return r; } @@ -469,38 +470,29 @@ static int hci_dev_up(struct nfc_dev *nfc_dev) return r; } - r = nfc_llc_start(hdev->llc); - if (r < 0) - goto exit_close; - r = hci_dev_session_init(hdev); if (r < 0) - goto exit_llc; + goto exit; r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, NFC_HCI_EVT_END_OPERATION, NULL, 0); if (r < 0) - goto exit_llc; + goto exit; if (hdev->ops->hci_ready) { r = hdev->ops->hci_ready(hdev); if (r < 0) - goto exit_llc; + goto exit; } r = hci_dev_version(hdev); if (r < 0) - goto exit_llc; - - return 0; - -exit_llc: - nfc_llc_stop(hdev->llc); - -exit_close: - if (hdev->ops->close) - hdev->ops->close(hdev); + goto exit; +exit: + if (r < 0) + if (hdev->ops->close) + hdev->ops->close(hdev); return r; } @@ -508,8 +500,6 @@ static int hci_dev_down(struct nfc_dev *nfc_dev) { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); - nfc_llc_stop(hdev->llc); - if (hdev->ops->close) hdev->ops->close(hdev); @@ -549,37 +539,13 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev, { } -#define HCI_CB_TYPE_TRANSCEIVE 1 - -static void hci_transceive_cb(void *context, struct sk_buff *skb, int err) -{ - struct nfc_hci_dev *hdev = context; - - switch (hdev->async_cb_type) { - case HCI_CB_TYPE_TRANSCEIVE: - /* - * TODO: Check RF Error indicator to make sure data is valid. - * It seems that HCI cmd can complete without error, but data - * can be invalid if an RF error occured? Ignore for now. - */ - if (err == 0) - skb_trim(skb, skb->len - 1); /* RF Err ind */ - - hdev->async_cb(hdev->async_cb_context, skb, err); - break; - default: - if (err == 0) - kfree_skb(skb); - break; - } -} - static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, struct sk_buff *skb, data_exchange_cb_t cb, void *cb_context) { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); int r; + struct sk_buff *res_skb = NULL; pr_debug("target_idx=%d\n", target->idx); @@ -587,37 +553,40 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, case NFC_HCI_RF_READER_A_GATE: case NFC_HCI_RF_READER_B_GATE: if (hdev->ops->data_exchange) { - r = hdev->ops->data_exchange(hdev, target, skb, cb, - cb_context); + r = hdev->ops->data_exchange(hdev, target, skb, + &res_skb); if (r <= 0) /* handled */ break; } *skb_push(skb, 1) = 0; /* CTR, see spec:10.2.2.1 */ - - hdev->async_cb_type = HCI_CB_TYPE_TRANSCEIVE; - hdev->async_cb = cb; - hdev->async_cb_context = cb_context; - - r = nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, - NFC_HCI_WR_XCHG_DATA, skb->data, - skb->len, hci_transceive_cb, hdev); + r = nfc_hci_send_cmd(hdev, target->hci_reader_gate, + NFC_HCI_WR_XCHG_DATA, + skb->data, skb->len, &res_skb); + /* + * TODO: Check RF Error indicator to make sure data is valid. + * It seems that HCI cmd can complete without error, but data + * can be invalid if an RF error occured? Ignore for now. + */ + if (r == 0) + skb_trim(res_skb, res_skb->len - 1); /* RF Err ind */ break; default: if (hdev->ops->data_exchange) { - r = hdev->ops->data_exchange(hdev, target, skb, cb, - cb_context); + r = hdev->ops->data_exchange(hdev, target, skb, + &res_skb); if (r == 1) r = -ENOTSUPP; } else r = -ENOTSUPP; - break; } kfree_skb(skb); - return r; + cb(cb_context, res_skb, r); + + return 0; } static int hci_check_presence(struct nfc_dev *nfc_dev, @@ -631,93 +600,6 @@ static int hci_check_presence(struct nfc_dev *nfc_dev, return 0; } -static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err) -{ - mutex_lock(&hdev->msg_tx_mutex); - - if (hdev->cmd_pending_msg == NULL) { - nfc_driver_failure(hdev->ndev, err); - goto exit; - } - - __nfc_hci_cmd_completion(hdev, err, NULL); - -exit: - mutex_unlock(&hdev->msg_tx_mutex); -} - -static void nfc_hci_llc_failure(struct nfc_hci_dev *hdev, int err) -{ - nfc_hci_failure(hdev, err); -} - -static void nfc_hci_recv_from_llc(struct nfc_hci_dev *hdev, struct sk_buff *skb) -{ - struct hcp_packet *packet; - u8 type; - u8 instruction; - struct sk_buff *hcp_skb; - u8 pipe; - struct sk_buff *frag_skb; - int msg_len; - - packet = (struct hcp_packet *)skb->data; - if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) { - skb_queue_tail(&hdev->rx_hcp_frags, skb); - return; - } - - /* it's the last fragment. Does it need re-aggregation? */ - if (skb_queue_len(&hdev->rx_hcp_frags)) { - pipe = packet->header & NFC_HCI_FRAGMENT; - skb_queue_tail(&hdev->rx_hcp_frags, skb); - - msg_len = 0; - skb_queue_walk(&hdev->rx_hcp_frags, frag_skb) { - msg_len += (frag_skb->len - - NFC_HCI_HCP_PACKET_HEADER_LEN); - } - - hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN + - msg_len, GFP_KERNEL); - if (hcp_skb == NULL) { - nfc_hci_failure(hdev, -ENOMEM); - return; - } - - *skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe; - - skb_queue_walk(&hdev->rx_hcp_frags, frag_skb) { - msg_len = frag_skb->len - NFC_HCI_HCP_PACKET_HEADER_LEN; - memcpy(skb_put(hcp_skb, msg_len), - frag_skb->data + NFC_HCI_HCP_PACKET_HEADER_LEN, - msg_len); - } - - skb_queue_purge(&hdev->rx_hcp_frags); - } else { - packet->header &= NFC_HCI_FRAGMENT; - hcp_skb = skb; - } - - /* if this is a response, dispatch immediately to - * unblock waiting cmd context. Otherwise, enqueue to dispatch - * in separate context where handler can also execute command. - */ - packet = (struct hcp_packet *)hcp_skb->data; - type = HCP_MSG_GET_TYPE(packet->message.header); - if (type == NFC_HCI_HCP_RESPONSE) { - pipe = packet->header; - instruction = HCP_MSG_GET_CMD(packet->message.header); - skb_pull(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN + - NFC_HCI_HCP_MESSAGE_HEADER_LEN); - nfc_hci_hcp_message_rx(hdev, pipe, type, instruction, hcp_skb); - } else { - skb_queue_tail(&hdev->msg_rx_queue, hcp_skb); - queue_work(system_nrt_wq, &hdev->msg_rx_work); - } -} - static struct nfc_ops hci_nfc_ops = { .dev_up = hci_dev_up, .dev_down = hci_dev_down, @@ -732,7 +614,6 @@ static struct nfc_ops hci_nfc_ops = { struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, struct nfc_hci_init_data *init_data, u32 protocols, - const char *llc_name, int tx_headroom, int tx_tailroom, int max_link_payload) @@ -749,19 +630,10 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, if (hdev == NULL) return NULL; - hdev->llc = nfc_llc_allocate(llc_name, hdev, ops->xmit, - nfc_hci_recv_from_llc, tx_headroom, - tx_tailroom, nfc_hci_llc_failure); - if (hdev->llc == NULL) { - kfree(hdev); - return NULL; - } - hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, tx_headroom + HCI_CMDS_HEADROOM, tx_tailroom); if (!hdev->ndev) { - nfc_llc_free(hdev->llc); kfree(hdev); return NULL; } @@ -781,18 +653,29 @@ EXPORT_SYMBOL(nfc_hci_allocate_device); void nfc_hci_free_device(struct nfc_hci_dev *hdev) { nfc_free_device(hdev->ndev); - nfc_llc_free(hdev->llc); kfree(hdev); } EXPORT_SYMBOL(nfc_hci_free_device); int nfc_hci_register_device(struct nfc_hci_dev *hdev) { + struct device *dev = &hdev->ndev->dev; + const char *devname = dev_name(dev); + char name[32]; + int r = 0; + mutex_init(&hdev->msg_tx_mutex); INIT_LIST_HEAD(&hdev->msg_tx_queue); INIT_WORK(&hdev->msg_tx_work, nfc_hci_msg_tx_work); + snprintf(name, sizeof(name), "%s_hci_msg_tx_wq", devname); + hdev->msg_tx_wq = alloc_workqueue(name, WQ_NON_REENTRANT | WQ_UNBOUND | + WQ_MEM_RECLAIM, 1); + if (hdev->msg_tx_wq == NULL) { + r = -ENOMEM; + goto exit; + } init_timer(&hdev->cmd_timer); hdev->cmd_timer.data = (unsigned long)hdev; @@ -801,10 +684,27 @@ int nfc_hci_register_device(struct nfc_hci_dev *hdev) skb_queue_head_init(&hdev->rx_hcp_frags); INIT_WORK(&hdev->msg_rx_work, nfc_hci_msg_rx_work); + snprintf(name, sizeof(name), "%s_hci_msg_rx_wq", devname); + hdev->msg_rx_wq = alloc_workqueue(name, WQ_NON_REENTRANT | WQ_UNBOUND | + WQ_MEM_RECLAIM, 1); + if (hdev->msg_rx_wq == NULL) { + r = -ENOMEM; + goto exit; + } skb_queue_head_init(&hdev->msg_rx_queue); - return nfc_register_device(hdev->ndev); + r = nfc_register_device(hdev->ndev); + +exit: + if (r < 0) { + if (hdev->msg_tx_wq) + destroy_workqueue(hdev->msg_tx_wq); + if (hdev->msg_rx_wq) + destroy_workqueue(hdev->msg_rx_wq); + } + + return r; } EXPORT_SYMBOL(nfc_hci_register_device); @@ -825,8 +725,9 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) nfc_unregister_device(hdev->ndev); - cancel_work_sync(&hdev->msg_tx_work); - cancel_work_sync(&hdev->msg_rx_work); + destroy_workqueue(hdev->msg_tx_wq); + + destroy_workqueue(hdev->msg_rx_wq); } EXPORT_SYMBOL(nfc_hci_unregister_device); @@ -842,30 +743,93 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev) } EXPORT_SYMBOL(nfc_hci_get_clientdata); +static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err) +{ + mutex_lock(&hdev->msg_tx_mutex); + + if (hdev->cmd_pending_msg == NULL) { + nfc_driver_failure(hdev->ndev, err); + goto exit; + } + + __nfc_hci_cmd_completion(hdev, err, NULL); + +exit: + mutex_unlock(&hdev->msg_tx_mutex); +} + void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err) { nfc_hci_failure(hdev, err); } EXPORT_SYMBOL(nfc_hci_driver_failure); -void inline nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) +void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) { - nfc_llc_rcv_from_drv(hdev->llc, skb); -} -EXPORT_SYMBOL(nfc_hci_recv_frame); + struct hcp_packet *packet; + u8 type; + u8 instruction; + struct sk_buff *hcp_skb; + u8 pipe; + struct sk_buff *frag_skb; + int msg_len; -static int __init nfc_hci_init(void) -{ - return nfc_llc_init(); -} + packet = (struct hcp_packet *)skb->data; + if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) { + skb_queue_tail(&hdev->rx_hcp_frags, skb); + return; + } -static void __exit nfc_hci_exit(void) -{ - nfc_llc_exit(); -} + /* it's the last fragment. Does it need re-aggregation? */ + if (skb_queue_len(&hdev->rx_hcp_frags)) { + pipe = packet->header & NFC_HCI_FRAGMENT; + skb_queue_tail(&hdev->rx_hcp_frags, skb); -subsys_initcall(nfc_hci_init); -module_exit(nfc_hci_exit); + msg_len = 0; + skb_queue_walk(&hdev->rx_hcp_frags, frag_skb) { + msg_len += (frag_skb->len - + NFC_HCI_HCP_PACKET_HEADER_LEN); + } + + hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN + + msg_len, GFP_KERNEL); + if (hcp_skb == NULL) { + nfc_hci_failure(hdev, -ENOMEM); + return; + } + + *skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe; + + skb_queue_walk(&hdev->rx_hcp_frags, frag_skb) { + msg_len = frag_skb->len - NFC_HCI_HCP_PACKET_HEADER_LEN; + memcpy(skb_put(hcp_skb, msg_len), + frag_skb->data + NFC_HCI_HCP_PACKET_HEADER_LEN, + msg_len); + } + + skb_queue_purge(&hdev->rx_hcp_frags); + } else { + packet->header &= NFC_HCI_FRAGMENT; + hcp_skb = skb; + } + + /* if this is a response, dispatch immediately to + * unblock waiting cmd context. Otherwise, enqueue to dispatch + * in separate context where handler can also execute command. + */ + packet = (struct hcp_packet *)hcp_skb->data; + type = HCP_MSG_GET_TYPE(packet->message.header); + if (type == NFC_HCI_HCP_RESPONSE) { + pipe = packet->header; + instruction = HCP_MSG_GET_CMD(packet->message.header); + skb_pull(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN + + NFC_HCI_HCP_MESSAGE_HEADER_LEN); + nfc_hci_hcp_message_rx(hdev, pipe, type, instruction, hcp_skb); + } else { + skb_queue_tail(&hdev->msg_rx_queue, hcp_skb); + queue_work(hdev->msg_rx_wq, &hdev->msg_rx_work); + } +} +EXPORT_SYMBOL(nfc_hci_recv_frame); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("NFC HCI Core"); diff --git a/trunk/net/nfc/hci/hci.h b/trunk/net/nfc/hci/hci.h index b274d12c18ac..fa9a21e92239 100644 --- a/trunk/net/nfc/hci/hci.h +++ b/trunk/net/nfc/hci/hci.h @@ -20,8 +20,6 @@ #ifndef __LOCAL_HCI_H #define __LOCAL_HCI_H -#include - struct gate_pipe_map { u8 gate; u8 pipe; @@ -37,6 +35,15 @@ struct hcp_packet { struct hcp_message message; } __packed; +/* + * HCI command execution completion callback. + * result will be a standard linux error (may be converted from HCI response) + * skb contains the response data and must be disposed, or may be NULL if + * an error occured + */ +typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, int result, + struct sk_buff *skb, void *cb_data); + struct hcp_exec_waiter { wait_queue_head_t *wq; bool exec_complete; @@ -48,7 +55,7 @@ struct hci_msg { struct list_head msg_l; struct sk_buff_head msg_frags; bool wait_response; - data_exchange_cb_t cb; + hci_cmd_cb_t cb; void *cb_context; unsigned long completion_delay; }; @@ -76,7 +83,7 @@ struct hci_create_pipe_resp { int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, u8 type, u8 instruction, const u8 *payload, size_t payload_len, - data_exchange_cb_t cb, void *cb_context, + hci_cmd_cb_t cb, void *cb_data, unsigned long completion_delay); u8 nfc_hci_pipe2gate(struct nfc_hci_dev *hdev, u8 pipe); diff --git a/trunk/net/nfc/hci/hcp.c b/trunk/net/nfc/hci/hcp.c index 208eedd07ee3..f4dad1a89740 100644 --- a/trunk/net/nfc/hci/hcp.c +++ b/trunk/net/nfc/hci/hcp.c @@ -35,7 +35,7 @@ int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, u8 type, u8 instruction, const u8 *payload, size_t payload_len, - data_exchange_cb_t cb, void *cb_context, + hci_cmd_cb_t cb, void *cb_data, unsigned long completion_delay) { struct nfc_dev *ndev = hdev->ndev; @@ -52,7 +52,7 @@ int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, skb_queue_head_init(&cmd->msg_frags); cmd->wait_response = (type == NFC_HCI_HCP_COMMAND) ? true : false; cmd->cb = cb; - cmd->cb_context = cb_context; + cmd->cb_context = cb_data; cmd->completion_delay = completion_delay; hci_len = payload_len + 1; @@ -108,7 +108,7 @@ int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, list_add_tail(&cmd->msg_l, &hdev->msg_tx_queue); mutex_unlock(&hdev->msg_tx_mutex); - queue_work(system_nrt_wq, &hdev->msg_tx_work); + queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); return 0; diff --git a/trunk/net/nfc/hci/llc.c b/trunk/net/nfc/hci/llc.c deleted file mode 100644 index ae1205ded87f..000000000000 --- a/trunk/net/nfc/hci/llc.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Link Layer Control manager - * - * Copyright (C) 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include - -#include "llc.h" - -static struct list_head llc_engines; - -int nfc_llc_init(void) -{ - int r; - - INIT_LIST_HEAD(&llc_engines); - - r = nfc_llc_nop_register(); - if (r) - goto exit; - - r = nfc_llc_shdlc_register(); - if (r) - goto exit; - - return 0; - -exit: - nfc_llc_exit(); - return r; -} - -void nfc_llc_exit(void) -{ - struct nfc_llc_engine *llc_engine, *n; - - list_for_each_entry_safe(llc_engine, n, &llc_engines, entry) { - list_del(&llc_engine->entry); - kfree(llc_engine->name); - kfree(llc_engine); - } -} - -int nfc_llc_register(const char *name, struct nfc_llc_ops *ops) -{ - struct nfc_llc_engine *llc_engine; - - llc_engine = kzalloc(sizeof(struct nfc_llc_engine), GFP_KERNEL); - if (llc_engine == NULL) - return -ENOMEM; - - llc_engine->name = kstrdup(name, GFP_KERNEL); - if (llc_engine->name == NULL) { - kfree(llc_engine); - return -ENOMEM; - } - llc_engine->ops = ops; - - INIT_LIST_HEAD(&llc_engine->entry); - list_add_tail (&llc_engine->entry, &llc_engines); - - return 0; -} - -static struct nfc_llc_engine *nfc_llc_name_to_engine(const char *name) -{ - struct nfc_llc_engine *llc_engine; - - list_for_each_entry(llc_engine, &llc_engines, entry) { - if (strcmp(llc_engine->name, name) == 0) - return llc_engine; - } - - return NULL; -} - -void nfc_llc_unregister(const char *name) -{ - struct nfc_llc_engine *llc_engine; - - llc_engine = nfc_llc_name_to_engine(name); - if (llc_engine == NULL) - return; - - list_del(&llc_engine->entry); - kfree(llc_engine->name); - kfree(llc_engine); -} - -struct nfc_llc *nfc_llc_allocate(const char *name, struct nfc_hci_dev *hdev, - xmit_to_drv_t xmit_to_drv, - rcv_to_hci_t rcv_to_hci, int tx_headroom, - int tx_tailroom, llc_failure_t llc_failure) -{ - struct nfc_llc_engine *llc_engine; - struct nfc_llc *llc; - - llc_engine = nfc_llc_name_to_engine(name); - if (llc_engine == NULL) - return NULL; - - llc = kzalloc(sizeof(struct nfc_llc), GFP_KERNEL); - if (llc == NULL) - return NULL; - - llc->data = llc_engine->ops->init(hdev, xmit_to_drv, rcv_to_hci, - tx_headroom, tx_tailroom, - &llc->rx_headroom, &llc->rx_tailroom, - llc_failure); - if (llc->data == NULL) { - kfree(llc); - return NULL; - } - llc->ops = llc_engine->ops; - - return llc; -} - -void nfc_llc_free(struct nfc_llc *llc) -{ - llc->ops->deinit(llc); - kfree(llc); -} - -inline void nfc_llc_get_rx_head_tail_room(struct nfc_llc *llc, int *rx_headroom, - int *rx_tailroom) -{ - *rx_headroom = llc->rx_headroom; - *rx_tailroom = llc->rx_tailroom; -} - -inline int nfc_llc_start(struct nfc_llc *llc) -{ - return llc->ops->start(llc); -} - -inline int nfc_llc_stop(struct nfc_llc *llc) -{ - return llc->ops->stop(llc); -} - -inline void nfc_llc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb) -{ - llc->ops->rcv_from_drv(llc, skb); -} - -inline int nfc_llc_xmit_from_hci(struct nfc_llc *llc, struct sk_buff *skb) -{ - return llc->ops->xmit_from_hci(llc, skb); -} - -inline void *nfc_llc_get_data(struct nfc_llc *llc) -{ - return llc->data; -} diff --git a/trunk/net/nfc/hci/llc.h b/trunk/net/nfc/hci/llc.h deleted file mode 100644 index 7be0b7f3ceb6..000000000000 --- a/trunk/net/nfc/hci/llc.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Link Layer Control manager - * - * Copyright (C) 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __LOCAL_LLC_H_ -#define __LOCAL_LLC_H_ - -#include -#include -#include - -struct nfc_llc_ops { - void *(*init) (struct nfc_hci_dev *hdev, xmit_to_drv_t xmit_to_drv, - rcv_to_hci_t rcv_to_hci, int tx_headroom, - int tx_tailroom, int *rx_headroom, int *rx_tailroom, - llc_failure_t llc_failure); - void (*deinit) (struct nfc_llc *llc); - int (*start) (struct nfc_llc *llc); - int (*stop) (struct nfc_llc *llc); - void (*rcv_from_drv) (struct nfc_llc *llc, struct sk_buff *skb); - int (*xmit_from_hci) (struct nfc_llc *llc, struct sk_buff *skb); -}; - -struct nfc_llc_engine { - const char *name; - struct nfc_llc_ops *ops; - struct list_head entry; -}; - -struct nfc_llc { - void *data; - struct nfc_llc_ops *ops; - int rx_headroom; - int rx_tailroom; -}; - -void *nfc_llc_get_data(struct nfc_llc *llc); - -int nfc_llc_register(const char *name, struct nfc_llc_ops *ops); -void nfc_llc_unregister(const char *name); - -int nfc_llc_nop_register(void); - -#if defined(CONFIG_NFC_SHDLC) -int nfc_llc_shdlc_register(void); -#else -static inline int nfc_llc_shdlc_register(void) -{ - return 0; -} -#endif - -#endif /* __LOCAL_LLC_H_ */ diff --git a/trunk/net/nfc/hci/llc_nop.c b/trunk/net/nfc/hci/llc_nop.c deleted file mode 100644 index 87b10291b40f..000000000000 --- a/trunk/net/nfc/hci/llc_nop.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * nop (passthrough) Link Layer Control - * - * Copyright (C) 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include - -#include "llc.h" - -struct llc_nop { - struct nfc_hci_dev *hdev; - xmit_to_drv_t xmit_to_drv; - rcv_to_hci_t rcv_to_hci; - int tx_headroom; - int tx_tailroom; - llc_failure_t llc_failure; -}; - -static void *llc_nop_init(struct nfc_hci_dev *hdev, xmit_to_drv_t xmit_to_drv, - rcv_to_hci_t rcv_to_hci, int tx_headroom, - int tx_tailroom, int *rx_headroom, int *rx_tailroom, - llc_failure_t llc_failure) -{ - struct llc_nop *llc_nop; - - *rx_headroom = 0; - *rx_tailroom = 0; - - llc_nop = kzalloc(sizeof(struct llc_nop), GFP_KERNEL); - if (llc_nop == NULL) - return NULL; - - llc_nop->hdev = hdev; - llc_nop->xmit_to_drv = xmit_to_drv; - llc_nop->rcv_to_hci = rcv_to_hci; - llc_nop->tx_headroom = tx_headroom; - llc_nop->tx_tailroom = tx_tailroom; - llc_nop->llc_failure = llc_failure; - - return llc_nop; -} - -static void llc_nop_deinit(struct nfc_llc *llc) -{ - kfree(nfc_llc_get_data(llc)); -} - -static int llc_nop_start(struct nfc_llc *llc) -{ - return 0; -} - -static int llc_nop_stop(struct nfc_llc *llc) -{ - return 0; -} - -static void llc_nop_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb) -{ - struct llc_nop *llc_nop = nfc_llc_get_data(llc); - - llc_nop->rcv_to_hci(llc_nop->hdev, skb); -} - -static int llc_nop_xmit_from_hci(struct nfc_llc *llc, struct sk_buff *skb) -{ - struct llc_nop *llc_nop = nfc_llc_get_data(llc); - - return llc_nop->xmit_to_drv(llc_nop->hdev, skb); -} - -static struct nfc_llc_ops llc_nop_ops = { - .init = llc_nop_init, - .deinit = llc_nop_deinit, - .start = llc_nop_start, - .stop = llc_nop_stop, - .rcv_from_drv = llc_nop_rcv_from_drv, - .xmit_from_hci = llc_nop_xmit_from_hci, -}; - -int nfc_llc_nop_register(void) -{ - return nfc_llc_register(LLC_NOP_NAME, &llc_nop_ops); -} diff --git a/trunk/net/nfc/hci/llc_shdlc.c b/trunk/net/nfc/hci/shdlc.c similarity index 54% rename from trunk/net/nfc/hci/llc_shdlc.c rename to trunk/net/nfc/hci/shdlc.c index 8f69d791dcb3..6f840c18c892 100644 --- a/trunk/net/nfc/hci/llc_shdlc.c +++ b/trunk/net/nfc/hci/shdlc.c @@ -1,11 +1,10 @@ /* - * shdlc Link Layer Control - * * Copyright (C) 2012 Intel Corporation. All rights reserved. * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,65 +19,18 @@ #define pr_fmt(fmt) "shdlc: %s: " fmt, __func__ -#include #include +#include #include +#include #include #include -#include "llc.h" - -enum shdlc_state { - SHDLC_DISCONNECTED = 0, - SHDLC_CONNECTING = 1, - SHDLC_NEGOTIATING = 2, - SHDLC_HALF_CONNECTED = 3, - SHDLC_CONNECTED = 4 -}; - -struct llc_shdlc { - struct nfc_hci_dev *hdev; - xmit_to_drv_t xmit_to_drv; - rcv_to_hci_t rcv_to_hci; - - struct mutex state_mutex; - enum shdlc_state state; - int hard_fault; - - wait_queue_head_t *connect_wq; - int connect_tries; - int connect_result; - struct timer_list connect_timer;/* aka T3 in spec 10.6.1 */ - - u8 w; /* window size */ - bool srej_support; - - struct timer_list t1_timer; /* send ack timeout */ - bool t1_active; - - struct timer_list t2_timer; /* guard/retransmit timeout */ - bool t2_active; - - int ns; /* next seq num for send */ - int nr; /* next expected seq num for receive */ - int dnr; /* oldest sent unacked seq num */ - - struct sk_buff_head rcv_q; - - struct sk_buff_head send_q; - bool rnr; /* other side is not ready to receive */ - - struct sk_buff_head ack_pending_q; - - struct work_struct sm_work; - - int tx_headroom; - int tx_tailroom; - - llc_failure_t llc_failure; -}; +#include +#include #define SHDLC_LLC_HEAD_ROOM 2 +#define SHDLC_LLC_TAIL_ROOM 2 #define SHDLC_MAX_WINDOW 4 #define SHDLC_SREJ_SUPPORT false @@ -119,7 +71,7 @@ do { \ } while (0) /* checks x < y <= z modulo 8 */ -static bool llc_shdlc_x_lt_y_lteq_z(int x, int y, int z) +static bool nfc_shdlc_x_lt_y_lteq_z(int x, int y, int z) { if (x < z) return ((x < y) && (y <= z)) ? true : false; @@ -128,7 +80,7 @@ static bool llc_shdlc_x_lt_y_lteq_z(int x, int y, int z) } /* checks x <= y < z modulo 8 */ -static bool llc_shdlc_x_lteq_y_lt_z(int x, int y, int z) +static bool nfc_shdlc_x_lteq_y_lt_z(int x, int y, int z) { if (x <= z) return ((x <= y) && (y < z)) ? true : false; @@ -136,21 +88,36 @@ static bool llc_shdlc_x_lteq_y_lt_z(int x, int y, int z) return ((y >= x) || (y < z)) ? true : false; } -static struct sk_buff *llc_shdlc_alloc_skb(struct llc_shdlc *shdlc, +static struct sk_buff *nfc_shdlc_alloc_skb(struct nfc_shdlc *shdlc, int payload_len) { struct sk_buff *skb; - skb = alloc_skb(shdlc->tx_headroom + SHDLC_LLC_HEAD_ROOM + - shdlc->tx_tailroom + payload_len, GFP_KERNEL); + skb = alloc_skb(shdlc->client_headroom + SHDLC_LLC_HEAD_ROOM + + shdlc->client_tailroom + SHDLC_LLC_TAIL_ROOM + + payload_len, GFP_KERNEL); if (skb) - skb_reserve(skb, shdlc->tx_headroom + SHDLC_LLC_HEAD_ROOM); + skb_reserve(skb, shdlc->client_headroom + SHDLC_LLC_HEAD_ROOM); return skb; } +static void nfc_shdlc_add_len_crc(struct sk_buff *skb) +{ + u16 crc; + int len; + + len = skb->len + 2; + *skb_push(skb, 1) = len; + + crc = crc_ccitt(0xffff, skb->data, skb->len); + crc = ~crc; + *skb_put(skb, 1) = crc & 0xff; + *skb_put(skb, 1) = crc >> 8; +} + /* immediately sends an S frame. */ -static int llc_shdlc_send_s_frame(struct llc_shdlc *shdlc, +static int nfc_shdlc_send_s_frame(struct nfc_shdlc *shdlc, enum sframe_type sframe_type, int nr) { int r; @@ -158,13 +125,15 @@ static int llc_shdlc_send_s_frame(struct llc_shdlc *shdlc, pr_debug("sframe_type=%d nr=%d\n", sframe_type, nr); - skb = llc_shdlc_alloc_skb(shdlc, 0); + skb = nfc_shdlc_alloc_skb(shdlc, 0); if (skb == NULL) return -ENOMEM; *skb_push(skb, 1) = SHDLC_CONTROL_HEAD_S | (sframe_type << 3) | nr; - r = shdlc->xmit_to_drv(shdlc->hdev, skb); + nfc_shdlc_add_len_crc(skb); + + r = shdlc->ops->xmit(shdlc, skb); kfree_skb(skb); @@ -172,7 +141,7 @@ static int llc_shdlc_send_s_frame(struct llc_shdlc *shdlc, } /* immediately sends an U frame. skb may contain optional payload */ -static int llc_shdlc_send_u_frame(struct llc_shdlc *shdlc, +static int nfc_shdlc_send_u_frame(struct nfc_shdlc *shdlc, struct sk_buff *skb, enum uframe_modifier uframe_modifier) { @@ -182,7 +151,9 @@ static int llc_shdlc_send_u_frame(struct llc_shdlc *shdlc, *skb_push(skb, 1) = SHDLC_CONTROL_HEAD_U | uframe_modifier; - r = shdlc->xmit_to_drv(shdlc->hdev, skb); + nfc_shdlc_add_len_crc(skb); + + r = shdlc->ops->xmit(shdlc, skb); kfree_skb(skb); @@ -193,7 +164,7 @@ static int llc_shdlc_send_u_frame(struct llc_shdlc *shdlc, * Free ack_pending frames until y_nr - 1, and reset t2 according to * the remaining oldest ack_pending frame sent time */ -static void llc_shdlc_reset_t2(struct llc_shdlc *shdlc, int y_nr) +static void nfc_shdlc_reset_t2(struct nfc_shdlc *shdlc, int y_nr) { struct sk_buff *skb; int dnr = shdlc->dnr; /* MUST initially be < y_nr */ @@ -233,7 +204,7 @@ static void llc_shdlc_reset_t2(struct llc_shdlc *shdlc, int y_nr) * Receive validated frames from lower layer. skb contains HCI payload only. * Handle according to algorithm at spec:10.8.2 */ -static void llc_shdlc_rcv_i_frame(struct llc_shdlc *shdlc, +static void nfc_shdlc_rcv_i_frame(struct nfc_shdlc *shdlc, struct sk_buff *skb, int ns, int nr) { int x_ns = ns; @@ -245,64 +216,66 @@ static void llc_shdlc_rcv_i_frame(struct llc_shdlc *shdlc, goto exit; if (x_ns != shdlc->nr) { - llc_shdlc_send_s_frame(shdlc, S_FRAME_REJ, shdlc->nr); + nfc_shdlc_send_s_frame(shdlc, S_FRAME_REJ, shdlc->nr); goto exit; } if (shdlc->t1_active == false) { shdlc->t1_active = true; - mod_timer(&shdlc->t1_timer, jiffies + + mod_timer(&shdlc->t1_timer, msecs_to_jiffies(SHDLC_T1_VALUE_MS(shdlc->w))); pr_debug("(re)Start T1(send ack)\n"); } if (skb->len) { - shdlc->rcv_to_hci(shdlc->hdev, skb); + nfc_hci_recv_frame(shdlc->hdev, skb); skb = NULL; } shdlc->nr = (shdlc->nr + 1) % 8; - if (llc_shdlc_x_lt_y_lteq_z(shdlc->dnr, y_nr, shdlc->ns)) { - llc_shdlc_reset_t2(shdlc, y_nr); + if (nfc_shdlc_x_lt_y_lteq_z(shdlc->dnr, y_nr, shdlc->ns)) { + nfc_shdlc_reset_t2(shdlc, y_nr); shdlc->dnr = y_nr; } exit: - kfree_skb(skb); + if (skb) + kfree_skb(skb); } -static void llc_shdlc_rcv_ack(struct llc_shdlc *shdlc, int y_nr) +static void nfc_shdlc_rcv_ack(struct nfc_shdlc *shdlc, int y_nr) { pr_debug("remote acked up to frame %d excluded\n", y_nr); - if (llc_shdlc_x_lt_y_lteq_z(shdlc->dnr, y_nr, shdlc->ns)) { - llc_shdlc_reset_t2(shdlc, y_nr); + if (nfc_shdlc_x_lt_y_lteq_z(shdlc->dnr, y_nr, shdlc->ns)) { + nfc_shdlc_reset_t2(shdlc, y_nr); shdlc->dnr = y_nr; } } -static void llc_shdlc_requeue_ack_pending(struct llc_shdlc *shdlc) +static void nfc_shdlc_requeue_ack_pending(struct nfc_shdlc *shdlc) { struct sk_buff *skb; pr_debug("ns reset to %d\n", shdlc->dnr); while ((skb = skb_dequeue_tail(&shdlc->ack_pending_q))) { - skb_pull(skb, 1); /* remove control field */ + skb_pull(skb, 2); /* remove len+control */ + skb_trim(skb, skb->len - 2); /* remove crc */ skb_queue_head(&shdlc->send_q, skb); } shdlc->ns = shdlc->dnr; } -static void llc_shdlc_rcv_rej(struct llc_shdlc *shdlc, int y_nr) +static void nfc_shdlc_rcv_rej(struct nfc_shdlc *shdlc, int y_nr) { struct sk_buff *skb; pr_debug("remote asks retransmition from frame %d\n", y_nr); - if (llc_shdlc_x_lteq_y_lt_z(shdlc->dnr, y_nr, shdlc->ns)) { + if (nfc_shdlc_x_lteq_y_lt_z(shdlc->dnr, y_nr, shdlc->ns)) { if (shdlc->t2_active) { del_timer_sync(&shdlc->t2_timer); shdlc->t2_active = false; @@ -316,12 +289,12 @@ static void llc_shdlc_rcv_rej(struct llc_shdlc *shdlc, int y_nr) } } - llc_shdlc_requeue_ack_pending(shdlc); + nfc_shdlc_requeue_ack_pending(shdlc); } } /* See spec RR:10.8.3 REJ:10.8.4 */ -static void llc_shdlc_rcv_s_frame(struct llc_shdlc *shdlc, +static void nfc_shdlc_rcv_s_frame(struct nfc_shdlc *shdlc, enum sframe_type s_frame_type, int nr) { struct sk_buff *skb; @@ -331,21 +304,21 @@ static void llc_shdlc_rcv_s_frame(struct llc_shdlc *shdlc, switch (s_frame_type) { case S_FRAME_RR: - llc_shdlc_rcv_ack(shdlc, nr); + nfc_shdlc_rcv_ack(shdlc, nr); if (shdlc->rnr == true) { /* see SHDLC 10.7.7 */ shdlc->rnr = false; if (shdlc->send_q.qlen == 0) { - skb = llc_shdlc_alloc_skb(shdlc, 0); + skb = nfc_shdlc_alloc_skb(shdlc, 0); if (skb) skb_queue_tail(&shdlc->send_q, skb); } } break; case S_FRAME_REJ: - llc_shdlc_rcv_rej(shdlc, nr); + nfc_shdlc_rcv_rej(shdlc, nr); break; case S_FRAME_RNR: - llc_shdlc_rcv_ack(shdlc, nr); + nfc_shdlc_rcv_ack(shdlc, nr); shdlc->rnr = true; break; default: @@ -353,7 +326,7 @@ static void llc_shdlc_rcv_s_frame(struct llc_shdlc *shdlc, } } -static void llc_shdlc_connect_complete(struct llc_shdlc *shdlc, int r) +static void nfc_shdlc_connect_complete(struct nfc_shdlc *shdlc, int r) { pr_debug("result=%d\n", r); @@ -364,7 +337,7 @@ static void llc_shdlc_connect_complete(struct llc_shdlc *shdlc, int r) shdlc->nr = 0; shdlc->dnr = 0; - shdlc->state = SHDLC_HALF_CONNECTED; + shdlc->state = SHDLC_CONNECTED; } else { shdlc->state = SHDLC_DISCONNECTED; } @@ -374,36 +347,36 @@ static void llc_shdlc_connect_complete(struct llc_shdlc *shdlc, int r) wake_up(shdlc->connect_wq); } -static int llc_shdlc_connect_initiate(struct llc_shdlc *shdlc) +static int nfc_shdlc_connect_initiate(struct nfc_shdlc *shdlc) { struct sk_buff *skb; pr_debug("\n"); - skb = llc_shdlc_alloc_skb(shdlc, 2); + skb = nfc_shdlc_alloc_skb(shdlc, 2); if (skb == NULL) return -ENOMEM; *skb_put(skb, 1) = SHDLC_MAX_WINDOW; *skb_put(skb, 1) = SHDLC_SREJ_SUPPORT ? 1 : 0; - return llc_shdlc_send_u_frame(shdlc, skb, U_FRAME_RSET); + return nfc_shdlc_send_u_frame(shdlc, skb, U_FRAME_RSET); } -static int llc_shdlc_connect_send_ua(struct llc_shdlc *shdlc) +static int nfc_shdlc_connect_send_ua(struct nfc_shdlc *shdlc) { struct sk_buff *skb; pr_debug("\n"); - skb = llc_shdlc_alloc_skb(shdlc, 0); + skb = nfc_shdlc_alloc_skb(shdlc, 0); if (skb == NULL) return -ENOMEM; - return llc_shdlc_send_u_frame(shdlc, skb, U_FRAME_UA); + return nfc_shdlc_send_u_frame(shdlc, skb, U_FRAME_UA); } -static void llc_shdlc_rcv_u_frame(struct llc_shdlc *shdlc, +static void nfc_shdlc_rcv_u_frame(struct nfc_shdlc *shdlc, struct sk_buff *skb, enum uframe_modifier u_frame_modifier) { @@ -415,13 +388,8 @@ static void llc_shdlc_rcv_u_frame(struct llc_shdlc *shdlc, switch (u_frame_modifier) { case U_FRAME_RSET: - switch (shdlc->state) { - case SHDLC_NEGOTIATING: - case SHDLC_CONNECTING: - /* - * We sent RSET, but chip wants to negociate or we - * got RSET before we managed to send out our. - */ + if (shdlc->state == SHDLC_NEGOCIATING) { + /* we sent RSET, but chip wants to negociate */ if (skb->len > 0) w = skb->data[0]; @@ -433,34 +401,22 @@ static void llc_shdlc_rcv_u_frame(struct llc_shdlc *shdlc, (SHDLC_SREJ_SUPPORT || (srej_support == false))) { shdlc->w = w; shdlc->srej_support = srej_support; - r = llc_shdlc_connect_send_ua(shdlc); - llc_shdlc_connect_complete(shdlc, r); + r = nfc_shdlc_connect_send_ua(shdlc); + nfc_shdlc_connect_complete(shdlc, r); } - break; - case SHDLC_HALF_CONNECTED: - /* - * Chip resent RSET due to its timeout - Ignote it - * as we already sent UA. - */ - break; - case SHDLC_CONNECTED: + } else if (shdlc->state == SHDLC_CONNECTED) { /* * Chip wants to reset link. This is unexpected and * unsupported. */ shdlc->hard_fault = -ECONNRESET; - break; - default: - break; } break; case U_FRAME_UA: if ((shdlc->state == SHDLC_CONNECTING && shdlc->connect_tries > 0) || - (shdlc->state == SHDLC_NEGOTIATING)) { - llc_shdlc_connect_complete(shdlc, 0); - shdlc->state = SHDLC_CONNECTED; - } + (shdlc->state == SHDLC_NEGOCIATING)) + nfc_shdlc_connect_complete(shdlc, 0); break; default: break; @@ -469,7 +425,7 @@ static void llc_shdlc_rcv_u_frame(struct llc_shdlc *shdlc, kfree_skb(skb); } -static void llc_shdlc_handle_rcv_queue(struct llc_shdlc *shdlc) +static void nfc_shdlc_handle_rcv_queue(struct nfc_shdlc *shdlc) { struct sk_buff *skb; u8 control; @@ -487,25 +443,19 @@ static void llc_shdlc_handle_rcv_queue(struct llc_shdlc *shdlc) switch (control & SHDLC_CONTROL_HEAD_MASK) { case SHDLC_CONTROL_HEAD_I: case SHDLC_CONTROL_HEAD_I2: - if (shdlc->state == SHDLC_HALF_CONNECTED) - shdlc->state = SHDLC_CONNECTED; - ns = (control & SHDLC_CONTROL_NS_MASK) >> 3; nr = control & SHDLC_CONTROL_NR_MASK; - llc_shdlc_rcv_i_frame(shdlc, skb, ns, nr); + nfc_shdlc_rcv_i_frame(shdlc, skb, ns, nr); break; case SHDLC_CONTROL_HEAD_S: - if (shdlc->state == SHDLC_HALF_CONNECTED) - shdlc->state = SHDLC_CONNECTED; - s_frame_type = (control & SHDLC_CONTROL_TYPE_MASK) >> 3; nr = control & SHDLC_CONTROL_NR_MASK; - llc_shdlc_rcv_s_frame(shdlc, s_frame_type, nr); + nfc_shdlc_rcv_s_frame(shdlc, s_frame_type, nr); kfree_skb(skb); break; case SHDLC_CONTROL_HEAD_U: u_frame_modifier = control & SHDLC_CONTROL_M_MASK; - llc_shdlc_rcv_u_frame(shdlc, skb, u_frame_modifier); + nfc_shdlc_rcv_u_frame(shdlc, skb, u_frame_modifier); break; default: pr_err("UNKNOWN Control=%d\n", control); @@ -515,7 +465,7 @@ static void llc_shdlc_handle_rcv_queue(struct llc_shdlc *shdlc) } } -static int llc_shdlc_w_used(int ns, int dnr) +static int nfc_shdlc_w_used(int ns, int dnr) { int unack_count; @@ -528,7 +478,7 @@ static int llc_shdlc_w_used(int ns, int dnr) } /* Send frames according to algorithm at spec:10.8.1 */ -static void llc_shdlc_handle_send_queue(struct llc_shdlc *shdlc) +static void nfc_shdlc_handle_send_queue(struct nfc_shdlc *shdlc) { struct sk_buff *skb; int r; @@ -539,7 +489,7 @@ static void llc_shdlc_handle_send_queue(struct llc_shdlc *shdlc) ("sendQlen=%d ns=%d dnr=%d rnr=%s w_room=%d unackQlen=%d\n", shdlc->send_q.qlen, shdlc->ns, shdlc->dnr, shdlc->rnr == false ? "false" : "true", - shdlc->w - llc_shdlc_w_used(shdlc->ns, shdlc->dnr), + shdlc->w - nfc_shdlc_w_used(shdlc->ns, shdlc->dnr), shdlc->ack_pending_q.qlen); while (shdlc->send_q.qlen && shdlc->ack_pending_q.qlen < shdlc->w && @@ -558,9 +508,11 @@ static void llc_shdlc_handle_send_queue(struct llc_shdlc *shdlc) pr_debug("Sending I-Frame %d, waiting to rcv %d\n", shdlc->ns, shdlc->nr); - SHDLC_DUMP_SKB("shdlc frame written", skb); + /* SHDLC_DUMP_SKB("shdlc frame written", skb); */ + + nfc_shdlc_add_len_crc(skb); - r = shdlc->xmit_to_drv(shdlc->hdev, skb); + r = shdlc->ops->xmit(shdlc, skb); if (r < 0) { shdlc->hard_fault = r; break; @@ -582,36 +534,36 @@ static void llc_shdlc_handle_send_queue(struct llc_shdlc *shdlc) } } -static void llc_shdlc_connect_timeout(unsigned long data) +static void nfc_shdlc_connect_timeout(unsigned long data) { - struct llc_shdlc *shdlc = (struct llc_shdlc *)data; + struct nfc_shdlc *shdlc = (struct nfc_shdlc *)data; pr_debug("\n"); - queue_work(system_nrt_wq, &shdlc->sm_work); + queue_work(shdlc->sm_wq, &shdlc->sm_work); } -static void llc_shdlc_t1_timeout(unsigned long data) +static void nfc_shdlc_t1_timeout(unsigned long data) { - struct llc_shdlc *shdlc = (struct llc_shdlc *)data; + struct nfc_shdlc *shdlc = (struct nfc_shdlc *)data; pr_debug("SoftIRQ: need to send ack\n"); - queue_work(system_nrt_wq, &shdlc->sm_work); + queue_work(shdlc->sm_wq, &shdlc->sm_work); } -static void llc_shdlc_t2_timeout(unsigned long data) +static void nfc_shdlc_t2_timeout(unsigned long data) { - struct llc_shdlc *shdlc = (struct llc_shdlc *)data; + struct nfc_shdlc *shdlc = (struct nfc_shdlc *)data; pr_debug("SoftIRQ: need to retransmit\n"); - queue_work(system_nrt_wq, &shdlc->sm_work); + queue_work(shdlc->sm_wq, &shdlc->sm_work); } -static void llc_shdlc_sm_work(struct work_struct *work) +static void nfc_shdlc_sm_work(struct work_struct *work) { - struct llc_shdlc *shdlc = container_of(work, struct llc_shdlc, sm_work); + struct nfc_shdlc *shdlc = container_of(work, struct nfc_shdlc, sm_work); int r; pr_debug("\n"); @@ -626,47 +578,46 @@ static void llc_shdlc_sm_work(struct work_struct *work) break; case SHDLC_CONNECTING: if (shdlc->hard_fault) { - llc_shdlc_connect_complete(shdlc, shdlc->hard_fault); + nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault); break; } if (shdlc->connect_tries++ < 5) - r = llc_shdlc_connect_initiate(shdlc); + r = nfc_shdlc_connect_initiate(shdlc); else r = -ETIME; if (r < 0) - llc_shdlc_connect_complete(shdlc, r); + nfc_shdlc_connect_complete(shdlc, r); else { mod_timer(&shdlc->connect_timer, jiffies + msecs_to_jiffies(SHDLC_CONNECT_VALUE_MS)); - shdlc->state = SHDLC_NEGOTIATING; + shdlc->state = SHDLC_NEGOCIATING; } break; - case SHDLC_NEGOTIATING: + case SHDLC_NEGOCIATING: if (timer_pending(&shdlc->connect_timer) == 0) { shdlc->state = SHDLC_CONNECTING; - queue_work(system_nrt_wq, &shdlc->sm_work); + queue_work(shdlc->sm_wq, &shdlc->sm_work); } - llc_shdlc_handle_rcv_queue(shdlc); + nfc_shdlc_handle_rcv_queue(shdlc); if (shdlc->hard_fault) { - llc_shdlc_connect_complete(shdlc, shdlc->hard_fault); + nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault); break; } break; - case SHDLC_HALF_CONNECTED: case SHDLC_CONNECTED: - llc_shdlc_handle_rcv_queue(shdlc); - llc_shdlc_handle_send_queue(shdlc); + nfc_shdlc_handle_rcv_queue(shdlc); + nfc_shdlc_handle_send_queue(shdlc); if (shdlc->t1_active && timer_pending(&shdlc->t1_timer) == 0) { pr_debug ("Handle T1(send ack) elapsed (T1 now inactive)\n"); shdlc->t1_active = false; - r = llc_shdlc_send_s_frame(shdlc, S_FRAME_RR, + r = nfc_shdlc_send_s_frame(shdlc, S_FRAME_RR, shdlc->nr); if (r < 0) shdlc->hard_fault = r; @@ -678,12 +629,12 @@ static void llc_shdlc_sm_work(struct work_struct *work) shdlc->t2_active = false; - llc_shdlc_requeue_ack_pending(shdlc); - llc_shdlc_handle_send_queue(shdlc); + nfc_shdlc_requeue_ack_pending(shdlc); + nfc_shdlc_handle_send_queue(shdlc); } if (shdlc->hard_fault) { - shdlc->llc_failure(shdlc->hdev, shdlc->hard_fault); + nfc_hci_driver_failure(shdlc->hdev, shdlc->hard_fault); } break; default: @@ -696,7 +647,7 @@ static void llc_shdlc_sm_work(struct work_struct *work) * Called from syscall context to establish shdlc link. Sleeps until * link is ready or failure. */ -static int llc_shdlc_connect(struct llc_shdlc *shdlc) +static int nfc_shdlc_connect(struct nfc_shdlc *shdlc) { DECLARE_WAIT_QUEUE_HEAD_ONSTACK(connect_wq); @@ -711,14 +662,14 @@ static int llc_shdlc_connect(struct llc_shdlc *shdlc) mutex_unlock(&shdlc->state_mutex); - queue_work(system_nrt_wq, &shdlc->sm_work); + queue_work(shdlc->sm_wq, &shdlc->sm_work); wait_event(connect_wq, shdlc->connect_result != 1); return shdlc->connect_result; } -static void llc_shdlc_disconnect(struct llc_shdlc *shdlc) +static void nfc_shdlc_disconnect(struct nfc_shdlc *shdlc) { pr_debug("\n"); @@ -728,7 +679,7 @@ static void llc_shdlc_disconnect(struct llc_shdlc *shdlc) mutex_unlock(&shdlc->state_mutex); - queue_work(system_nrt_wq, &shdlc->sm_work); + queue_work(shdlc->sm_wq, &shdlc->sm_work); } /* @@ -736,7 +687,7 @@ static void llc_shdlc_disconnect(struct llc_shdlc *shdlc) * skb contains only LLC header and payload. * If skb == NULL, it is a notification that the link below is dead. */ -static void llc_shdlc_recv_frame(struct llc_shdlc *shdlc, struct sk_buff *skb) +void nfc_shdlc_recv_frame(struct nfc_shdlc *shdlc, struct sk_buff *skb) { if (skb == NULL) { pr_err("NULL Frame -> link is dead\n"); @@ -746,37 +697,176 @@ static void llc_shdlc_recv_frame(struct llc_shdlc *shdlc, struct sk_buff *skb) skb_queue_tail(&shdlc->rcv_q, skb); } - queue_work(system_nrt_wq, &shdlc->sm_work); + queue_work(shdlc->sm_wq, &shdlc->sm_work); +} +EXPORT_SYMBOL(nfc_shdlc_recv_frame); + +static int nfc_shdlc_open(struct nfc_hci_dev *hdev) +{ + struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); + int r; + + pr_debug("\n"); + + if (shdlc->ops->open) { + r = shdlc->ops->open(shdlc); + if (r < 0) + return r; + } + + r = nfc_shdlc_connect(shdlc); + if (r < 0 && shdlc->ops->close) + shdlc->ops->close(shdlc); + + return r; +} + +static void nfc_shdlc_close(struct nfc_hci_dev *hdev) +{ + struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); + + pr_debug("\n"); + + nfc_shdlc_disconnect(shdlc); + + if (shdlc->ops->close) + shdlc->ops->close(shdlc); } -static void *llc_shdlc_init(struct nfc_hci_dev *hdev, xmit_to_drv_t xmit_to_drv, - rcv_to_hci_t rcv_to_hci, int tx_headroom, - int tx_tailroom, int *rx_headroom, int *rx_tailroom, - llc_failure_t llc_failure) +static int nfc_shdlc_hci_ready(struct nfc_hci_dev *hdev) { - struct llc_shdlc *shdlc; + struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); + int r = 0; + + pr_debug("\n"); - *rx_headroom = SHDLC_LLC_HEAD_ROOM; - *rx_tailroom = 0; + if (shdlc->ops->hci_ready) + r = shdlc->ops->hci_ready(shdlc); + + return r; +} + +static int nfc_shdlc_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) +{ + struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); + + SHDLC_DUMP_SKB("queuing HCP packet to shdlc", skb); + + skb_queue_tail(&shdlc->send_q, skb); - shdlc = kzalloc(sizeof(struct llc_shdlc), GFP_KERNEL); + queue_work(shdlc->sm_wq, &shdlc->sm_work); + + return 0; +} + +static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, + u32 im_protocols, u32 tm_protocols) +{ + struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); + + pr_debug("\n"); + + if (shdlc->ops->start_poll) + return shdlc->ops->start_poll(shdlc, + im_protocols, tm_protocols); + + return 0; +} + +static int nfc_shdlc_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, + struct nfc_target *target) +{ + struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); + + if (shdlc->ops->target_from_gate) + return shdlc->ops->target_from_gate(shdlc, gate, target); + + return -EPERM; +} + +static int nfc_shdlc_complete_target_discovered(struct nfc_hci_dev *hdev, + u8 gate, + struct nfc_target *target) +{ + struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); + + pr_debug("\n"); + + if (shdlc->ops->complete_target_discovered) + return shdlc->ops->complete_target_discovered(shdlc, gate, + target); + + return 0; +} + +static int nfc_shdlc_data_exchange(struct nfc_hci_dev *hdev, + struct nfc_target *target, + struct sk_buff *skb, + struct sk_buff **res_skb) +{ + struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); + + if (shdlc->ops->data_exchange) + return shdlc->ops->data_exchange(shdlc, target, skb, res_skb); + + return -EPERM; +} + +static int nfc_shdlc_check_presence(struct nfc_hci_dev *hdev, + struct nfc_target *target) +{ + struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); + + if (shdlc->ops->check_presence) + return shdlc->ops->check_presence(shdlc, target); + + return 0; +} + +static struct nfc_hci_ops shdlc_ops = { + .open = nfc_shdlc_open, + .close = nfc_shdlc_close, + .hci_ready = nfc_shdlc_hci_ready, + .xmit = nfc_shdlc_xmit, + .start_poll = nfc_shdlc_start_poll, + .target_from_gate = nfc_shdlc_target_from_gate, + .complete_target_discovered = nfc_shdlc_complete_target_discovered, + .data_exchange = nfc_shdlc_data_exchange, + .check_presence = nfc_shdlc_check_presence, +}; + +struct nfc_shdlc *nfc_shdlc_allocate(struct nfc_shdlc_ops *ops, + struct nfc_hci_init_data *init_data, + u32 protocols, + int tx_headroom, int tx_tailroom, + int max_link_payload, const char *devname) +{ + struct nfc_shdlc *shdlc; + int r; + char name[32]; + + if (ops->xmit == NULL) + return NULL; + + shdlc = kzalloc(sizeof(struct nfc_shdlc), GFP_KERNEL); if (shdlc == NULL) return NULL; mutex_init(&shdlc->state_mutex); + shdlc->ops = ops; shdlc->state = SHDLC_DISCONNECTED; init_timer(&shdlc->connect_timer); shdlc->connect_timer.data = (unsigned long)shdlc; - shdlc->connect_timer.function = llc_shdlc_connect_timeout; + shdlc->connect_timer.function = nfc_shdlc_connect_timeout; init_timer(&shdlc->t1_timer); shdlc->t1_timer.data = (unsigned long)shdlc; - shdlc->t1_timer.function = llc_shdlc_t1_timeout; + shdlc->t1_timer.function = nfc_shdlc_t1_timeout; init_timer(&shdlc->t2_timer); shdlc->t2_timer.data = (unsigned long)shdlc; - shdlc->t2_timer.function = llc_shdlc_t2_timeout; + shdlc->t2_timer.function = nfc_shdlc_t2_timeout; shdlc->w = SHDLC_MAX_WINDOW; shdlc->srej_support = SHDLC_SREJ_SUPPORT; @@ -785,73 +875,77 @@ static void *llc_shdlc_init(struct nfc_hci_dev *hdev, xmit_to_drv_t xmit_to_drv, skb_queue_head_init(&shdlc->send_q); skb_queue_head_init(&shdlc->ack_pending_q); - INIT_WORK(&shdlc->sm_work, llc_shdlc_sm_work); + INIT_WORK(&shdlc->sm_work, nfc_shdlc_sm_work); + snprintf(name, sizeof(name), "%s_shdlc_sm_wq", devname); + shdlc->sm_wq = alloc_workqueue(name, WQ_NON_REENTRANT | WQ_UNBOUND | + WQ_MEM_RECLAIM, 1); + if (shdlc->sm_wq == NULL) + goto err_allocwq; - shdlc->hdev = hdev; - shdlc->xmit_to_drv = xmit_to_drv; - shdlc->rcv_to_hci = rcv_to_hci; - shdlc->tx_headroom = tx_headroom; - shdlc->tx_tailroom = tx_tailroom; - shdlc->llc_failure = llc_failure; + shdlc->client_headroom = tx_headroom; + shdlc->client_tailroom = tx_tailroom; + + shdlc->hdev = nfc_hci_allocate_device(&shdlc_ops, init_data, protocols, + tx_headroom + SHDLC_LLC_HEAD_ROOM, + tx_tailroom + SHDLC_LLC_TAIL_ROOM, + max_link_payload); + if (shdlc->hdev == NULL) + goto err_allocdev; + + nfc_hci_set_clientdata(shdlc->hdev, shdlc); + + r = nfc_hci_register_device(shdlc->hdev); + if (r < 0) + goto err_regdev; return shdlc; -} -static void llc_shdlc_deinit(struct nfc_llc *llc) -{ - struct llc_shdlc *shdlc = nfc_llc_get_data(llc); +err_regdev: + nfc_hci_free_device(shdlc->hdev); - skb_queue_purge(&shdlc->rcv_q); - skb_queue_purge(&shdlc->send_q); - skb_queue_purge(&shdlc->ack_pending_q); +err_allocdev: + destroy_workqueue(shdlc->sm_wq); +err_allocwq: kfree(shdlc); + + return NULL; } +EXPORT_SYMBOL(nfc_shdlc_allocate); -static int llc_shdlc_start(struct nfc_llc *llc) +void nfc_shdlc_free(struct nfc_shdlc *shdlc) { - struct llc_shdlc *shdlc = nfc_llc_get_data(llc); + pr_debug("\n"); - return llc_shdlc_connect(shdlc); -} + nfc_hci_unregister_device(shdlc->hdev); + nfc_hci_free_device(shdlc->hdev); -static int llc_shdlc_stop(struct nfc_llc *llc) -{ - struct llc_shdlc *shdlc = nfc_llc_get_data(llc); + destroy_workqueue(shdlc->sm_wq); - llc_shdlc_disconnect(shdlc); + skb_queue_purge(&shdlc->rcv_q); + skb_queue_purge(&shdlc->send_q); + skb_queue_purge(&shdlc->ack_pending_q); - return 0; + kfree(shdlc); } +EXPORT_SYMBOL(nfc_shdlc_free); -static void llc_shdlc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb) +void nfc_shdlc_set_clientdata(struct nfc_shdlc *shdlc, void *clientdata) { - struct llc_shdlc *shdlc = nfc_llc_get_data(llc); + pr_debug("\n"); - llc_shdlc_recv_frame(shdlc, skb); + shdlc->clientdata = clientdata; } +EXPORT_SYMBOL(nfc_shdlc_set_clientdata); -static int llc_shdlc_xmit_from_hci(struct nfc_llc *llc, struct sk_buff *skb) +void *nfc_shdlc_get_clientdata(struct nfc_shdlc *shdlc) { - struct llc_shdlc *shdlc = nfc_llc_get_data(llc); - - skb_queue_tail(&shdlc->send_q, skb); - - queue_work(system_nrt_wq, &shdlc->sm_work); - - return 0; + return shdlc->clientdata; } +EXPORT_SYMBOL(nfc_shdlc_get_clientdata); -static struct nfc_llc_ops llc_shdlc_ops = { - .init = llc_shdlc_init, - .deinit = llc_shdlc_deinit, - .start = llc_shdlc_start, - .stop = llc_shdlc_stop, - .rcv_from_drv = llc_shdlc_rcv_from_drv, - .xmit_from_hci = llc_shdlc_xmit_from_hci, -}; - -int nfc_llc_shdlc_register(void) +struct nfc_hci_dev *nfc_shdlc_get_hci_dev(struct nfc_shdlc *shdlc) { - return nfc_llc_register(LLC_SHDLC_NAME, &llc_shdlc_ops); + return shdlc->hdev; } +EXPORT_SYMBOL(nfc_shdlc_get_hci_dev); diff --git a/trunk/net/nfc/llcp/commands.c b/trunk/net/nfc/llcp/commands.c index c45ccd6c094c..b982b5b890d7 100644 --- a/trunk/net/nfc/llcp/commands.c +++ b/trunk/net/nfc/llcp/commands.c @@ -312,8 +312,6 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); - nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); - return nfc_data_exchange(dev, local->target_idx, skb, nfc_llcp_recv, local); } diff --git a/trunk/net/nfc/llcp/llcp.c b/trunk/net/nfc/llcp/llcp.c index c12c5ef3d036..82f0f7588b46 100644 --- a/trunk/net/nfc/llcp/llcp.c +++ b/trunk/net/nfc/llcp/llcp.c @@ -56,7 +56,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) sk_for_each_safe(sk, node, tmp, &local->sockets.head) { llcp_sock = nfc_llcp_sock(sk); - bh_lock_sock(sk); + lock_sock(sk); if (sk->sk_state == LLCP_CONNECTED) nfc_put_device(llcp_sock->dev); @@ -68,26 +68,26 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, accept_queue) { accept_sk = &lsk->sk; - bh_lock_sock(accept_sk); + lock_sock(accept_sk); nfc_llcp_accept_unlink(accept_sk); accept_sk->sk_state = LLCP_CLOSED; - bh_unlock_sock(accept_sk); + release_sock(accept_sk); sock_orphan(accept_sk); } if (listen == true) { - bh_unlock_sock(sk); + release_sock(sk); continue; } } sk->sk_state = LLCP_CLOSED; - bh_unlock_sock(sk); + release_sock(sk); sock_orphan(sk); @@ -114,9 +114,9 @@ static void local_release(struct kref *ref) nfc_llcp_socket_release(local, false); del_timer_sync(&local->link_timer); skb_queue_purge(&local->tx_queue); - cancel_work_sync(&local->tx_work); - cancel_work_sync(&local->rx_work); - cancel_work_sync(&local->timeout_work); + destroy_workqueue(local->tx_wq); + destroy_workqueue(local->rx_wq); + destroy_workqueue(local->timeout_wq); kfree_skb(local->rx_pending); kfree(local); } @@ -181,7 +181,7 @@ static void nfc_llcp_symm_timer(unsigned long data) pr_err("SYMM timeout\n"); - queue_work(system_nrt_wq, &local->timeout_work); + queue_work(local->timeout_wq, &local->timeout_work); } struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) @@ -426,7 +426,6 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) u8 *miux_tlv, miux_length; __be16 miux; u8 gb_len = 0; - int ret = 0; version = LLCP_VERSION_11; version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version, @@ -451,8 +450,8 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) gb_len += ARRAY_SIZE(llcp_magic); if (gb_len > NFC_MAX_GT_LEN) { - ret = -EINVAL; - goto out; + kfree(version_tlv); + return -EINVAL; } gb_cur = local->gb; @@ -472,15 +471,12 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) memcpy(gb_cur, miux_tlv, miux_length); gb_cur += miux_length; - local->gb_len = gb_len; - -out: kfree(version_tlv); kfree(lto_tlv); - kfree(wks_tlv); - kfree(miux_tlv); - return ret; + local->gb_len = gb_len; + + return 0; } u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) @@ -558,46 +554,6 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) sock->recv_ack_n = (sock->recv_n - 1) % 16; } -void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local, - struct sk_buff *skb, u8 direction) -{ - struct hlist_node *node; - struct sk_buff *skb_copy = NULL, *nskb; - struct sock *sk; - u8 *data; - - read_lock(&local->raw_sockets.lock); - - sk_for_each(sk, node, &local->raw_sockets.head) { - if (sk->sk_state != LLCP_BOUND) - continue; - - if (skb_copy == NULL) { - skb_copy = __pskb_copy(skb, NFC_LLCP_RAW_HEADER_SIZE, - GFP_ATOMIC); - - if (skb_copy == NULL) - continue; - - data = skb_push(skb_copy, NFC_LLCP_RAW_HEADER_SIZE); - - data[0] = local->dev ? local->dev->idx : 0xFF; - data[1] = direction; - } - - nskb = skb_clone(skb_copy, GFP_ATOMIC); - if (!nskb) - continue; - - if (sock_queue_rcv_skb(sk, nskb)) - kfree_skb(nskb); - } - - read_unlock(&local->raw_sockets.lock); - - kfree_skb(skb_copy); -} - static void nfc_llcp_tx_work(struct work_struct *work) { struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, @@ -618,9 +574,6 @@ static void nfc_llcp_tx_work(struct work_struct *work) DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, true); - nfc_llcp_send_to_raw_sock(local, skb, - NFC_LLCP_DIRECTION_TX); - ret = nfc_data_exchange(local->dev, local->target_idx, skb, nfc_llcp_recv, local); @@ -1065,8 +1018,6 @@ static void nfc_llcp_rx_work(struct work_struct *work) print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, true); - nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX); - switch (ptype) { case LLCP_PDU_SYMM: pr_debug("SYMM\n"); @@ -1101,7 +1052,7 @@ static void nfc_llcp_rx_work(struct work_struct *work) } - queue_work(system_nrt_wq, &local->tx_work); + queue_work(local->tx_wq, &local->tx_work); kfree_skb(local->rx_pending); local->rx_pending = NULL; @@ -1120,7 +1071,7 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) local->rx_pending = skb_get(skb); del_timer(&local->link_timer); - queue_work(system_nrt_wq, &local->rx_work); + queue_work(local->rx_wq, &local->rx_work); return; } @@ -1135,7 +1086,7 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) local->rx_pending = skb_get(skb); del_timer(&local->link_timer); - queue_work(system_nrt_wq, &local->rx_work); + queue_work(local->rx_wq, &local->rx_work); return 0; } @@ -1170,7 +1121,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, if (rf_mode == NFC_RF_INITIATOR) { pr_debug("Queueing Tx work\n"); - queue_work(system_nrt_wq, &local->tx_work); + queue_work(local->tx_wq, &local->tx_work); } else { mod_timer(&local->link_timer, jiffies + msecs_to_jiffies(local->remote_lto)); @@ -1179,7 +1130,10 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, int nfc_llcp_register_device(struct nfc_dev *ndev) { + struct device *dev = &ndev->dev; struct nfc_llcp_local *local; + char name[32]; + int err; local = kzalloc(sizeof(struct nfc_llcp_local), GFP_KERNEL); if (local == NULL) @@ -1195,15 +1149,41 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) skb_queue_head_init(&local->tx_queue); INIT_WORK(&local->tx_work, nfc_llcp_tx_work); + snprintf(name, sizeof(name), "%s_llcp_tx_wq", dev_name(dev)); + local->tx_wq = + alloc_workqueue(name, + WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, + 1); + if (local->tx_wq == NULL) { + err = -ENOMEM; + goto err_local; + } local->rx_pending = NULL; INIT_WORK(&local->rx_work, nfc_llcp_rx_work); + snprintf(name, sizeof(name), "%s_llcp_rx_wq", dev_name(dev)); + local->rx_wq = + alloc_workqueue(name, + WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, + 1); + if (local->rx_wq == NULL) { + err = -ENOMEM; + goto err_tx_wq; + } INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work); + snprintf(name, sizeof(name), "%s_llcp_timeout_wq", dev_name(dev)); + local->timeout_wq = + alloc_workqueue(name, + WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, + 1); + if (local->timeout_wq == NULL) { + err = -ENOMEM; + goto err_rx_wq; + } - rwlock_init(&local->sockets.lock); - rwlock_init(&local->connecting_sockets.lock); - rwlock_init(&local->raw_sockets.lock); + local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); + local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); nfc_llcp_build_gb(local); @@ -1212,6 +1192,17 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) list_add(&llcp_devices, &local->list); + return 0; + +err_rx_wq: + destroy_workqueue(local->rx_wq); + +err_tx_wq: + destroy_workqueue(local->tx_wq); + +err_local: + kfree(local); + return 0; } diff --git a/trunk/net/nfc/llcp/llcp.h b/trunk/net/nfc/llcp/llcp.h index fdb2d24e60bd..83b8bba5a280 100644 --- a/trunk/net/nfc/llcp/llcp.h +++ b/trunk/net/nfc/llcp/llcp.h @@ -56,9 +56,12 @@ struct nfc_llcp_local { struct timer_list link_timer; struct sk_buff_head tx_queue; + struct workqueue_struct *tx_wq; struct work_struct tx_work; + struct workqueue_struct *rx_wq; struct work_struct rx_work; struct sk_buff *rx_pending; + struct workqueue_struct *timeout_wq; struct work_struct timeout_work; u32 target_idx; @@ -86,7 +89,6 @@ struct nfc_llcp_local { /* sockets array */ struct llcp_sock_list sockets; struct llcp_sock_list connecting_sockets; - struct llcp_sock_list raw_sockets; }; struct nfc_llcp_sock { @@ -185,8 +187,6 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap); int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock); -void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local, - struct sk_buff *skb, u8 direction); /* Sock API */ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp); diff --git a/trunk/net/nfc/llcp/sock.c b/trunk/net/nfc/llcp/sock.c index 40f056debf9a..ddeb9aa398f0 100644 --- a/trunk/net/nfc/llcp/sock.c +++ b/trunk/net/nfc/llcp/sock.c @@ -142,60 +142,6 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) return ret; } -static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr, - int alen) -{ - struct sock *sk = sock->sk; - struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); - struct nfc_llcp_local *local; - struct nfc_dev *dev; - struct sockaddr_nfc_llcp llcp_addr; - int len, ret = 0; - - if (!addr || addr->sa_family != AF_NFC) - return -EINVAL; - - pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); - - memset(&llcp_addr, 0, sizeof(llcp_addr)); - len = min_t(unsigned int, sizeof(llcp_addr), alen); - memcpy(&llcp_addr, addr, len); - - lock_sock(sk); - - if (sk->sk_state != LLCP_CLOSED) { - ret = -EBADFD; - goto error; - } - - dev = nfc_get_device(llcp_addr.dev_idx); - if (dev == NULL) { - ret = -ENODEV; - goto error; - } - - local = nfc_llcp_find_local(dev); - if (local == NULL) { - ret = -ENODEV; - goto put_dev; - } - - llcp_sock->dev = dev; - llcp_sock->local = nfc_llcp_local_get(local); - llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; - - nfc_llcp_sock_link(&local->raw_sockets, sk); - - sk->sk_state = LLCP_BOUND; - -put_dev: - nfc_put_device(dev); - -error: - release_sock(sk); - return ret; -} - static int llcp_sock_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; @@ -354,6 +300,9 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr, pr_debug("%p %d %d %d\n", sk, llcp_sock->target_idx, llcp_sock->dsap, llcp_sock->ssap); + if (llcp_sock == NULL || llcp_sock->dev == NULL) + return -EBADFD; + uaddr->sa_family = AF_NFC; *len = sizeof(struct sockaddr_nfc_llcp); @@ -472,10 +421,7 @@ static int llcp_sock_release(struct socket *sock) release_sock(sk); - if (sock->type == SOCK_RAW) - nfc_llcp_sock_unlink(&local->raw_sockets, sk); - else - nfc_llcp_sock_unlink(&local->sockets, sk); + nfc_llcp_sock_unlink(&local->sockets, sk); out: sock_orphan(sk); @@ -671,7 +617,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (!(flags & MSG_PEEK)) { /* SOCK_STREAM: re-queue skb if it contains unreceived data */ - if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_RAW) { + if (sk->sk_type == SOCK_STREAM) { skb_pull(skb, copied); if (skb->len) { skb_queue_head(&sk->sk_receive_queue, skb); @@ -712,26 +658,6 @@ static const struct proto_ops llcp_sock_ops = { .mmap = sock_no_mmap, }; -static const struct proto_ops llcp_rawsock_ops = { - .family = PF_NFC, - .owner = THIS_MODULE, - .bind = llcp_raw_sock_bind, - .connect = sock_no_connect, - .release = llcp_sock_release, - .socketpair = sock_no_socketpair, - .accept = sock_no_accept, - .getname = llcp_sock_getname, - .poll = llcp_sock_poll, - .ioctl = sock_no_ioctl, - .listen = sock_no_listen, - .shutdown = sock_no_shutdown, - .setsockopt = sock_no_setsockopt, - .getsockopt = sock_no_getsockopt, - .sendmsg = sock_no_sendmsg, - .recvmsg = llcp_sock_recvmsg, - .mmap = sock_no_mmap, -}; - static void llcp_sock_destruct(struct sock *sk) { struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); @@ -809,15 +735,10 @@ static int llcp_sock_create(struct net *net, struct socket *sock, pr_debug("%p\n", sock); - if (sock->type != SOCK_STREAM && - sock->type != SOCK_DGRAM && - sock->type != SOCK_RAW) + if (sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM) return -ESOCKTNOSUPPORT; - if (sock->type == SOCK_RAW) - sock->ops = &llcp_rawsock_ops; - else - sock->ops = &llcp_sock_ops; + sock->ops = &llcp_sock_ops; sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC); if (sk == NULL) diff --git a/trunk/net/nfc/nci/core.c b/trunk/net/nfc/nci/core.c index acf9abb7d99b..f81efe13985a 100644 --- a/trunk/net/nfc/nci/core.c +++ b/trunk/net/nfc/nci/core.c @@ -176,27 +176,6 @@ static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) (1 + ((*num) * sizeof(struct disc_map_config))), &cmd); } -struct nci_set_config_param { - __u8 id; - size_t len; - __u8 *val; -}; - -static void nci_set_config_req(struct nci_dev *ndev, unsigned long opt) -{ - struct nci_set_config_param *param = (struct nci_set_config_param *)opt; - struct nci_core_set_config_cmd cmd; - - BUG_ON(param->len > NCI_MAX_PARAM_LEN); - - cmd.num_params = 1; - cmd.param.id = param->id; - cmd.param.len = param->len; - memcpy(cmd.param.val, param->val, param->len); - - nci_send_cmd(ndev, NCI_OP_CORE_SET_CONFIG_CMD, (3 + param->len), &cmd); -} - static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) { struct nci_rf_disc_cmd cmd; @@ -409,32 +388,6 @@ static int nci_dev_down(struct nfc_dev *nfc_dev) return nci_close_device(ndev); } -static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) -{ - struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); - struct nci_set_config_param param; - __u8 local_gb[NFC_MAX_GT_LEN]; - int i, rc = 0; - - param.val = nfc_get_local_general_bytes(nfc_dev, ¶m.len); - if ((param.val == NULL) || (param.len == 0)) - return rc; - - if (param.len > NCI_MAX_PARAM_LEN) - return -EINVAL; - - for (i = 0; i < param.len; i++) - local_gb[param.len-1-i] = param.val[i]; - - param.id = NCI_PN_ATR_REQ_GEN_BYTES; - param.val = local_gb; - - rc = nci_request(ndev, nci_set_config_req, (unsigned long)¶m, - msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); - - return rc; -} - static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, __u32 tm_protocols) { @@ -462,14 +415,6 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, return -EBUSY; } - if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { - rc = nci_set_local_general_bytes(nfc_dev); - if (rc) { - pr_err("failed to set local general bytes\n"); - return rc; - } - } - rc = nci_request(ndev, nci_rf_discover_req, im_protocols, msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); @@ -564,7 +509,7 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); - pr_debug("entry\n"); + pr_debug("target_idx %d\n", target->idx); if (!ndev->target_active_prot) { pr_err("unable to deactivate target, no active target\n"); @@ -579,38 +524,6 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, } } - -static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, - __u8 comm_mode, __u8 *gb, size_t gb_len) -{ - struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); - int rc; - - pr_debug("target_idx %d, comm_mode %d\n", target->idx, comm_mode); - - rc = nci_activate_target(nfc_dev, target, NFC_PROTO_NFC_DEP); - if (rc) - return rc; - - rc = nfc_set_remote_general_bytes(nfc_dev, ndev->remote_gb, - ndev->remote_gb_len); - if (!rc) - rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_PASSIVE, - NFC_RF_INITIATOR); - - return rc; -} - -static int nci_dep_link_down(struct nfc_dev *nfc_dev) -{ - pr_debug("entry\n"); - - nci_deactivate_target(nfc_dev, NULL); - - return 0; -} - - static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, struct sk_buff *skb, data_exchange_cb_t cb, void *cb_context) @@ -644,8 +557,6 @@ static struct nfc_ops nci_nfc_ops = { .dev_down = nci_dev_down, .start_poll = nci_start_poll, .stop_poll = nci_stop_poll, - .dep_link_up = nci_dep_link_up, - .dep_link_down = nci_dep_link_down, .activate_target = nci_activate_target, .deactivate_target = nci_deactivate_target, .im_transceive = nci_transceive, diff --git a/trunk/net/nfc/nci/ntf.c b/trunk/net/nfc/nci/ntf.c index b2aa98ef0927..af7a93b04393 100644 --- a/trunk/net/nfc/nci/ntf.c +++ b/trunk/net/nfc/nci/ntf.c @@ -176,8 +176,6 @@ static int nci_add_new_protocol(struct nci_dev *ndev, protocol = NFC_PROTO_ISO14443_B_MASK; else if (rf_protocol == NCI_RF_PROTOCOL_T3T) protocol = NFC_PROTO_FELICA_MASK; - else if (rf_protocol == NCI_RF_PROTOCOL_NFC_DEP) - protocol = NFC_PROTO_NFC_DEP_MASK; else protocol = 0; @@ -363,33 +361,6 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, return NCI_STATUS_OK; } -static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev, - struct nci_rf_intf_activated_ntf *ntf, __u8 *data) -{ - struct activation_params_poll_nfc_dep *poll; - int i; - - switch (ntf->activation_rf_tech_and_mode) { - case NCI_NFC_A_PASSIVE_POLL_MODE: - case NCI_NFC_F_PASSIVE_POLL_MODE: - poll = &ntf->activation_params.poll_nfc_dep; - poll->atr_res_len = min_t(__u8, *data++, 63); - pr_debug("atr_res_len %d\n", poll->atr_res_len); - if (poll->atr_res_len > 0) { - for (i = 0; i < poll->atr_res_len; i++) - poll->atr_res[poll->atr_res_len-1-i] = data[i]; - } - break; - - default: - pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", - ntf->activation_rf_tech_and_mode); - return NCI_STATUS_RF_PROTOCOL_ERROR; - } - - return NCI_STATUS_OK; -} - static void nci_target_auto_activated(struct nci_dev *ndev, struct nci_rf_intf_activated_ntf *ntf) { @@ -483,11 +454,6 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, &ntf, data); break; - case NCI_RF_INTERFACE_NFC_DEP: - err = nci_extract_activation_params_nfc_dep(ndev, - &ntf, data); - break; - case NCI_RF_INTERFACE_FRAME: /* no activation params */ break; @@ -507,24 +473,6 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, /* set the available credits to initial value */ atomic_set(&ndev->credits_cnt, ndev->initial_num_credits); - - /* store general bytes to be reported later in dep_link_up */ - if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) { - ndev->remote_gb_len = 0; - - if (ntf.activation_params_len > 0) { - /* ATR_RES general bytes at offset 15 */ - ndev->remote_gb_len = min_t(__u8, - (ntf.activation_params - .poll_nfc_dep.atr_res_len - - NFC_ATR_RES_GT_OFFSET), - NFC_MAX_GT_LEN); - memcpy(ndev->remote_gb, - (ntf.activation_params.poll_nfc_dep - .atr_res + NFC_ATR_RES_GT_OFFSET), - ndev->remote_gb_len); - } - } } if (atomic_read(&ndev->state) == NCI_DISCOVERY) { diff --git a/trunk/net/nfc/nci/rsp.c b/trunk/net/nfc/nci/rsp.c index dd072f38ad00..3003c3390e49 100644 --- a/trunk/net/nfc/nci/rsp.c +++ b/trunk/net/nfc/nci/rsp.c @@ -119,16 +119,6 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) nci_req_complete(ndev, rsp_1->status); } -static void nci_core_set_config_rsp_packet(struct nci_dev *ndev, - struct sk_buff *skb) -{ - struct nci_core_set_config_rsp *rsp = (void *) skb->data; - - pr_debug("status 0x%x\n", rsp->status); - - nci_req_complete(ndev, rsp->status); -} - static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) { @@ -204,10 +194,6 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) nci_core_init_rsp_packet(ndev, skb); break; - case NCI_OP_CORE_SET_CONFIG_RSP: - nci_core_set_config_rsp_packet(ndev, skb); - break; - case NCI_OP_RF_DISCOVER_MAP_RSP: nci_rf_disc_map_rsp_packet(ndev, skb); break; diff --git a/trunk/net/nfc/netlink.c b/trunk/net/nfc/netlink.c index c1b5285cbde7..4bbb70e32d1e 100644 --- a/trunk/net/nfc/netlink.c +++ b/trunk/net/nfc/netlink.c @@ -761,63 +761,31 @@ static struct genl_ops nfc_genl_ops[] = { }, }; - -struct urelease_work { - struct work_struct w; - int portid; -}; - -static void nfc_urelease_event_work(struct work_struct *work) +static int nfc_genl_rcv_nl_event(struct notifier_block *this, + unsigned long event, void *ptr) { - struct urelease_work *w = container_of(work, struct urelease_work, w); + struct netlink_notify *n = ptr; struct class_dev_iter iter; struct nfc_dev *dev; - pr_debug("portid %d\n", w->portid); + if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC) + goto out; - mutex_lock(&nfc_devlist_mutex); + pr_debug("NETLINK_URELEASE event from id %d\n", n->portid); nfc_device_iter_init(&iter); dev = nfc_device_iter_next(&iter); while (dev) { - mutex_lock(&dev->genl_data.genl_data_mutex); - - if (dev->genl_data.poll_req_portid == w->portid) { + if (dev->genl_data.poll_req_portid == n->portid) { nfc_stop_poll(dev); dev->genl_data.poll_req_portid = 0; } - - mutex_unlock(&dev->genl_data.genl_data_mutex); - dev = nfc_device_iter_next(&iter); } nfc_device_iter_exit(&iter); - mutex_unlock(&nfc_devlist_mutex); - - kfree(w); -} - -static int nfc_genl_rcv_nl_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct netlink_notify *n = ptr; - struct urelease_work *w; - - if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC) - goto out; - - pr_debug("NETLINK_URELEASE event from id %d\n", n->portid); - - w = kmalloc(sizeof(*w), GFP_ATOMIC); - if (w) { - INIT_WORK((struct work_struct *) w, nfc_urelease_event_work); - w->portid = n->portid; - schedule_work((struct work_struct *) w); - } - out: return NOTIFY_DONE; } diff --git a/trunk/net/rfkill/core.c b/trunk/net/rfkill/core.c index a5c952741279..c275bad12068 100644 --- a/trunk/net/rfkill/core.c +++ b/trunk/net/rfkill/core.c @@ -270,7 +270,6 @@ static bool __rfkill_set_hw_state(struct rfkill *rfkill, static void rfkill_set_block(struct rfkill *rfkill, bool blocked) { unsigned long flags; - bool prev, curr; int err; if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) @@ -285,8 +284,6 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) rfkill->ops->query(rfkill, rfkill->data); spin_lock_irqsave(&rfkill->lock, flags); - prev = rfkill->state & RFKILL_BLOCK_SW; - if (rfkill->state & RFKILL_BLOCK_SW) rfkill->state |= RFKILL_BLOCK_SW_PREV; else @@ -316,13 +313,10 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) } rfkill->state &= ~RFKILL_BLOCK_SW_SETCALL; rfkill->state &= ~RFKILL_BLOCK_SW_PREV; - curr = rfkill->state & RFKILL_BLOCK_SW; spin_unlock_irqrestore(&rfkill->lock, flags); rfkill_led_trigger_event(rfkill); - - if (prev != curr) - rfkill_event(rfkill); + rfkill_event(rfkill); } #ifdef CONFIG_RFKILL_INPUT diff --git a/trunk/net/sched/em_meta.c b/trunk/net/sched/em_meta.c index 7c3de6ffa516..4ab6e3325573 100644 --- a/trunk/net/sched/em_meta.c +++ b/trunk/net/sched/em_meta.c @@ -461,7 +461,7 @@ META_COLLECTOR(int_sk_sndtimeo) META_COLLECTOR(int_sk_sendmsg_off) { SKIP_NONLOCAL(skb); - dst->value = skb->sk->sk_frag.offset; + dst->value = skb->sk->sk_sndmsg_off; } META_COLLECTOR(int_sk_write_pend) diff --git a/trunk/net/sched/sch_drr.c b/trunk/net/sched/sch_drr.c index 71e50c80315f..9ce0b4fe23ff 100644 --- a/trunk/net/sched/sch_drr.c +++ b/trunk/net/sched/sch_drr.c @@ -352,7 +352,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct drr_sched *q = qdisc_priv(sch); struct drr_class *cl; - int err = 0; + int err; cl = drr_classify(skb, sch, &err); if (cl == NULL) { diff --git a/trunk/net/sched/sch_qfq.c b/trunk/net/sched/sch_qfq.c index f0dd83cff906..e4723d31fdd5 100644 --- a/trunk/net/sched/sch_qfq.c +++ b/trunk/net/sched/sch_qfq.c @@ -865,10 +865,7 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl) if (mask) { struct qfq_group *next = qfq_ffs(q, mask); if (qfq_gt(roundedF, next->F)) { - if (qfq_gt(limit, next->F)) - cl->S = next->F; - else /* preserve timestamp correctness */ - cl->S = limit; + cl->S = next->F; return; } } @@ -881,7 +878,7 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct qfq_sched *q = qdisc_priv(sch); struct qfq_class *cl; - int err = 0; + int err; cl = qfq_classify(skb, sch, &err); if (cl == NULL) { diff --git a/trunk/net/socket.c b/trunk/net/socket.c index 80dc7e84b046..c641549a13e2 100644 --- a/trunk/net/socket.c +++ b/trunk/net/socket.c @@ -2600,6 +2600,12 @@ static int __init sock_init(void) if (err) goto out; + /* + * Initialize sock SLAB cache. + */ + + sk_init(); + /* * Initialize skbuff SLAB cache */ diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index 8016fee0752b..ec7fcee5bad6 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -612,17 +612,6 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) } EXPORT_SYMBOL(cfg80211_del_sta); -void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, - enum nl80211_connect_failed_reason reason, - gfp_t gfp) -{ - struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - - nl80211_send_conn_failed_event(rdev, dev, mac_addr, reason, gfp); -} -EXPORT_SYMBOL(cfg80211_conn_failed); - struct cfg80211_mgmt_registration { struct list_head list; diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 0418a6d5c1a6..139946dc8020 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -8364,40 +8364,6 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } -void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *mac_addr, - enum nl80211_connect_failed_reason reason, - gfp_t gfp) -{ - struct sk_buff *msg; - void *hdr; - - msg = nlmsg_new(NLMSG_GOODSIZE, gfp); - if (!msg) - return; - - hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED); - if (!hdr) { - nlmsg_free(msg); - return; - } - - if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || - nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) || - nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason)) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - - genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, - nl80211_mlme_mcgrp.id, gfp); - return; - - nla_put_failure: - genlmsg_cancel(msg, hdr); - nlmsg_free(msg); -} - static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, const u8 *addr, gfp_t gfp) { diff --git a/trunk/net/wireless/nl80211.h b/trunk/net/wireless/nl80211.h index f6153516068c..9f2616fffb40 100644 --- a/trunk/net/wireless/nl80211.h +++ b/trunk/net/wireless/nl80211.h @@ -91,11 +91,6 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *mac_addr, gfp_t gfp); -void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *mac_addr, - enum nl80211_connect_failed_reason reason, - gfp_t gfp); - int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, u32 nlpid, int freq, int sig_dbm, diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index 3b8cbbc214db..1ad04e54014c 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -350,9 +350,6 @@ static void reg_regdb_search(struct work_struct *work) struct reg_regdb_search_request *request; const struct ieee80211_regdomain *curdom, *regdom; int i, r; - bool set_reg = false; - - mutex_lock(&cfg80211_mutex); mutex_lock(®_regdb_search_mutex); while (!list_empty(®_regdb_search_list)) { @@ -368,7 +365,9 @@ static void reg_regdb_search(struct work_struct *work) r = reg_copy_regd(®dom, curdom); if (r) break; - set_reg = true; + mutex_lock(&cfg80211_mutex); + set_regdom(regdom); + mutex_unlock(&cfg80211_mutex); break; } } @@ -376,11 +375,6 @@ static void reg_regdb_search(struct work_struct *work) kfree(request); } mutex_unlock(®_regdb_search_mutex); - - if (set_reg) - set_regdom(regdom); - - mutex_unlock(&cfg80211_mutex); } static DECLARE_WORK(reg_regdb_work, reg_regdb_search); @@ -510,11 +504,9 @@ static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range, * * This lets us know if a specific frequency rule is or is not relevant to * a specific frequency's band. Bands are device specific and artificial - * definitions (the "2.4 GHz band", the "5 GHz band" and the "60GHz band"), - * however it is safe for now to assume that a frequency rule should not be - * part of a frequency's band if the start freq or end freq are off by more - * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 10 GHz for the - * 60 GHz band. + * definitions (the "2.4 GHz band" and the "5 GHz band"), however it is + * safe for now to assume that a frequency rule should not be part of a + * frequency's band if the start freq or end freq are off by more than 2 GHz. * This resolution can be lowered and should be considered as we add * regulatory rule support for other "bands". **/ @@ -522,16 +514,9 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, u32 freq_khz) { #define ONE_GHZ_IN_KHZ 1000000 - /* - * From 802.11ad: directional multi-gigabit (DMG): - * Pertaining to operation in a frequency band containing a channel - * with the Channel starting frequency above 45 GHz. - */ - u32 limit = freq_khz > 45 * ONE_GHZ_IN_KHZ ? - 10 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ; - if (abs(freq_khz - freq_range->start_freq_khz) <= limit) + if (abs(freq_khz - freq_range->start_freq_khz) <= (2 * ONE_GHZ_IN_KHZ)) return true; - if (abs(freq_khz - freq_range->end_freq_khz) <= limit) + if (abs(freq_khz - freq_range->end_freq_khz) <= (2 * ONE_GHZ_IN_KHZ)) return true; return false; #undef ONE_GHZ_IN_KHZ @@ -2208,6 +2193,7 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd) static int __set_regdom(const struct ieee80211_regdomain *rd) { const struct ieee80211_regdomain *intersected_rd = NULL; + struct cfg80211_registered_device *rdev = NULL; struct wiphy *request_wiphy; /* Some basic sanity checks first */ @@ -2319,7 +2305,24 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) return 0; } - return -EINVAL; + if (!intersected_rd) + return -EINVAL; + + rdev = wiphy_to_dev(request_wiphy); + + rdev->country_ie_alpha2[0] = rd->alpha2[0]; + rdev->country_ie_alpha2[1] = rd->alpha2[1]; + rdev->env = last_request->country_ie_env; + + BUG_ON(intersected_rd == rd); + + kfree(rd); + rd = NULL; + + reset_regdomains(false); + cfg80211_regdomain = intersected_rd; + + return 0; } diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index f4e0a6a148a5..741a32aa512e 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -602,7 +602,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) xfrm_pol_hold(policy); net->xfrm.policy_count[dir]++; atomic_inc(&flow_cache_genid); - rt_genid_bump(net); if (delpol) __xfrm_policy_unlink(delpol, dir); policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir); @@ -1781,7 +1780,7 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family, if (!afinfo) { dst_release(dst_orig); - return ERR_PTR(-EINVAL); + ret = ERR_PTR(-EINVAL); } else { ret = afinfo->blackhole_route(net, dst_orig); } diff --git a/trunk/net/xfrm/xfrm_user.c b/trunk/net/xfrm/xfrm_user.c index 94a2a1f726f9..5d6eb4b3c089 100644 --- a/trunk/net/xfrm/xfrm_user.c +++ b/trunk/net/xfrm/xfrm_user.c @@ -123,21 +123,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p, struct nlattr **attrs) { struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; - struct xfrm_replay_state_esn *rs; - if (p->flags & XFRM_STATE_ESN) { - if (!rt) - return -EINVAL; - - rs = nla_data(rt); - - if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) - return -EINVAL; - - if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && - nla_len(rt) != sizeof(*rs)) - return -EINVAL; - } + if ((p->flags & XFRM_STATE_ESN) && !rt) + return -EINVAL; if (!rt) return 0; @@ -382,15 +370,14 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es struct nlattr *rp) { struct xfrm_replay_state_esn *up; - int ulen; if (!replay_esn || !rp) return 0; up = nla_data(rp); - ulen = xfrm_replay_state_esn_len(up); - if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen) + if (xfrm_replay_state_esn_len(replay_esn) != + xfrm_replay_state_esn_len(up)) return -EINVAL; return 0; @@ -401,28 +388,22 @@ static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn struct nlattr *rta) { struct xfrm_replay_state_esn *p, *pp, *up; - int klen, ulen; if (!rta) return 0; up = nla_data(rta); - klen = xfrm_replay_state_esn_len(up); - ulen = nla_len(rta) >= klen ? klen : sizeof(*up); - p = kzalloc(klen, GFP_KERNEL); + p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); if (!p) return -ENOMEM; - pp = kzalloc(klen, GFP_KERNEL); + pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); if (!pp) { kfree(p); return -ENOMEM; } - memcpy(p, up, ulen); - memcpy(pp, up, ulen); - *replay_esn = p; *preplay_esn = pp; @@ -461,11 +442,10 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * * somehow made shareable and move it to xfrm_state.c - JHS * */ -static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs, - int update_esn) +static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) { struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; - struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL; + struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; @@ -575,7 +555,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, goto error; /* override default values from above */ - xfrm_update_ae_params(x, attrs, 0); + xfrm_update_ae_params(x, attrs); return x; @@ -709,7 +689,6 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) { - memset(p, 0, sizeof(*p)); memcpy(&p->id, &x->id, sizeof(p->id)); memcpy(&p->sel, &x->sel, sizeof(p->sel)); memcpy(&p->lft, &x->lft, sizeof(p->lft)); @@ -763,7 +742,7 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb) return -EMSGSIZE; algo = nla_data(nla); - strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name)); + strcpy(algo->alg_name, auth->alg_name); memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8); algo->alg_key_len = auth->alg_key_len; @@ -899,7 +878,6 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, { struct xfrm_dump_info info; struct sk_buff *skb; - int err; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!skb) @@ -910,10 +888,9 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, info.nlmsg_seq = seq; info.nlmsg_flags = 0; - err = dump_one_state(x, 0, &info); - if (err) { + if (dump_one_state(x, 0, &info)) { kfree_skb(skb); - return ERR_PTR(err); + return NULL; } return skb; @@ -1340,7 +1317,6 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir) { - memset(p, 0, sizeof(*p)); memcpy(&p->sel, &xp->selector, sizeof(p->sel)); memcpy(&p->lft, &xp->lft, sizeof(p->lft)); memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft)); @@ -1445,7 +1421,6 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) struct xfrm_user_tmpl *up = &vec[i]; struct xfrm_tmpl *kp = &xp->xfrm_vec[i]; - memset(up, 0, sizeof(*up)); memcpy(&up->id, &kp->id, sizeof(up->id)); up->family = kp->encap_family; memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr)); @@ -1571,7 +1546,6 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, { struct xfrm_dump_info info; struct sk_buff *skb; - int err; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!skb) @@ -1582,10 +1556,9 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, info.nlmsg_seq = seq; info.nlmsg_flags = 0; - err = dump_one_policy(xp, dir, 0, &info); - if (err) { + if (dump_one_policy(xp, dir, 0, &info) < 0) { kfree_skb(skb); - return ERR_PTR(err); + return NULL; } return skb; @@ -1849,7 +1822,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, goto out; spin_lock_bh(&x->lock); - xfrm_update_ae_params(x, attrs, 1); + xfrm_update_ae_params(x, attrs); spin_unlock_bh(&x->lock); c.event = nlh->nlmsg_type; diff --git a/trunk/scripts/Makefile.fwinst b/trunk/scripts/Makefile.fwinst index 4d908d16c035..c3f69ae275d1 100644 --- a/trunk/scripts/Makefile.fwinst +++ b/trunk/scripts/Makefile.fwinst @@ -27,7 +27,7 @@ endif installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw)) installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) -installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./ +installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/. # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work. PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs @@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@) $(installed-fw-dirs): $(call cmd,mkdir) -$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %) +$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%) $(call cmd,install) PHONY += __fw_install __fw_modinst FORCE diff --git a/trunk/scripts/checksyscalls.sh b/trunk/scripts/checksyscalls.sh index fd8fa9aa7c4e..d24810fc6af6 100755 --- a/trunk/scripts/checksyscalls.sh +++ b/trunk/scripts/checksyscalls.sh @@ -200,7 +200,7 @@ EOF syscall_list() { grep '^[0-9]' "$1" | sort -n | ( while read nr abi name entry ; do - cat <dev, "audmux internal port setup failed\n"); return ret; } - ret = imx_audmux_v2_configure_port(ext_port, + imx_audmux_v2_configure_port(ext_port, IMX_AUDMUX_V2_PTCR_SYN, IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); if (ret) { diff --git a/trunk/sound/soc/omap/am3517evm.c b/trunk/sound/soc/omap/am3517evm.c index df65f98211ec..009533ab8d18 100644 --- a/trunk/sound/soc/omap/am3517evm.c +++ b/trunk/sound/soc/omap/am3517evm.c @@ -59,7 +59,7 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, return ret; } - ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, + snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, SND_SOC_CLOCK_IN); if (ret < 0) { printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); diff --git a/trunk/sound/soc/samsung/dma.c b/trunk/sound/soc/samsung/dma.c index b70964ea448c..f3ebc38c10fe 100644 --- a/trunk/sound/soc/samsung/dma.c +++ b/trunk/sound/soc/samsung/dma.c @@ -34,7 +34,9 @@ static const struct snd_pcm_hardware dma_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U8 | @@ -246,11 +248,15 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->state |= ST_RUNNING; prtd->params->ops->trigger(prtd->params->ch); break; case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: prtd->state &= ~ST_RUNNING; prtd->params->ops->stop(prtd->params->ch); break; diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index f90139b5f50d..dd7c49fafd75 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -291,11 +291,8 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, if (dapm->codec->driver->set_bias_level) ret = dapm->codec->driver->set_bias_level(dapm->codec, level); - else - dapm->bias_level = level; - } else if (!card || dapm != &card->dapm) { + } else dapm->bias_level = level; - } if (ret != 0) goto out; diff --git a/trunk/sound/soc/spear/spear_pcm.c b/trunk/sound/soc/spear/spear_pcm.c index 8c7f23729446..97c2cac8e92c 100644 --- a/trunk/sound/soc/spear/spear_pcm.c +++ b/trunk/sound/soc/spear/spear_pcm.c @@ -138,7 +138,7 @@ static void spear_pcm_free(struct snd_pcm *pcm) continue; buf = &substream->dma_buffer; - if (!buf || !buf->area) + if (!buf && !buf->area) continue; dma_free_writecombine(pcm->card->dev, buf->bytes, diff --git a/trunk/sound/soc/tegra/tegra_alc5632.c b/trunk/sound/soc/tegra/tegra_alc5632.c index 76cb1b363b71..e463529b38bb 100644 --- a/trunk/sound/soc/tegra/tegra_alc5632.c +++ b/trunk/sound/soc/tegra/tegra_alc5632.c @@ -89,6 +89,7 @@ static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = { .name = "Headset detection", .report = SND_JACK_HEADSET, .debounce_time = 150, + .invert = 1, }; static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = { diff --git a/trunk/sound/soc/tegra/tegra_pcm.c b/trunk/sound/soc/tegra/tegra_pcm.c index 8d6900c1ee47..5658bcec1931 100644 --- a/trunk/sound/soc/tegra/tegra_pcm.c +++ b/trunk/sound/soc/tegra/tegra_pcm.c @@ -334,11 +334,11 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slave_config.dst_addr = dmap->addr; - slave_config.dst_maxburst = 4; + slave_config.src_maxburst = 0; } else { slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slave_config.src_addr = dmap->addr; - slave_config.src_maxburst = 4; + slave_config.dst_maxburst = 0; } slave_config.slave_id = dmap->req_sel; diff --git a/trunk/sound/soc/ux500/ux500_msp_i2s.c b/trunk/sound/soc/ux500/ux500_msp_i2s.c index eb85113d472a..5c472f335a64 100644 --- a/trunk/sound/soc/ux500/ux500_msp_i2s.c +++ b/trunk/sound/soc/ux500/ux500_msp_i2s.c @@ -663,6 +663,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, struct ux500_msp **msp_p, struct msp_i2s_platform_data *platform_data) { + int ret = 0; struct resource *res = NULL; struct i2s_controller *i2s_cont; struct ux500_msp *msp; @@ -684,14 +685,15 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, if (res == NULL) { dev_err(&pdev->dev, "%s: ERROR: Unable to get resource!\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto err_res; } - msp->registers = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); + msp->registers = ioremap(res->start, (res->end - res->start + 1)); if (msp->registers == NULL) { dev_err(&pdev->dev, "%s: ERROR: ioremap failed!\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto err_res; } msp->msp_state = MSP_STATE_IDLE; @@ -703,7 +705,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, dev_err(&pdev->dev, "%s: ERROR: Failed to allocate I2S-controller!\n", __func__); - return -ENOMEM; + goto err_i2s_cont; } i2s_cont->dev.parent = &pdev->dev; i2s_cont->data = (void *)msp; @@ -714,6 +716,14 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, msp->i2s_cont = i2s_cont; return 0; + +err_i2s_cont: + iounmap(msp->registers); + +err_res: + devm_kfree(&pdev->dev, msp); + + return ret; } void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, @@ -722,6 +732,11 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id); device_unregister(&msp->i2s_cont->dev); + devm_kfree(&pdev->dev, msp->i2s_cont); + + iounmap(msp->registers); + + devm_kfree(&pdev->dev, msp); } MODULE_LICENSE("GPL v2"); diff --git a/trunk/sound/usb/endpoint.c b/trunk/sound/usb/endpoint.c index 060dccb9ec75..d6e2bb49c59c 100644 --- a/trunk/sound/usb/endpoint.c +++ b/trunk/sound/usb/endpoint.c @@ -197,13 +197,7 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep, /* no data provider, so send silence */ unsigned int offs = 0; for (i = 0; i < ctx->packets; ++i) { - int counts; - - if (ctx->packet_size[i]) - counts = ctx->packet_size[i]; - else - counts = snd_usb_endpoint_next_packet_size(ep); - + int counts = ctx->packet_size[i]; urb->iso_frame_desc[i].offset = offs * ep->stride; urb->iso_frame_desc[i].length = counts * ep->stride; offs += counts;